@aztec/ivc-integration 3.0.3 → 3.9.9-nightly.20260312

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.
@@ -4,85 +4,85 @@ pragma solidity >=0.8.21;
4
4
 
5
5
  uint256 constant N = 16777216;
6
6
  uint256 constant LOG_N = 24;
7
- uint256 constant NUMBER_OF_PUBLIC_INPUTS = 17;
8
- uint256 constant VK_HASH = 0x2483e4516597c18a018591468c70f9cf8aae18afe48a8dff59e99657d367b063;
7
+ uint256 constant NUMBER_OF_PUBLIC_INPUTS = 9;
8
+ uint256 constant VK_HASH = 0x1a71c9c8e8d1fc37789326bbf84db5728e523d1663d64a3ee4d907db31280798;
9
9
  library HonkVerificationKey {
10
10
  function loadVerificationKey() internal pure returns (Honk.VerificationKey memory) {
11
11
  Honk.VerificationKey memory vk = Honk.VerificationKey({
12
12
  circuitSize: uint256(16777216),
13
13
  logCircuitSize: uint256(24),
14
- publicInputsSize: uint256(17),
14
+ publicInputsSize: uint256(9),
15
15
  ql: Honk.G1Point({
16
- x: uint256(0x0f2365b105ff53384a1fd8d7a27c5288a8100554378f35a6b344cd9ce8adad85),
17
- y: uint256(0x03e6c96c0bc572a5b3df41a4871dc2c2bae22ac5d0f07d046bb96bee05835f85)
16
+ x: uint256(0x288949ddd65c505eb5cc75f154e5758f88ffca8d2b27ecec1a8c18d64836555e),
17
+ y: uint256(0x16bdc5f6b2acfec698224a75fb369f408f10203d39d18c59f1e7fd2a06cd203e)
18
18
  }),
19
19
  qr: Honk.G1Point({
20
- x: uint256(0x004cb36247e12fb32b73a4ebece2be052889df91bb4af49dfe8a74a53865ecc3),
21
- y: uint256(0x17a1d0af10c38a99db2ad668f56c9642722b05b0ea72ed99c146ffceeda7a334)
20
+ x: uint256(0x0f00e9b07cdc3cb5ec6c7f0c3f015d52b77d22309cb6ce0231a4969c4ac47488),
21
+ y: uint256(0x173daa0ad01139b438315c03c09114c7054ed90ff4562466afb6e2cc48d69eae)
22
22
  }),
23
23
  qo: Honk.G1Point({
24
- x: uint256(0x1796eb7073a560ad27262a9fcccd8cc6a7c8ac3c5667c343d332c745ddd49cdf),
25
- y: uint256(0x2710cb416b75e315229256987e3c736f6aa9e6e3d1f7394828e81b93ba058a93)
24
+ x: uint256(0x2158a434ef091cbe48d362fda5c78de82eaaac1227a0c411ea21ad7c7d09bb89),
25
+ y: uint256(0x11e9f2ece557a9ab50b059decabaa2c3e102080b7389aa51335094c527a4399b)
26
26
  }),
27
27
  q4: Honk.G1Point({
28
- x: uint256(0x29415184cae246d7e7beeb3d707ae40c762426aa34e3ac9d22eda508b422adb3),
29
- y: uint256(0x042112fe467bd4fd695476676773a444cb16423c026ff2eb57077a29d293b47c)
28
+ x: uint256(0x0b4c24c473fadd17b6fc761b52fc51cabd6dfb6b93a889128f7d5443d76b4e37),
29
+ y: uint256(0x2bcbb260096016d41e7b099758e6c7a4b2487a30728fa877f64163da404d2aa6)
30
30
  }),
31
31
  qm: Honk.G1Point({
32
- x: uint256(0x0e93587de243211bc0e46e11a1e7e80694eee62981bbea775277d85b2889cda5),
33
- y: uint256(0x0b508346fe7fc422cf003ca50511285b28b8310e5ce3d764317ded0f9fc6ffde)
32
+ x: uint256(0x305785ae74b36fc97f5cfbfcd19e965f14c3cb5fc07a866b4da8c40dfa43ea09),
33
+ y: uint256(0x1c618b8fb74db18bb65237cd45de3060ae7abd8931f5d6fbc0a3d18019f9a34c)
34
34
  }),
35
35
  qc: Honk.G1Point({
36
- x: uint256(0x28703227d883dab576898b7325c6b9f0fbc834481b2993d7f23f8132e9daf1db),
37
- y: uint256(0x2ad4bd924ebf2d393df34f5f6d5faa3dbd8a3285c4756e600e5cfe083f51a4e3)
36
+ x: uint256(0x1e7d370a010cbec0e4a7a5be0832a59a0ed151216aa2ef780e40945770f04256),
37
+ y: uint256(0x19645746fcec15c93f0b8f620fbaf63b2d973d174b52ac8dc006b0292bc4d75a)
38
38
  }),
39
39
  qLookup: Honk.G1Point({
40
- x: uint256(0x0c4032c3079594eb75a8449d3d5ce8bc3661650d53f9b24d923d8f404cb0bbc9),
41
- y: uint256(0x1084d709650356d40f0158fd6da81f54eb5fe796a0ca89441369b7c24301f851)
40
+ x: uint256(0x22011c91613251ef53fd12a397e4bd6165b1ed309dcd94b33ac4226d34b68889),
41
+ y: uint256(0x1fb02875a3542a3a6f4426ad912b70cf32b444a8e439701da6e8e7b30029cfc7)
42
42
  }),
43
43
  qArith: Honk.G1Point({
44
- x: uint256(0x035bf72586d41e96e39b9a1b5c87f4c15931cf828fa9dbdd04d7fcf7a2c9b820),
45
- y: uint256(0x2d1c89402419dae4ab086f37587eaa261a4f799114081a9e7c6dfa0cdd681dc9)
44
+ x: uint256(0x1d87e7db98f2289def77fcd6917b3195a04c8ea4fba2fbecb4953d53e2a5fa5e),
45
+ y: uint256(0x1e747aa5ce9c23534fba30d6fb86e148f55ff741cdc40aa72669b48fae5e78da)
46
46
  }),
47
47
  qDeltaRange: Honk.G1Point({
48
- x: uint256(0x10cc9f130a3617b8ba1d4c7f8a4ecf772b76948dad571e47b06aea5f6e5e82db),
49
- y: uint256(0x1062815b19b50f9736cbe3849bf00f9957947bf27f424f304f8097bbf3358fdd)
48
+ x: uint256(0x197382111c5e19efd384fad7b441ab910eea06a90e613c0ac1d3558d5d1fe9bb),
49
+ y: uint256(0x2409d8e704a1df2a931db78f4b9eff415259f325e2c1d91752018ca1367bc813)
50
50
  }),
51
51
  qElliptic: Honk.G1Point({
52
- x: uint256(0x15a4f05d00dfd0db51eb5133fbfe3b8e0c67fc6adec433a2eed788991e11159f),
53
- y: uint256(0x1ca5a9a9bcbf26d428feb2552757a17d9820c1ae18e9cd6c7ac5bdbebafb838f)
52
+ x: uint256(0x2f7bf7a96beccc2dcb1c979e895a5cf553347e85d3f09ac4ad25968c48ee6c0f),
53
+ y: uint256(0x0b9eb2604a17d6ee22545ecefc418886ee29c45e1f367a73781af51b70b5e59a)
54
54
  }),
55
55
  qMemory: Honk.G1Point({
56
- x: uint256(0x1b2ddb367c92012e81f0cf6fd8b057d254c4fe79472a2bcdcec684d14720da01),
57
- y: uint256(0x00fded1abfb60e5e7ba4e0da120de9d8e52bf726c44f8d331f46673b1fde5cd3)
56
+ x: uint256(0x067081ee7301cf94893b575b8a4607a50631612578b3230b0f63434e6ec1dcf3),
57
+ y: uint256(0x12e2288cdb86fd9caa98689e3ad9926b0372d1e7afeeb1ec6f7b251a176eb3e1)
58
58
  }),
59
59
  qNnf: Honk.G1Point({
60
- x: uint256(0x15aa8a2883f91db5b8334efa999e7a1686ed95bc25d4802eb60121f8984a8c51),
61
- y: uint256(0x10f5de1ef49ecd1db3ebdb997bb4795d34377fec527e2c048e934f6c0a88572c)
60
+ x: uint256(0x303e26adafa2a01b02f559580ab06f571fe0f80473552ea7f4a47255af7b25f3),
61
+ y: uint256(0x2f599def60b1f4640366dba9daaf25de7a311eed3243dd96004ef5cb76dd4eef)
62
62
  }),
63
63
  qPoseidon2External: Honk.G1Point({
64
- x: uint256(0x228271d918164c6f35cbb191a79841195f4dd0ca862772b3b35999ad275c9a0e),
65
- y: uint256(0x1e215612b6dd1be8e45f8ddb9d2de66ae3f16caa45356a8bac12136e8bbe986c)
64
+ x: uint256(0x26c42fb5290e1f109c68ae1aadb78005efbe391925d37ff2682eb2fb9f673d81),
65
+ y: uint256(0x23d32838bb651192c72a84f8d35ad9ed23bfc60bd6a95aafe5f400ac79bb91a6)
66
66
  }),
67
67
  qPoseidon2Internal: Honk.G1Point({
68
- x: uint256(0x20be4e3e2847c2166ff19287744f61196747cbd2975749f04cbbd94ed903e56e),
69
- y: uint256(0x00ba35bc0241f49319ceae8027122eb462af14ca679fbfdae1f259fe7ea46d6a)
68
+ x: uint256(0x0e257562358c0fa333e2e92fb24893b10b6606582657ac902463c4125a8d76b4),
69
+ y: uint256(0x0a45aedd100c830266aa7501650f16d4c1a340da32528e2dc0ffcfe01de89c65)
70
70
  }),
71
71
  s1: Honk.G1Point({
72
- x: uint256(0x18c9d69eb064aa58dccfdb64028d880dab96a6c48401c1e5990d4ea44613ba1a),
73
- y: uint256(0x0dad8177318828acebf73d7bc51b9e36a0b561750286fb59628e7d496532a11b)
72
+ x: uint256(0x157c4a46714f7cc4bd0065ac8726ead6d925e1c3e2cb03ec167bde135d933eeb),
73
+ y: uint256(0x191e130de881a7b6a3560a6dc7f8f517abcc324c5f16b8e4dc901d5079ec7387)
74
74
  }),
75
75
  s2: Honk.G1Point({
76
- x: uint256(0x22de4ef2c6e945f99cb1adc27a1c526e0ce618404cbeb51895898fffe9818667),
77
- y: uint256(0x21a55d5432ee5e4114bbefcaf467a2f0175ed72666b9a5490c8c39d7b5800f3a)
76
+ x: uint256(0x0d02a27696ba0a08b32422113dc489b15acc111cb2fcd7f674ef4b903adcbdb3),
77
+ y: uint256(0x03499c1fd603f04963deab2fdbb152e7d8f88267d6ca8c817eea2643e608de29)
78
78
  }),
79
79
  s3: Honk.G1Point({
80
- x: uint256(0x25f6f34984d2cdd0ca61060a1cec0907db393f2fb05c226b6a09c46a074c785a),
81
- y: uint256(0x07e4d48a999a872265b418345cfcc50712f82266d716014aa056dbacbe6d0513)
80
+ x: uint256(0x19c00dd88d170187c1717dfa303fe1c20604decf14cc58c4d6fe9ab346ae3f67),
81
+ y: uint256(0x0e3991d6fd47060ba758b4ed58736ffd3f082af15af7b84fafe5041b568dcff2)
82
82
  }),
83
83
  s4: Honk.G1Point({
84
- x: uint256(0x1c7889c9dcf7801029523cc960a7892d22ca95247f38b42adc27931bdf8ecfd0),
85
- y: uint256(0x29f693a30e9e62397ed0fe86485d3c2a2f9725f294402804915bcedf1a89895e)
84
+ x: uint256(0x2ddedcc10b1b78151f4638978bc1ed9ceafa34911d7c8a2ffcdecc092f5f53bd),
85
+ y: uint256(0x2fee038cad71230c95a0497bd2a116171a431193a214d5a9677570fa45de2fda)
86
86
  }),
87
87
  t1: Honk.G1Point({
88
88
  x: uint256(0x099e3bd5a0a00ab7fe18040105b9b395b5d8b7b4a63b05df652b0d10ef146d26),
@@ -93,36 +93,36 @@ library HonkVerificationKey {
93
93
  y: uint256(0x305e8992b148eedb22e6e992077a84482141c7ebe42000a1d58ccb74381f6d19)
94
94
  }),
95
95
  t3: Honk.G1Point({
96
- x: uint256(0x061f64497996e8915722501e9e367938ed8da2375186b518c7345c60b1134b2d),
97
- y: uint256(0x1b84d38339321f405ebaf6a2f830842ad3d7cb59792e11c0d2691f317fd50e6e)
96
+ x: uint256(0x16465a5ccbb550cd2c63bd58116fe47c86847618681dc29d8a9363ab7c40e1c3),
97
+ y: uint256(0x2e24d420fbf9508ed31de692db477b439973ac12d7ca796d6fe98ca40e6ca6b7)
98
98
  }),
99
99
  t4: Honk.G1Point({
100
100
  x: uint256(0x043d063b130adfb37342af45d0155a28edd1a7e46c840d9c943fdf45521c64ce),
101
101
  y: uint256(0x261522c4089330646aff96736194949330952ae74c573d1686d9cb4a00733854)
102
102
  }),
103
103
  id1: Honk.G1Point({
104
- x: uint256(0x0cfc6d916a8ee137548e5f03368fe440a12b2353526e4045da57928d9d3ea1ac),
105
- y: uint256(0x057c503fcaabdad32d220fe39de0802e9d02870a6198399519377ee38ac92f7d)
104
+ x: uint256(0x11a02b4dd65f30c8d3b70888267f766e6abaaa0a1a5ad0bfa8cb1b597fedc630),
105
+ y: uint256(0x195cb3d252708ee60a385f0a3a84167322910971be20715e2965a4d97c1d1084)
106
106
  }),
107
107
  id2: Honk.G1Point({
108
- x: uint256(0x04a3281f7984a62b53e3c00e9de68886175fc455aae5bab2b4334cdd67ea8676),
109
- y: uint256(0x06400420abfaae2fca0debeafe5091cfe1bf4c7432d288ebdde64242331a20c3)
108
+ x: uint256(0x2a775e6191621460b6ae8f22d1cef5f92ec91bf820478d9619fc74d4e2956801),
109
+ y: uint256(0x057c47f7fa5fdfe685bd62595390454071e5749841dbabb0bcd45aee00ac9af7)
110
110
  }),
111
111
  id3: Honk.G1Point({
112
- x: uint256(0x1d18e5659dc058966fa5fcfa0dcd1b6ef05ca88950525a91993530f1d082e938),
113
- y: uint256(0x1c7184cee4af54cd8bef5ff6401548a5b7485af396891ccbbf0237931e9d6a67)
112
+ x: uint256(0x2ae753680356fd3211ca6b4210fe2682ebacc40d78c1ac3319be365682860bbd),
113
+ y: uint256(0x18aa3b045ae71c20a8b673b91ccf5ea61ba25bff9c958f9bad138e7e126a257a)
114
114
  }),
115
115
  id4: Honk.G1Point({
116
- x: uint256(0x0fc51759c8595c1857c8d428fc89835b47fbd258425b365262ab87b6f21c025d),
117
- y: uint256(0x1e6cbebfe6e913fc4caace9df3a9b0ef9ee77f8f16ba00d31722b95707eaada6)
116
+ x: uint256(0x2e12e92c2de2ec043befd1cb502a2e48458c7ea1dc19243640df4f6ec699b0be),
117
+ y: uint256(0x12655a8e9a32a038c570a5c83aa5dabe77df900b5c78bab8a64a252de136cdfc)
118
118
  }),
119
119
  lagrangeFirst: Honk.G1Point({
120
120
  x: uint256(0x0000000000000000000000000000000000000000000000000000000000000001),
121
121
  y: uint256(0x0000000000000000000000000000000000000000000000000000000000000002)
122
122
  }),
123
123
  lagrangeLast: Honk.G1Point({
124
- x: uint256(0x0e48a3b860eeef2951502efcb4cb49994a7c3a80302a0ad1b9f13f64ac7d2053),
125
- y: uint256(0x0014bb3719e4eeb82182790fee5729aa3943e7091e74d4eaf61fb1d26205df2f)
124
+ x: uint256(0x04a0bdd0751a2184a98670fd8df17f372fac62b55691c8232c1484f51282cd7e),
125
+ y: uint256(0x121349b0521c633e5b12c42ec4f8cb0c1a3bdadcafe6350d901ae7cf13e7b5bd)
126
126
  })
127
127
  });
128
128
  return vk;
@@ -132,7 +132,32 @@ library HonkVerificationKey {
132
132
  pragma solidity ^0.8.27;
133
133
 
134
134
  interface IVerifier {
135
- function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external returns (bool);
135
+ function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool);
136
+ }
137
+
138
+ /**
139
+ * @notice Library of error codes
140
+ * @dev You can run `forge inspect Errors errors` to get the selectors for the optimised verifier
141
+ */
142
+ library Errors {
143
+ error ValueGeLimbMax();
144
+ error ValueGeGroupOrder();
145
+ error ValueGeFieldOrder();
146
+
147
+ error InvertOfZero();
148
+ error NotPowerOfTwo();
149
+ error ModExpFailed();
150
+
151
+ error ProofLengthWrong();
152
+ error ProofLengthWrongWithLogN(uint256 logN, uint256 actualLength, uint256 expectedLength);
153
+ error PublicInputsLengthWrong();
154
+ error SumcheckFailed();
155
+ error ShpleminiFailed();
156
+
157
+ error PointAtInfinity();
158
+
159
+ error ConsistencyCheckFailed();
160
+ error GeminiChallengeInSubgroup();
136
161
  }
137
162
 
138
163
  type Fr is uint256;
@@ -141,7 +166,6 @@ using {add as +} for Fr global;
141
166
  using {sub as -} for Fr global;
142
167
  using {mul as *} for Fr global;
143
168
 
144
- using {exp as ^} for Fr global;
145
169
  using {notEqual as !=} for Fr global;
146
170
  using {equal as ==} for Fr global;
147
171
 
@@ -156,26 +180,12 @@ Fr constant ZERO = Fr.wrap(0);
156
180
  // Instantiation
157
181
 
158
182
  library FrLib {
159
- function from(uint256 value) internal pure returns (Fr) {
160
- unchecked {
161
- return Fr.wrap(value % MODULUS);
162
- }
163
- }
164
-
165
- function fromBytes32(bytes32 value) internal pure returns (Fr) {
166
- unchecked {
167
- return Fr.wrap(uint256(value) % MODULUS);
168
- }
169
- }
170
-
171
- function toBytes32(Fr value) internal pure returns (bytes32) {
172
- unchecked {
173
- return bytes32(Fr.unwrap(value));
174
- }
175
- }
183
+ bytes4 internal constant FRLIB_MODEXP_FAILED_SELECTOR = 0xf8d61709;
176
184
 
177
185
  function invert(Fr value) internal view returns (Fr) {
178
186
  uint256 v = Fr.unwrap(value);
187
+ require(v != 0, Errors.InvertOfZero());
188
+
179
189
  uint256 result;
180
190
 
181
191
  // Call the modexp precompile to invert in the field
@@ -185,14 +195,15 @@ library FrLib {
185
195
  mstore(add(free, 0x20), 0x20)
186
196
  mstore(add(free, 0x40), 0x20)
187
197
  mstore(add(free, 0x60), v)
188
- mstore(add(free, 0x80), sub(MODULUS, 2))
198
+ mstore(add(free, 0x80), sub(MODULUS, 2))
189
199
  mstore(add(free, 0xa0), MODULUS)
190
200
  let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20)
191
201
  if iszero(success) {
192
- revert(0, 0)
202
+ mstore(0x00, FRLIB_MODEXP_FAILED_SELECTOR)
203
+ revert(0, 0x04)
193
204
  }
194
205
  result := mload(0x00)
195
- mstore(0x40, add(free, 0x80))
206
+ mstore(0x40, add(free, 0xc0))
196
207
  }
197
208
 
198
209
  return Fr.wrap(result);
@@ -200,6 +211,8 @@ library FrLib {
200
211
 
201
212
  function pow(Fr base, uint256 v) internal view returns (Fr) {
202
213
  uint256 b = Fr.unwrap(base);
214
+ // Only works for power of 2
215
+ require(v > 0 && (v & (v - 1)) == 0, Errors.NotPowerOfTwo());
203
216
  uint256 result;
204
217
 
205
218
  // Call the modexp precompile to invert in the field
@@ -209,14 +222,15 @@ library FrLib {
209
222
  mstore(add(free, 0x20), 0x20)
210
223
  mstore(add(free, 0x40), 0x20)
211
224
  mstore(add(free, 0x60), b)
212
- mstore(add(free, 0x80), v)
225
+ mstore(add(free, 0x80), v)
213
226
  mstore(add(free, 0xa0), MODULUS)
214
227
  let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20)
215
228
  if iszero(success) {
216
- revert(0, 0)
229
+ mstore(0x00, FRLIB_MODEXP_FAILED_SELECTOR)
230
+ revert(0, 0x04)
217
231
  }
218
232
  result := mload(0x00)
219
- mstore(0x40, add(free, 0x80))
233
+ mstore(0x40, add(free, 0xc0))
220
234
  }
221
235
 
222
236
  return Fr.wrap(result);
@@ -245,6 +259,27 @@ library FrLib {
245
259
  return Fr.wrap(MODULUS - Fr.unwrap(value));
246
260
  }
247
261
  }
262
+
263
+ function from(uint256 value) internal pure returns (Fr) {
264
+ unchecked {
265
+ require(value < MODULUS, Errors.ValueGeFieldOrder());
266
+ return Fr.wrap(value);
267
+ }
268
+ }
269
+
270
+ function fromBytes32(bytes32 value) internal pure returns (Fr) {
271
+ unchecked {
272
+ uint256 v = uint256(value);
273
+ require(v < MODULUS, Errors.ValueGeFieldOrder());
274
+ return Fr.wrap(v);
275
+ }
276
+ }
277
+
278
+ function toBytes32(Fr value) internal pure returns (bytes32) {
279
+ unchecked {
280
+ return bytes32(Fr.unwrap(value));
281
+ }
282
+ }
248
283
  }
249
284
 
250
285
  // Free functions
@@ -266,15 +301,6 @@ function sub(Fr a, Fr b) pure returns (Fr) {
266
301
  }
267
302
  }
268
303
 
269
- function exp(Fr base, Fr exponent) pure returns (Fr) {
270
- if (Fr.unwrap(exponent) == 0) return Fr.wrap(1);
271
- // Implement exponent with a loop as we will overflow otherwise
272
- for (uint256 i = 1; i < Fr.unwrap(exponent); i += i) {
273
- base = base * base;
274
- }
275
- return base;
276
- }
277
-
278
304
  function notEqual(Fr a, Fr b) pure returns (bool) {
279
305
  unchecked {
280
306
  return Fr.unwrap(a) != Fr.unwrap(b);
@@ -299,7 +325,7 @@ uint256 constant NUMBER_OF_ENTITIES_ZK = NUMBER_OF_ENTITIES + NUM_MASKING_POLYNO
299
325
  uint256 constant NUMBER_UNSHIFTED = 36;
300
326
  uint256 constant NUMBER_UNSHIFTED_ZK = NUMBER_UNSHIFTED + NUM_MASKING_POLYNOMIALS;
301
327
  uint256 constant NUMBER_TO_BE_SHIFTED = 5;
302
- uint256 constant PAIRING_POINTS_SIZE = 16;
328
+ uint256 constant PAIRING_POINTS_SIZE = 8;
303
329
 
304
330
  uint256 constant FIELD_ELEMENT_SIZE = 0x20;
305
331
  uint256 constant GROUP_ELEMENT_SIZE = 0x40;
@@ -401,8 +427,6 @@ library Honk {
401
427
  struct RelationParameters {
402
428
  // challenges
403
429
  Fr eta;
404
- Fr etaTwo;
405
- Fr etaThree;
406
430
  Fr beta;
407
431
  Fr gamma;
408
432
  // derived
@@ -488,7 +512,7 @@ library TranscriptLib {
488
512
  uint256 vkHash,
489
513
  uint256 publicInputsSize,
490
514
  uint256 logN
491
- ) internal view returns (Transcript memory t) {
515
+ ) internal pure returns (Transcript memory t) {
492
516
  Fr previousChallenge;
493
517
  (t.relationParameters, previousChallenge) =
494
518
  generateRelationParametersChallenges(proof, publicInputs, vkHash, publicInputsSize, previousChallenge);
@@ -515,8 +539,8 @@ library TranscriptLib {
515
539
  // Split into two equal 127-bit chunks (254/2)
516
540
  uint256 lo = challengeU256 & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // 127 bits
517
541
  uint256 hi = challengeU256 >> 127;
518
- first = FrLib.fromBytes32(bytes32(lo));
519
- second = FrLib.fromBytes32(bytes32(hi));
542
+ first = FrLib.from(lo);
543
+ second = FrLib.from(hi);
520
544
  }
521
545
 
522
546
  function generateRelationParametersChallenges(
@@ -526,10 +550,9 @@ library TranscriptLib {
526
550
  uint256 publicInputsSize,
527
551
  Fr previousChallenge
528
552
  ) internal pure returns (Honk.RelationParameters memory rp, Fr nextPreviousChallenge) {
529
- (rp.eta, rp.etaTwo, rp.etaThree, previousChallenge) =
530
- generateEtaChallenge(proof, publicInputs, vkHash, publicInputsSize);
553
+ (rp.eta, previousChallenge) = generateEtaChallenge(proof, publicInputs, vkHash, publicInputsSize);
531
554
 
532
- (rp.beta, rp.gamma, nextPreviousChallenge) = generateBetaAndGammaChallenges(previousChallenge, proof);
555
+ (rp.beta, rp.gamma, nextPreviousChallenge) = generateBetaGammaChallenges(previousChallenge, proof);
533
556
  }
534
557
 
535
558
  function generateEtaChallenge(
@@ -537,12 +560,13 @@ library TranscriptLib {
537
560
  bytes32[] calldata publicInputs,
538
561
  uint256 vkHash,
539
562
  uint256 publicInputsSize
540
- ) internal pure returns (Fr eta, Fr etaTwo, Fr etaThree, Fr previousChallenge) {
563
+ ) internal pure returns (Fr eta, Fr previousChallenge) {
541
564
  bytes32[] memory round0 = new bytes32[](1 + publicInputsSize + 6);
542
565
  round0[0] = bytes32(vkHash);
543
566
 
544
567
  for (uint256 i = 0; i < publicInputsSize - PAIRING_POINTS_SIZE; i++) {
545
- round0[1 + i] = bytes32(publicInputs[i]);
568
+ require(uint256(publicInputs[i]) < P, Errors.ValueGeFieldOrder());
569
+ round0[1 + i] = publicInputs[i];
546
570
  }
547
571
  for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) {
548
572
  round0[1 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]);
@@ -557,15 +581,11 @@ library TranscriptLib {
557
581
  round0[1 + publicInputsSize + 4] = bytes32(proof.w3.x);
558
582
  round0[1 + publicInputsSize + 5] = bytes32(proof.w3.y);
559
583
 
560
- previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round0)));
561
- (eta, etaTwo) = splitChallenge(previousChallenge);
562
-
563
- previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge))));
564
- Fr unused;
565
- (etaThree, unused) = splitChallenge(previousChallenge);
584
+ previousChallenge = FrLib.from(uint256(keccak256(abi.encodePacked(round0))) % P);
585
+ (eta,) = splitChallenge(previousChallenge);
566
586
  }
567
587
 
568
- function generateBetaAndGammaChallenges(Fr previousChallenge, Honk.Proof memory proof)
588
+ function generateBetaGammaChallenges(Fr previousChallenge, Honk.Proof memory proof)
569
589
  internal
570
590
  pure
571
591
  returns (Fr beta, Fr gamma, Fr nextPreviousChallenge)
@@ -579,7 +599,7 @@ library TranscriptLib {
579
599
  round1[5] = bytes32(proof.w4.x);
580
600
  round1[6] = bytes32(proof.w4.y);
581
601
 
582
- nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round1)));
602
+ nextPreviousChallenge = FrLib.from(uint256(keccak256(abi.encodePacked(round1))) % P);
583
603
  (beta, gamma) = splitChallenge(nextPreviousChallenge);
584
604
  }
585
605
 
@@ -597,7 +617,7 @@ library TranscriptLib {
597
617
  alpha0[3] = proof.zPerm.x;
598
618
  alpha0[4] = proof.zPerm.y;
599
619
 
600
- nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(alpha0)));
620
+ nextPreviousChallenge = FrLib.from(uint256(keccak256(abi.encodePacked(alpha0))) % P);
601
621
  Fr alpha;
602
622
  (alpha,) = splitChallenge(nextPreviousChallenge);
603
623
 
@@ -613,7 +633,7 @@ library TranscriptLib {
613
633
  pure
614
634
  returns (Fr[CONST_PROOF_SIZE_LOG_N] memory gateChallenges, Fr nextPreviousChallenge)
615
635
  {
616
- previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge))));
636
+ previousChallenge = FrLib.from(uint256(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))) % P);
617
637
  (gateChallenges[0],) = splitChallenge(previousChallenge);
618
638
  for (uint256 i = 1; i < logN; i++) {
619
639
  gateChallenges[i] = gateChallenges[i - 1] * gateChallenges[i - 1];
@@ -633,7 +653,7 @@ library TranscriptLib {
633
653
  for (uint256 j = 0; j < BATCHED_RELATION_PARTIAL_LENGTH; j++) {
634
654
  univariateChal[j + 1] = proof.sumcheckUnivariates[i][j];
635
655
  }
636
- prevChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(univariateChal)));
656
+ prevChallenge = FrLib.from(uint256(keccak256(abi.encodePacked(univariateChal))) % P);
637
657
  Fr unused;
638
658
  (sumcheckChallenges[i], unused) = splitChallenge(prevChallenge);
639
659
  }
@@ -652,7 +672,7 @@ library TranscriptLib {
652
672
  rhoChallengeElements[i + 1] = proof.sumcheckEvaluations[i];
653
673
  }
654
674
 
655
- nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(rhoChallengeElements)));
675
+ nextPreviousChallenge = FrLib.from(uint256(keccak256(abi.encodePacked(rhoChallengeElements))) % P);
656
676
  Fr unused;
657
677
  (rho, unused) = splitChallenge(nextPreviousChallenge);
658
678
  }
@@ -670,7 +690,7 @@ library TranscriptLib {
670
690
  gR[2 + i * 2] = proof.geminiFoldComms[i].y;
671
691
  }
672
692
 
673
- nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(gR)));
693
+ nextPreviousChallenge = FrLib.from(uint256(keccak256(abi.encodePacked(gR))) % P);
674
694
  Fr unused;
675
695
  (geminiR, unused) = splitChallenge(nextPreviousChallenge);
676
696
  }
@@ -687,14 +707,14 @@ library TranscriptLib {
687
707
  shplonkNuChallengeElements[i + 1] = Fr.unwrap(proof.geminiAEvaluations[i]);
688
708
  }
689
709
 
690
- nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkNuChallengeElements)));
710
+ nextPreviousChallenge = FrLib.from(uint256(keccak256(abi.encodePacked(shplonkNuChallengeElements))) % P);
691
711
  Fr unused;
692
712
  (shplonkNu, unused) = splitChallenge(nextPreviousChallenge);
693
713
  }
694
714
 
695
715
  function generateShplonkZChallenge(Honk.Proof memory proof, Fr prevChallenge)
696
716
  internal
697
- view
717
+ pure
698
718
  returns (Fr shplonkZ, Fr nextPreviousChallenge)
699
719
  {
700
720
  uint256[3] memory shplonkZChallengeElements;
@@ -703,7 +723,7 @@ library TranscriptLib {
703
723
  shplonkZChallengeElements[1] = proof.shplonkQ.x;
704
724
  shplonkZChallengeElements[2] = proof.shplonkQ.y;
705
725
 
706
- nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkZChallengeElements)));
726
+ nextPreviousChallenge = FrLib.from(uint256(keccak256(abi.encodePacked(shplonkZChallengeElements))) % P);
707
727
  Fr unused;
708
728
  (shplonkZ, unused) = splitChallenge(nextPreviousChallenge);
709
729
  }
@@ -713,7 +733,10 @@ library TranscriptLib {
713
733
 
714
734
  // Pairing point object
715
735
  for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) {
716
- p.pairingPointObject[i] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]);
736
+ uint256 limb = uint256(bytes32(proof[boundary:boundary + FIELD_ELEMENT_SIZE]));
737
+ // lo limbs (even index) < 2^136, hi limbs (odd index) < 2^120
738
+ require(limb < 2 ** (i % 2 == 0 ? 136 : 120), Errors.ValueGeLimbMax());
739
+ p.pairingPointObject[i] = FrLib.from(limb);
717
740
  boundary += FIELD_ELEMENT_SIZE;
718
741
  }
719
742
  // Commitments
@@ -770,10 +793,91 @@ library TranscriptLib {
770
793
  }
771
794
  }
772
795
 
773
- // Field arithmetic libraries
774
-
775
796
  library RelationsLib {
797
+ struct EllipticParams {
798
+ // Points
799
+ Fr x_1;
800
+ Fr y_1;
801
+ Fr x_2;
802
+ Fr y_2;
803
+ Fr y_3;
804
+ Fr x_3;
805
+ // push accumulators into memory
806
+ Fr x_double_identity;
807
+ }
808
+
809
+ // Parameters used within the Memory Relation
810
+ // A struct is used to work around stack too deep. This relation has alot of variables
811
+ struct MemParams {
812
+ Fr memory_record_check;
813
+ Fr partial_record_check;
814
+ Fr next_gate_access_type;
815
+ Fr record_delta;
816
+ Fr index_delta;
817
+ Fr adjacent_values_match_if_adjacent_indices_match;
818
+ Fr adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation;
819
+ Fr access_check;
820
+ Fr next_gate_access_type_is_boolean;
821
+ Fr ROM_consistency_check_identity;
822
+ Fr RAM_consistency_check_identity;
823
+ Fr timestamp_delta;
824
+ Fr RAM_timestamp_check_identity;
825
+ Fr memory_identity;
826
+ Fr index_is_monotonically_increasing;
827
+ }
828
+
829
+ // Parameters used within the Non-Native Field Relation
830
+ // A struct is used to work around stack too deep. This relation has alot of variables
831
+ struct NnfParams {
832
+ Fr limb_subproduct;
833
+ Fr non_native_field_gate_1;
834
+ Fr non_native_field_gate_2;
835
+ Fr non_native_field_gate_3;
836
+ Fr limb_accumulator_1;
837
+ Fr limb_accumulator_2;
838
+ Fr nnf_identity;
839
+ }
840
+
841
+ struct PoseidonExternalParams {
842
+ Fr s1;
843
+ Fr s2;
844
+ Fr s3;
845
+ Fr s4;
846
+ Fr u1;
847
+ Fr u2;
848
+ Fr u3;
849
+ Fr u4;
850
+ Fr t0;
851
+ Fr t1;
852
+ Fr t2;
853
+ Fr t3;
854
+ Fr v1;
855
+ Fr v2;
856
+ Fr v3;
857
+ Fr v4;
858
+ Fr q_pos_by_scaling;
859
+ }
860
+
861
+ struct PoseidonInternalParams {
862
+ Fr u1;
863
+ Fr u2;
864
+ Fr u3;
865
+ Fr u4;
866
+ Fr u_sum;
867
+ Fr v1;
868
+ Fr v2;
869
+ Fr v3;
870
+ Fr v4;
871
+ Fr s1;
872
+ Fr q_pos_by_scaling;
873
+ }
874
+
776
875
  Fr internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = Fr.wrap(17); // -(-17)
876
+ uint256 internal constant NEG_HALF_MODULO_P = 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000;
877
+
878
+ // Constants for the Non-native Field relation
879
+ Fr internal constant LIMB_SIZE = Fr.wrap(uint256(1) << 68);
880
+ Fr internal constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14);
777
881
 
778
882
  function accumulateRelationEvaluations(
779
883
  Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations,
@@ -807,12 +911,10 @@ library RelationsLib {
807
911
  return p[uint256(_wire)];
808
912
  }
809
913
 
810
- uint256 internal constant NEG_HALF_MODULO_P = 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000;
811
914
  /**
812
915
  * Ultra Arithmetic Relation
813
916
  *
814
917
  */
815
-
816
918
  function accumulateArithmeticRelation(
817
919
  Fr[NUMBER_OF_ENTITIES] memory p,
818
920
  Fr[NUMBER_OF_SUBRELATIONS] memory evals,
@@ -893,38 +995,42 @@ library RelationsLib {
893
995
  Fr[NUMBER_OF_SUBRELATIONS] memory evals,
894
996
  Fr domainSep
895
997
  ) internal pure {
896
- Fr write_term;
897
- Fr read_term;
998
+ Fr table_term;
999
+ Fr lookup_term;
898
1000
 
899
1001
  // Calculate the write term (the table accumulation)
1002
+ // table_term = table_1 + γ + table_2 * β + table_3 * β² + table_4 * β³
900
1003
  {
901
- write_term = wire(p, WIRE.TABLE_1) + rp.gamma + (wire(p, WIRE.TABLE_2) * rp.eta)
902
- + (wire(p, WIRE.TABLE_3) * rp.etaTwo) + (wire(p, WIRE.TABLE_4) * rp.etaThree);
1004
+ Fr beta_sqr = rp.beta * rp.beta;
1005
+ table_term = wire(p, WIRE.TABLE_1) + rp.gamma + (wire(p, WIRE.TABLE_2) * rp.beta)
1006
+ + (wire(p, WIRE.TABLE_3) * beta_sqr) + (wire(p, WIRE.TABLE_4) * beta_sqr * rp.beta);
903
1007
  }
904
1008
 
905
- // Calculate the write term
1009
+ // Calculate the read term
1010
+ // lookup_term = derived_entry_1 + γ + derived_entry_2 * β + derived_entry_3 * β² + q_index * β³
906
1011
  {
1012
+ Fr beta_sqr = rp.beta * rp.beta;
907
1013
  Fr derived_entry_1 = wire(p, WIRE.W_L) + rp.gamma + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_L_SHIFT));
908
1014
  Fr derived_entry_2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_M) * wire(p, WIRE.W_R_SHIFT);
909
1015
  Fr derived_entry_3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_C) * wire(p, WIRE.W_O_SHIFT);
910
1016
 
911
- read_term = derived_entry_1 + (derived_entry_2 * rp.eta) + (derived_entry_3 * rp.etaTwo)
912
- + (wire(p, WIRE.Q_O) * rp.etaThree);
1017
+ lookup_term = derived_entry_1 + (derived_entry_2 * rp.beta) + (derived_entry_3 * beta_sqr)
1018
+ + (wire(p, WIRE.Q_O) * beta_sqr * rp.beta);
913
1019
  }
914
1020
 
915
- Fr read_inverse = wire(p, WIRE.LOOKUP_INVERSES) * write_term;
916
- Fr write_inverse = wire(p, WIRE.LOOKUP_INVERSES) * read_term;
1021
+ Fr lookup_inverse = wire(p, WIRE.LOOKUP_INVERSES) * table_term;
1022
+ Fr table_inverse = wire(p, WIRE.LOOKUP_INVERSES) * lookup_term;
917
1023
 
918
1024
  Fr inverse_exists_xor =
919
1025
  wire(p, WIRE.LOOKUP_READ_TAGS) + wire(p, WIRE.Q_LOOKUP)
920
1026
  - (wire(p, WIRE.LOOKUP_READ_TAGS) * wire(p, WIRE.Q_LOOKUP));
921
1027
 
922
1028
  // Inverse calculated correctly relation
923
- Fr accumulatorNone = read_term * write_term * wire(p, WIRE.LOOKUP_INVERSES) - inverse_exists_xor;
1029
+ Fr accumulatorNone = lookup_term * table_term * wire(p, WIRE.LOOKUP_INVERSES) - inverse_exists_xor;
924
1030
  accumulatorNone = accumulatorNone * domainSep;
925
1031
 
926
1032
  // Inverse
927
- Fr accumulatorOne = wire(p, WIRE.Q_LOOKUP) * read_inverse - wire(p, WIRE.LOOKUP_READ_COUNTS) * write_inverse;
1033
+ Fr accumulatorOne = wire(p, WIRE.Q_LOOKUP) * lookup_inverse - wire(p, WIRE.LOOKUP_READ_COUNTS) * table_inverse;
928
1034
 
929
1035
  Fr read_tag = wire(p, WIRE.LOOKUP_READ_TAGS);
930
1036
 
@@ -995,18 +1101,6 @@ library RelationsLib {
995
1101
  }
996
1102
  }
997
1103
 
998
- struct EllipticParams {
999
- // Points
1000
- Fr x_1;
1001
- Fr y_1;
1002
- Fr x_2;
1003
- Fr y_2;
1004
- Fr y_3;
1005
- Fr x_3;
1006
- // push accumulators into memory
1007
- Fr x_double_identity;
1008
- }
1009
-
1010
1104
  function accumulateEllipticRelation(
1011
1105
  Fr[NUMBER_OF_ENTITIES] memory p,
1012
1106
  Fr[NUMBER_OF_SUBRELATIONS] memory evals,
@@ -1075,26 +1169,6 @@ library RelationsLib {
1075
1169
  }
1076
1170
  }
1077
1171
 
1078
- // Parameters used within the Memory Relation
1079
- // A struct is used to work around stack too deep. This relation has alot of variables
1080
- struct MemParams {
1081
- Fr memory_record_check;
1082
- Fr partial_record_check;
1083
- Fr next_gate_access_type;
1084
- Fr record_delta;
1085
- Fr index_delta;
1086
- Fr adjacent_values_match_if_adjacent_indices_match;
1087
- Fr adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation;
1088
- Fr access_check;
1089
- Fr next_gate_access_type_is_boolean;
1090
- Fr ROM_consistency_check_identity;
1091
- Fr RAM_consistency_check_identity;
1092
- Fr timestamp_delta;
1093
- Fr RAM_timestamp_check_identity;
1094
- Fr memory_identity;
1095
- Fr index_is_monotonically_increasing;
1096
- }
1097
-
1098
1172
  function accumulateMemoryRelation(
1099
1173
  Fr[NUMBER_OF_ENTITIES] memory p,
1100
1174
  Honk.RelationParameters memory rp,
@@ -1103,6 +1177,10 @@ library RelationsLib {
1103
1177
  ) internal pure {
1104
1178
  MemParams memory ap;
1105
1179
 
1180
+ // Compute eta powers locally
1181
+ Fr eta_two = rp.eta * rp.eta;
1182
+ Fr eta_three = eta_two * rp.eta;
1183
+
1106
1184
  /**
1107
1185
  * MEMORY
1108
1186
  *
@@ -1144,8 +1222,8 @@ library RelationsLib {
1144
1222
  *
1145
1223
  * For ROM gates, qc = 0
1146
1224
  */
1147
- ap.memory_record_check = wire(p, WIRE.W_O) * rp.etaThree;
1148
- ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_R) * rp.etaTwo);
1225
+ ap.memory_record_check = wire(p, WIRE.W_O) * eta_three;
1226
+ ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_R) * eta_two);
1149
1227
  ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_L) * rp.eta);
1150
1228
  ap.memory_record_check = ap.memory_record_check + wire(p, WIRE.Q_C);
1151
1229
  ap.partial_record_check = ap.memory_record_check; // used in RAM consistency check; deg 1 or 4
@@ -1205,8 +1283,8 @@ library RelationsLib {
1205
1283
 
1206
1284
  // reverse order we could re-use `ap.partial_record_check` 1 - ((w3' * eta + w2') * eta + w1') * eta
1207
1285
  // deg 1 or 4
1208
- ap.next_gate_access_type = wire(p, WIRE.W_O_SHIFT) * rp.etaThree;
1209
- ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_R_SHIFT) * rp.etaTwo);
1286
+ ap.next_gate_access_type = wire(p, WIRE.W_O_SHIFT) * eta_three;
1287
+ ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_R_SHIFT) * eta_two);
1210
1288
  ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_L_SHIFT) * rp.eta);
1211
1289
  ap.next_gate_access_type = wire(p, WIRE.W_4_SHIFT) - ap.next_gate_access_type;
1212
1290
 
@@ -1260,22 +1338,6 @@ library RelationsLib {
1260
1338
  evals[13] = ap.memory_identity;
1261
1339
  }
1262
1340
 
1263
- // Constants for the Non-native Field relation
1264
- Fr constant LIMB_SIZE = Fr.wrap(uint256(1) << 68);
1265
- Fr constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14);
1266
-
1267
- // Parameters used within the Non-Native Field Relation
1268
- // A struct is used to work around stack too deep. This relation has alot of variables
1269
- struct NnfParams {
1270
- Fr limb_subproduct;
1271
- Fr non_native_field_gate_1;
1272
- Fr non_native_field_gate_2;
1273
- Fr non_native_field_gate_3;
1274
- Fr limb_accumulator_1;
1275
- Fr limb_accumulator_2;
1276
- Fr nnf_identity;
1277
- }
1278
-
1279
1341
  function accumulateNnfRelation(
1280
1342
  Fr[NUMBER_OF_ENTITIES] memory p,
1281
1343
  Fr[NUMBER_OF_SUBRELATIONS] memory evals,
@@ -1352,26 +1414,6 @@ library RelationsLib {
1352
1414
  evals[19] = ap.nnf_identity;
1353
1415
  }
1354
1416
 
1355
- struct PoseidonExternalParams {
1356
- Fr s1;
1357
- Fr s2;
1358
- Fr s3;
1359
- Fr s4;
1360
- Fr u1;
1361
- Fr u2;
1362
- Fr u3;
1363
- Fr u4;
1364
- Fr t0;
1365
- Fr t1;
1366
- Fr t2;
1367
- Fr t3;
1368
- Fr v1;
1369
- Fr v2;
1370
- Fr v3;
1371
- Fr v4;
1372
- Fr q_pos_by_scaling;
1373
- }
1374
-
1375
1417
  function accumulatePoseidonExternalRelation(
1376
1418
  Fr[NUMBER_OF_ENTITIES] memory p,
1377
1419
  Fr[NUMBER_OF_SUBRELATIONS] memory evals,
@@ -1414,20 +1456,6 @@ library RelationsLib {
1414
1456
  evals[23] = evals[23] + ep.q_pos_by_scaling * (ep.v4 - wire(p, WIRE.W_4_SHIFT));
1415
1457
  }
1416
1458
 
1417
- struct PoseidonInternalParams {
1418
- Fr u1;
1419
- Fr u2;
1420
- Fr u3;
1421
- Fr u4;
1422
- Fr u_sum;
1423
- Fr v1;
1424
- Fr v2;
1425
- Fr v3;
1426
- Fr v4;
1427
- Fr s1;
1428
- Fr q_pos_by_scaling;
1429
- }
1430
-
1431
1459
  function accumulatePoseidonInternalRelation(
1432
1460
  Fr[NUMBER_OF_ENTITIES] memory p,
1433
1461
  Fr[NUMBER_OF_SUBRELATIONS] memory evals,
@@ -1483,8 +1511,6 @@ library RelationsLib {
1483
1511
  }
1484
1512
  }
1485
1513
 
1486
- // Field arithmetic libraries - prevent littering the code with modmul / addmul
1487
-
1488
1514
  library CommitmentSchemeLib {
1489
1515
  using FrLib for Fr;
1490
1516
 
@@ -1514,16 +1540,7 @@ library CommitmentSchemeLib {
1514
1540
  Fr[] foldPosEvaluations;
1515
1541
  }
1516
1542
 
1517
- function computeSquares(Fr r, uint256 logN) internal pure returns (Fr[] memory) {
1518
- Fr[] memory squares = new Fr[](logN);
1519
- squares[0] = r;
1520
- for (uint256 i = 1; i < logN; ++i) {
1521
- squares[i] = squares[i - 1].sqr();
1522
- }
1523
- return squares;
1524
- }
1525
1543
  // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., m-1
1526
-
1527
1544
  function computeFoldPosEvaluations(
1528
1545
  Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckUChallenges,
1529
1546
  Fr batchedEvalAccumulator,
@@ -1546,23 +1563,19 @@ library CommitmentSchemeLib {
1546
1563
  }
1547
1564
  return foldPosEvaluations;
1548
1565
  }
1549
- }
1550
-
1551
- uint256 constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // EC group order. F_q
1552
-
1553
- function bytes32ToString(bytes32 value) pure returns (string memory result) {
1554
- bytes memory alphabet = "0123456789abcdef";
1555
1566
 
1556
- bytes memory str = new bytes(66);
1557
- str[0] = "0";
1558
- str[1] = "x";
1559
- for (uint256 i = 0; i < 32; i++) {
1560
- str[2 + i * 2] = alphabet[uint8(value[i] >> 4)];
1561
- str[3 + i * 2] = alphabet[uint8(value[i] & 0x0f)];
1567
+ function computeSquares(Fr r, uint256 logN) internal pure returns (Fr[] memory) {
1568
+ Fr[] memory squares = new Fr[](logN);
1569
+ squares[0] = r;
1570
+ for (uint256 i = 1; i < logN; ++i) {
1571
+ squares[i] = squares[i - 1].sqr();
1572
+ }
1573
+ return squares;
1562
1574
  }
1563
- result = string(str);
1564
1575
  }
1565
1576
 
1577
+ uint256 constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // EC group order. F_q
1578
+
1566
1579
  // Fr utility
1567
1580
 
1568
1581
  function bytesToFr(bytes calldata proofSection) pure returns (Fr scalar) {
@@ -1571,54 +1584,66 @@ function bytesToFr(bytes calldata proofSection) pure returns (Fr scalar) {
1571
1584
 
1572
1585
  // EC Point utilities
1573
1586
  function bytesToG1Point(bytes calldata proofSection) pure returns (Honk.G1Point memory point) {
1574
- point = Honk.G1Point({
1575
- x: uint256(bytes32(proofSection[0x00:0x20])) % Q, y: uint256(bytes32(proofSection[0x20:0x40])) % Q
1576
- });
1587
+ uint256 x = uint256(bytes32(proofSection[0x00:0x20]));
1588
+ uint256 y = uint256(bytes32(proofSection[0x20:0x40]));
1589
+ require(x < Q && y < Q, Errors.ValueGeGroupOrder());
1590
+
1591
+ // Reject the point at infinity (0,0). EVM precompiles silently treat (0,0)
1592
+ // as the identity element, which could zero out commitments.
1593
+ // On-curve validation (y² = x³ + 3) is handled by the ecAdd/ecMul precompiles
1594
+ // per EIP-196, so we only need to catch this special case here.
1595
+ require((x | y) != 0, Errors.PointAtInfinity());
1596
+
1597
+ point = Honk.G1Point({x: x, y: y});
1577
1598
  }
1578
1599
 
1579
1600
  function negateInplace(Honk.G1Point memory point) pure returns (Honk.G1Point memory) {
1580
- point.y = (Q - point.y) % Q;
1601
+ // When y == 0 (order-2 point), negation is the same point. Q - 0 = Q which is >= Q.
1602
+ if (point.y != 0) {
1603
+ point.y = Q - point.y;
1604
+ }
1581
1605
  return point;
1582
1606
  }
1583
1607
 
1584
1608
  /**
1585
1609
  * Convert the pairing points to G1 points.
1586
1610
  *
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
1611
+ * The pairing points are serialised as an array of 2 limbs representing two points
1612
+ * (P0 and P1, used for lhs and rhs of pairing operation).
1589
1613
  *
1590
- * There are 4 fields for each group element, leaving 8 fields for each side of the pairing.
1614
+ * There are 2 limbs (lo, hi) for each coordinate, so 4 limbs per point, 8 total.
1615
+ * Layout: [P0.x_lo, P0.x_hi, P0.y_lo, P0.y_hi, P1.x_lo, P1.x_hi, P1.y_lo, P1.y_hi]
1591
1616
  *
1592
1617
  * @param pairingPoints The pairing points to convert.
1593
- * @return lhs
1594
- * @return rhs
1618
+ * @return lhs P0 point
1619
+ * @return rhs P1 point
1595
1620
  */
1596
1621
  function convertPairingPointsToG1(Fr[PAIRING_POINTS_SIZE] memory pairingPoints)
1597
1622
  pure
1598
1623
  returns (Honk.G1Point memory lhs, Honk.G1Point memory rhs)
1599
1624
  {
1625
+ // P0 (lhs): x = lo | (hi << 136)
1600
1626
  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;
1627
+ lhsX |= Fr.unwrap(pairingPoints[1]) << 136;
1605
1628
 
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;
1629
+ uint256 lhsY = Fr.unwrap(pairingPoints[2]);
1630
+ lhsY |= Fr.unwrap(pairingPoints[3]) << 136;
1611
1631
 
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;
1632
+ // P1 (rhs): x = lo | (hi << 136)
1633
+ uint256 rhsX = Fr.unwrap(pairingPoints[4]);
1634
+ rhsX |= Fr.unwrap(pairingPoints[5]) << 136;
1635
+
1636
+ uint256 rhsY = Fr.unwrap(pairingPoints[6]);
1637
+ rhsY |= Fr.unwrap(pairingPoints[7]) << 136;
1617
1638
 
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;
1639
+ // Reconstructed coordinates must be < Q to prevent malleability.
1640
+ // Without this, two different limb encodings could map to the same curve point
1641
+ // (via mulmod reduction in on-curve checks) but produce different transcript hashes.
1642
+ require(lhsX < Q && lhsY < Q && rhsX < Q && rhsY < Q, Errors.ValueGeGroupOrder());
1643
+
1644
+ lhs.x = lhsX;
1645
+ lhs.y = lhsY;
1646
+ rhs.x = rhsX;
1622
1647
  rhs.y = rhsY;
1623
1648
  }
1624
1649
 
@@ -1656,7 +1681,7 @@ function generateRecursionSeparator(
1656
1681
  recursionSeparatorElements[6] = accRhs.x;
1657
1682
  recursionSeparatorElements[7] = accRhs.y;
1658
1683
 
1659
- recursionSeparator = FrLib.fromBytes32(keccak256(abi.encodePacked(recursionSeparatorElements)));
1684
+ recursionSeparator = FrLib.from(uint256(keccak256(abi.encodePacked(recursionSeparatorElements))) % P);
1660
1685
  }
1661
1686
 
1662
1687
  /**
@@ -1774,17 +1799,20 @@ function ecAdd(Honk.G1Point memory lhs, Honk.G1Point memory rhs) view returns (H
1774
1799
  return result;
1775
1800
  }
1776
1801
 
1777
- function validateOnCurve(Honk.G1Point memory point) pure {
1778
- uint256 x = point.x;
1779
- uint256 y = point.y;
1802
+ function rejectPointAtInfinity(Honk.G1Point memory point) pure {
1803
+ require((point.x | point.y) != 0, Errors.PointAtInfinity());
1804
+ }
1780
1805
 
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))
1806
+ /**
1807
+ * Check if pairing point limbs are all zero (default/infinity).
1808
+ * Default pairing points indicate no recursive verification occurred.
1809
+ */
1810
+ function arePairingPointsDefault(Fr[PAIRING_POINTS_SIZE] memory pairingPoints) pure returns (bool) {
1811
+ uint256 acc = 0;
1812
+ for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) {
1813
+ acc |= Fr.unwrap(pairingPoints[i]);
1785
1814
  }
1786
-
1787
- require(success, "point is not on the curve");
1815
+ return acc == 0;
1788
1816
  }
1789
1817
 
1790
1818
  function pairing(Honk.G1Point memory rhs, Honk.G1Point memory lhs) view returns (bool decodedResult) {
@@ -1809,18 +1837,24 @@ function pairing(Honk.G1Point memory rhs, Honk.G1Point memory lhs) view returns
1809
1837
  decodedResult = success && abi.decode(result, (bool));
1810
1838
  }
1811
1839
 
1812
- // Field arithmetic libraries - prevent littering the code with modmul / addmul
1813
-
1840
+ abstract contract BaseHonkVerifier is IVerifier {
1841
+ using FrLib for Fr;
1814
1842
 
1843
+ // Constants for proof length calculation (matching UltraKeccakFlavor)
1844
+ uint256 internal constant NUM_WITNESS_ENTITIES = 8;
1845
+ uint256 internal constant NUM_ELEMENTS_COMM = 2; // uint256 elements for curve points
1846
+ uint256 internal constant NUM_ELEMENTS_FR = 1; // uint256 elements for field elements
1815
1847
 
1848
+ // Number of field elements in a ultra keccak honk proof for log_n = 25, including pairing point object.
1849
+ uint256 internal constant PROOF_SIZE = 350; // Legacy constant - will be replaced by calculateProofSize($LOG_N)
1850
+ uint256 internal constant SHIFTED_COMMITMENTS_START = 29;
1816
1851
 
1817
- abstract contract BaseHonkVerifier is IVerifier {
1818
- using FrLib for Fr;
1852
+ uint256 internal constant PERMUTATION_ARGUMENT_VALUE_SEPARATOR = 1 << 28;
1819
1853
 
1820
- uint256 immutable $N;
1821
- uint256 immutable $LOG_N;
1822
- uint256 immutable $VK_HASH;
1823
- uint256 immutable $NUM_PUBLIC_INPUTS;
1854
+ uint256 internal immutable $N;
1855
+ uint256 internal immutable $LOG_N;
1856
+ uint256 internal immutable $VK_HASH;
1857
+ uint256 internal immutable $NUM_PUBLIC_INPUTS;
1824
1858
 
1825
1859
  constructor(uint256 _N, uint256 _logN, uint256 _vkHash, uint256 _numPublicInputs) {
1826
1860
  $N = _N;
@@ -1829,59 +1863,19 @@ abstract contract BaseHonkVerifier is IVerifier {
1829
1863
  $NUM_PUBLIC_INPUTS = _numPublicInputs;
1830
1864
  }
1831
1865
 
1832
- // Errors
1833
- error ProofLengthWrong();
1834
- error ProofLengthWrongWithLogN(uint256 logN, uint256 actualLength, uint256 expectedLength);
1835
- error PublicInputsLengthWrong();
1836
- error SumcheckFailed();
1837
- error ShpleminiFailed();
1838
-
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;
1869
-
1870
- function loadVerificationKey() internal pure virtual returns (Honk.VerificationKey memory);
1871
-
1872
1866
  function verify(bytes calldata proof, bytes32[] calldata publicInputs) public view override returns (bool) {
1873
1867
  // Calculate expected proof size based on $LOG_N
1874
1868
  uint256 expectedProofSize = calculateProofSize($LOG_N);
1875
1869
 
1876
1870
  // Check the received proof is the expected size where each field element is 32 bytes
1877
1871
  if (proof.length != expectedProofSize * 32) {
1878
- revert ProofLengthWrongWithLogN($LOG_N, proof.length, expectedProofSize * 32);
1872
+ revert Errors.ProofLengthWrongWithLogN($LOG_N, proof.length, expectedProofSize * 32);
1879
1873
  }
1880
1874
 
1881
1875
  Honk.VerificationKey memory vk = loadVerificationKey();
1882
1876
  Honk.Proof memory p = TranscriptLib.loadProof(proof, $LOG_N);
1883
1877
  if (publicInputs.length != vk.publicInputsSize - PAIRING_POINTS_SIZE) {
1884
- revert PublicInputsLengthWrong();
1878
+ revert Errors.PublicInputsLengthWrong();
1885
1879
  }
1886
1880
 
1887
1881
  // Generate the fiat shamir challenges for the whole protocol
@@ -1898,16 +1892,14 @@ abstract contract BaseHonkVerifier is IVerifier {
1898
1892
 
1899
1893
  // Sumcheck
1900
1894
  bool sumcheckVerified = verifySumcheck(p, t);
1901
- if (!sumcheckVerified) revert SumcheckFailed();
1895
+ if (!sumcheckVerified) revert Errors.SumcheckFailed();
1902
1896
 
1903
1897
  bool shpleminiVerified = verifyShplemini(p, vk, t);
1904
- if (!shpleminiVerified) revert ShpleminiFailed();
1898
+ if (!shpleminiVerified) revert Errors.ShpleminiFailed();
1905
1899
 
1906
1900
  return sumcheckVerified && shpleminiVerified; // Boolean condition not required - nice for vanity :)
1907
1901
  }
1908
1902
 
1909
- uint256 constant PERMUTATION_ARGUMENT_VALUE_SEPARATOR = 1 << 28;
1910
-
1911
1903
  function computePublicInputDelta(
1912
1904
  bytes32[] memory publicInputs,
1913
1905
  Fr[PAIRING_POINTS_SIZE] memory pairingPointObject,
@@ -1954,7 +1946,7 @@ abstract contract BaseHonkVerifier is IVerifier {
1954
1946
  for (uint256 round = 0; round < $LOG_N; ++round) {
1955
1947
  Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariate = proof.sumcheckUnivariates[round];
1956
1948
  bool valid = checkSum(roundUnivariate, roundTarget);
1957
- if (!valid) revert SumcheckFailed();
1949
+ if (!valid) revert Errors.SumcheckFailed();
1958
1950
 
1959
1951
  Fr roundChallenge = tp.sumCheckUChallenges[round];
1960
1952
 
@@ -1970,15 +1962,6 @@ abstract contract BaseHonkVerifier is IVerifier {
1970
1962
  verified = (grandHonkRelationSum == roundTarget);
1971
1963
  }
1972
1964
 
1973
- function checkSum(Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariate, Fr roundTarget)
1974
- internal
1975
- pure
1976
- returns (bool checked)
1977
- {
1978
- Fr totalSum = roundUnivariate[0] + roundUnivariate[1];
1979
- checked = totalSum == roundTarget;
1980
- }
1981
-
1982
1965
  // Return the new target sum for the next sumcheck round
1983
1966
  function computeNextTargetSum(Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariates, Fr roundChallenge)
1984
1967
  internal
@@ -2022,16 +2005,6 @@ abstract contract BaseHonkVerifier is IVerifier {
2022
2005
  targetSum = targetSum * numeratorValue;
2023
2006
  }
2024
2007
 
2025
- // Univariate evaluation of the monomial ((1-X_l) + X_l.B_l) at the challenge point X_l=u_l
2026
- function partiallyEvaluatePOW(Fr gateChallenge, Fr currentEvaluation, Fr roundChallenge)
2027
- internal
2028
- pure
2029
- returns (Fr newEvaluation)
2030
- {
2031
- Fr univariateEval = ONE + (roundChallenge * (gateChallenge - ONE));
2032
- newEvaluation = currentEvaluation * univariateEval;
2033
- }
2034
-
2035
2008
  function verifyShplemini(Honk.Proof memory proof, Honk.VerificationKey memory vk, Transcript memory tp)
2036
2009
  internal
2037
2010
  view
@@ -2224,18 +2197,20 @@ abstract contract BaseHonkVerifier is IVerifier {
2224
2197
  Honk.G1Point memory P_0_agg = batchMul(commitments, scalars);
2225
2198
  Honk.G1Point memory P_1_agg = negateInplace(quotient_commitment);
2226
2199
 
2227
- // Aggregate pairing points
2228
- Fr recursionSeparator = generateRecursionSeparator(proof.pairingPointObject, P_0_agg, P_1_agg);
2229
- (Honk.G1Point memory P_0_other, Honk.G1Point memory P_1_other) =
2230
- convertPairingPointsToG1(proof.pairingPointObject);
2200
+ // Aggregate pairing points (skip if default/infinity — no recursive verification occurred)
2201
+ if (!arePairingPointsDefault(proof.pairingPointObject)) {
2202
+ Fr recursionSeparator = generateRecursionSeparator(proof.pairingPointObject, P_0_agg, P_1_agg);
2203
+ (Honk.G1Point memory P_0_other, Honk.G1Point memory P_1_other) =
2204
+ convertPairingPointsToG1(proof.pairingPointObject);
2231
2205
 
2232
- // Validate the points from the proof are on the curve
2233
- validateOnCurve(P_0_other);
2234
- validateOnCurve(P_1_other);
2206
+ // Validate the points from the proof are on the curve
2207
+ rejectPointAtInfinity(P_0_other);
2208
+ rejectPointAtInfinity(P_1_other);
2235
2209
 
2236
- // accumulate with aggregate points in proof
2237
- P_0_agg = mulWithSeperator(P_0_agg, P_0_other, recursionSeparator);
2238
- P_1_agg = mulWithSeperator(P_1_agg, P_1_other, recursionSeparator);
2210
+ // accumulate with aggregate points in proof
2211
+ P_0_agg = mulWithSeperator(P_0_agg, P_0_other, recursionSeparator);
2212
+ P_1_agg = mulWithSeperator(P_1_agg, P_1_other, recursionSeparator);
2213
+ }
2239
2214
 
2240
2215
  return pairing(P_0_agg, P_1_agg);
2241
2216
  }
@@ -2249,7 +2224,7 @@ abstract contract BaseHonkVerifier is IVerifier {
2249
2224
 
2250
2225
  // Validate all points are on the curve
2251
2226
  for (uint256 i = 0; i < limit; ++i) {
2252
- validateOnCurve(base[i]);
2227
+ rejectPointAtInfinity(base[i]);
2253
2228
  }
2254
2229
 
2255
2230
  bool success = true;
@@ -2277,8 +2252,51 @@ abstract contract BaseHonkVerifier is IVerifier {
2277
2252
  mstore(add(result, 0x20), mload(add(free, 0x20)))
2278
2253
  }
2279
2254
 
2280
- require(success, ShpleminiFailed());
2255
+ require(success, Errors.ShpleminiFailed());
2281
2256
  }
2257
+
2258
+ // Calculate proof size based on log_n (matching UltraKeccakFlavor formula)
2259
+ function calculateProofSize(uint256 logN) internal pure returns (uint256) {
2260
+ // Witness commitments
2261
+ uint256 proofLength = NUM_WITNESS_ENTITIES * NUM_ELEMENTS_COMM; // witness commitments
2262
+
2263
+ // Sumcheck
2264
+ proofLength += logN * BATCHED_RELATION_PARTIAL_LENGTH * NUM_ELEMENTS_FR; // sumcheck univariates
2265
+ proofLength += NUMBER_OF_ENTITIES * NUM_ELEMENTS_FR; // sumcheck evaluations
2266
+
2267
+ // Gemini
2268
+ proofLength += (logN - 1) * NUM_ELEMENTS_COMM; // Gemini Fold commitments
2269
+ proofLength += logN * NUM_ELEMENTS_FR; // Gemini evaluations
2270
+
2271
+ // Shplonk and KZG commitments
2272
+ proofLength += NUM_ELEMENTS_COMM * 2; // Shplonk Q and KZG W commitments
2273
+
2274
+ // Pairing points
2275
+ proofLength += PAIRING_POINTS_SIZE; // pairing inputs carried on public inputs
2276
+
2277
+ return proofLength;
2278
+ }
2279
+
2280
+ function checkSum(Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariate, Fr roundTarget)
2281
+ internal
2282
+ pure
2283
+ returns (bool checked)
2284
+ {
2285
+ Fr totalSum = roundUnivariate[0] + roundUnivariate[1];
2286
+ checked = totalSum == roundTarget;
2287
+ }
2288
+
2289
+ // Univariate evaluation of the monomial ((1-X_l) + X_l.B_l) at the challenge point X_l=u_l
2290
+ function partiallyEvaluatePOW(Fr gateChallenge, Fr currentEvaluation, Fr roundChallenge)
2291
+ internal
2292
+ pure
2293
+ returns (Fr newEvaluation)
2294
+ {
2295
+ Fr univariateEval = ONE + (roundChallenge * (gateChallenge - ONE));
2296
+ newEvaluation = currentEvaluation * univariateEval;
2297
+ }
2298
+
2299
+ function loadVerificationKey() internal pure virtual returns (Honk.VerificationKey memory);
2282
2300
  }
2283
2301
 
2284
2302
  contract HonkVerifier is BaseHonkVerifier(N, LOG_N, VK_HASH, NUMBER_OF_PUBLIC_INPUTS) {