@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.
- package/artifacts/app_creator.json +1 -1
- package/artifacts/app_reader.json +1 -1
- package/artifacts/keys/app_creator.vk.data.json +115 -115
- package/artifacts/keys/app_reader.vk.data.json +115 -115
- package/artifacts/keys/mock_private_kernel_init.vk.data.json +120 -120
- package/artifacts/keys/mock_private_kernel_inner.vk.data.json +120 -120
- package/artifacts/keys/mock_private_kernel_reset.vk.data.json +120 -120
- package/artifacts/keys/mock_private_kernel_tail.ivc.vk +0 -0
- package/artifacts/keys/mock_private_kernel_tail.vk.data.json +120 -120
- package/artifacts/keys/mock_rollup_base_private.vk.data.json +94 -92
- package/artifacts/keys/mock_rollup_base_public.vk.data.json +94 -92
- package/artifacts/keys/mock_rollup_merge.vk.data.json +94 -92
- package/artifacts/keys/mock_rollup_root.vk.data.json +56 -108
- package/artifacts/keys/mock_rollup_root_verifier.sol +690 -412
- package/artifacts/mock_private_kernel_init.json +1 -1
- package/artifacts/mock_private_kernel_inner.json +1 -1
- package/artifacts/mock_private_kernel_reset.json +1 -1
- package/artifacts/mock_private_kernel_tail.json +1 -1
- package/artifacts/mock_rollup_base_private.json +1 -1
- package/artifacts/mock_rollup_base_public.json +1 -1
- package/artifacts/mock_rollup_merge.json +1 -1
- package/artifacts/mock_rollup_root.json +1 -1
- package/dest/prove_native.d.ts +1 -1
- package/dest/prove_wasm.d.ts +2 -2
- package/dest/prove_wasm.d.ts.map +1 -1
- package/dest/prove_wasm.js +4 -4
- package/dest/serve.js +2 -2
- package/dest/types/index.d.ts +2 -2
- package/dest/witgen.d.ts +2 -2
- package/dest/witgen.d.ts.map +1 -1
- package/dest/witgen.js +2 -2
- package/package.json +16 -16
- package/src/prove_wasm.ts +10 -2
- package/src/serve.ts +2 -2
- package/src/types/index.ts +2 -2
- 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(
|
|
16
|
-
y: uint256(
|
|
16
|
+
x: uint256(0x0c60b18c1ec8931d1840b9f11a36c44d2e7da517918c0415b7df490c5502fda8),
|
|
17
|
+
y: uint256(0x0b8ece93dfa56a4771be75be6555d227ae201bd3eea78ac86a87234c68812063)
|
|
17
18
|
}),
|
|
18
19
|
qr: Honk.G1Point({
|
|
19
|
-
x: uint256(
|
|
20
|
-
y: uint256(
|
|
20
|
+
x: uint256(0x06cd1d8188c7542849ef57e9cc8893473a712a6da6afa963eb8ee58de227b8b9),
|
|
21
|
+
y: uint256(0x1104e48d2014827b6b0e4bb5d5559319661ce7cc3565112a9d0e1b2fa2e30317)
|
|
21
22
|
}),
|
|
22
23
|
qo: Honk.G1Point({
|
|
23
|
-
x: uint256(
|
|
24
|
-
y: uint256(
|
|
24
|
+
x: uint256(0x2f34d57f61daf01f4b9c1ef7d487f2b7b1836c9591424f005ba60ab95b3ef2ed),
|
|
25
|
+
y: uint256(0x2999e6f81261661d0962b31ff1d9f8bdc2d7ca8c2148b88282489e61e5360c28)
|
|
25
26
|
}),
|
|
26
27
|
q4: Honk.G1Point({
|
|
27
|
-
x: uint256(
|
|
28
|
-
y: uint256(
|
|
28
|
+
x: uint256(0x1418fea5a0faa2ee54bf0248bd9ac390bbcacbc2996fefcc9bb4a6ba9dfd0260),
|
|
29
|
+
y: uint256(0x19fc8df0bcb4e09e25fd42c1926c5c7764d649b5cfd09c99e9dc051708fe61de)
|
|
29
30
|
}),
|
|
30
31
|
qm: Honk.G1Point({
|
|
31
|
-
x: uint256(
|
|
32
|
-
y: uint256(
|
|
32
|
+
x: uint256(0x2b4c9105b249d59815ecfa0a434c0d50f53739b3e0e27c75f9c3465b94f404db),
|
|
33
|
+
y: uint256(0x075c114babc04dcb4434585245be91f4fb30089f9e0fa8c4396d0899a746cd72)
|
|
33
34
|
}),
|
|
34
35
|
qc: Honk.G1Point({
|
|
35
|
-
x: uint256(
|
|
36
|
-
y: uint256(
|
|
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(
|
|
40
|
-
y: uint256(
|
|
44
|
+
x: uint256(0x093cb4bb0b070139f3d1c6453dcc91e3b90706a60f383e4019fbbbc55f915593),
|
|
45
|
+
y: uint256(0x147b519bb194c3a0aab2193458b8a698136120695c10611e005fc52c5c62a810)
|
|
41
46
|
}),
|
|
42
47
|
qDeltaRange: Honk.G1Point({
|
|
43
|
-
x: uint256(
|
|
44
|
-
y: uint256(
|
|
48
|
+
x: uint256(0x09314af86e789e03f6a4f885695305d59653d9dd77212d5d274cd2496d1fdd89),
|
|
49
|
+
y: uint256(0x18e29c2f6bf780beec6a0aa6ca5656e05cb888af61bc11690167176932720269)
|
|
45
50
|
}),
|
|
46
51
|
qElliptic: Honk.G1Point({
|
|
47
|
-
x: uint256(
|
|
48
|
-
y: uint256(
|
|
52
|
+
x: uint256(0x144cec3ddc9fdb04e1b743e1796d4497481b288bcb5662c8a814a36c91bba8a0),
|
|
53
|
+
y: uint256(0x1d44c2a0edb5be481f690aec0ec7b4d7d87fd015b326489b27c84b3395d52ada)
|
|
49
54
|
}),
|
|
50
|
-
|
|
51
|
-
x: uint256(
|
|
52
|
-
y: uint256(
|
|
55
|
+
qMemory: Honk.G1Point({
|
|
56
|
+
x: uint256(0x1e32e3ddee17d0311af427f8a0c8c93ec03ee2552422e518956c914986f265ae),
|
|
57
|
+
y: uint256(0x21c1a895c48d67a0806a93b3b0c10e328cb81ac4d9770751d6d5034d765f2e75)
|
|
53
58
|
}),
|
|
54
|
-
|
|
55
|
-
x: uint256(
|
|
56
|
-
y: uint256(
|
|
59
|
+
qNnf: Honk.G1Point({
|
|
60
|
+
x: uint256(0x0d1378ced79a95272e49ca049e2d78a65681cf80bbe9b787bd2c086d4faf0236),
|
|
61
|
+
y: uint256(0x11e74523e66d06f858126bc5f3ddec4fc024ae8ebccedb2c782cfe3470a14f0d)
|
|
57
62
|
}),
|
|
58
63
|
qPoseidon2External: Honk.G1Point({
|
|
59
|
-
x: uint256(
|
|
60
|
-
y: uint256(
|
|
64
|
+
x: uint256(0x175ce7120e83243b00df020161b054ee52cef7e5c43ae9ed68d3ec1c31577e09),
|
|
65
|
+
y: uint256(0x014b2421ff7e799e69cd24e4ed9bf0b4c38b3f1bfede670cfd0a1bc143534c44)
|
|
61
66
|
}),
|
|
62
67
|
qPoseidon2Internal: Honk.G1Point({
|
|
63
|
-
x: uint256(
|
|
64
|
-
y: uint256(
|
|
68
|
+
x: uint256(0x103f2560ed9a91a0d4dffa3ba8602815aa588ff32b5747719c0e6210240fc6f5),
|
|
69
|
+
y: uint256(0x2b28cd08de4e88139da28d5ce5a7ebd5e465a873d0b6069d40a9907adb9401fb)
|
|
65
70
|
}),
|
|
66
71
|
s1: Honk.G1Point({
|
|
67
|
-
x: uint256(
|
|
68
|
-
y: uint256(
|
|
72
|
+
x: uint256(0x1effc069e3b7481d0a43665103f4a2680f4b65f53a59021953ab20862b24e29a),
|
|
73
|
+
y: uint256(0x00ae13c105d82c1ff5ca3cdd30c912e6fb24afb1893dd12f9c145a6c33ac6185)
|
|
69
74
|
}),
|
|
70
75
|
s2: Honk.G1Point({
|
|
71
|
-
x: uint256(
|
|
72
|
-
y: uint256(
|
|
76
|
+
x: uint256(0x0f7f10529e5aae1e1e112792aa80e7707906f4f536fc96ffc7bc25774e9dba11),
|
|
77
|
+
y: uint256(0x2d1811e9ffa00409d48af6eeff991c6866765fcffd1863160c5c485c7bb6e923)
|
|
73
78
|
}),
|
|
74
79
|
s3: Honk.G1Point({
|
|
75
|
-
x: uint256(
|
|
76
|
-
y: uint256(
|
|
80
|
+
x: uint256(0x257ee866e0c29c215e6379e784c662b59c214d687a0363934ef9c5c0a3331e59),
|
|
81
|
+
y: uint256(0x2f06bdee150a0dce94e73d65c819a345d07f4d146213d766b570bf2d82675078)
|
|
77
82
|
}),
|
|
78
83
|
s4: Honk.G1Point({
|
|
79
|
-
x: uint256(
|
|
80
|
-
y: uint256(
|
|
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(
|
|
92
|
-
y: uint256(
|
|
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(
|
|
100
|
-
y: uint256(
|
|
104
|
+
x: uint256(0x19f9495c2d7164bf4ffab93784be18f18967a11e13a767be733f5bef9d114231),
|
|
105
|
+
y: uint256(0x11d56b79e7120211adec0d6b193584d9334f869a77a5ef4a29fe921c0d736469)
|
|
101
106
|
}),
|
|
102
107
|
id2: Honk.G1Point({
|
|
103
|
-
x: uint256(
|
|
104
|
-
y: uint256(
|
|
108
|
+
x: uint256(0x09843d6144239130855e359ebd182f506f038d894d75d4e670905e1ffcda9604),
|
|
109
|
+
y: uint256(0x0ec072a3e7b76b24db376094d63714c6627409d02b367881ae052a33fc4fdbcf)
|
|
105
110
|
}),
|
|
106
111
|
id3: Honk.G1Point({
|
|
107
|
-
x: uint256(
|
|
108
|
-
y: uint256(
|
|
112
|
+
x: uint256(0x277c18d61cf5c0872161a3223757324ce2ecc98f1dc98d03de20012b4d776ac8),
|
|
113
|
+
y: uint256(0x21591d35c338d60b8de7b9290653dcbd2c04e93c583791f6de6a2248905a224e)
|
|
109
114
|
}),
|
|
110
115
|
id4: Honk.G1Point({
|
|
111
|
-
x: uint256(
|
|
112
|
-
y: uint256(
|
|
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(
|
|
120
|
-
y: uint256(
|
|
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
|
-
|
|
160
|
+
unchecked {
|
|
161
|
+
return Fr.wrap(value % MODULUS);
|
|
162
|
+
}
|
|
156
163
|
}
|
|
157
164
|
|
|
158
165
|
function fromBytes32(bytes32 value) internal pure returns (Fr) {
|
|
159
|
-
|
|
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
|
-
|
|
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
|
-
|
|
226
|
+
unchecked {
|
|
227
|
+
return numerator * invert(denominator);
|
|
228
|
+
}
|
|
214
229
|
}
|
|
215
230
|
|
|
216
231
|
function sqr(Fr value) internal pure returns (Fr) {
|
|
217
|
-
|
|
232
|
+
unchecked {
|
|
233
|
+
return value * value;
|
|
234
|
+
}
|
|
218
235
|
}
|
|
219
236
|
|
|
220
237
|
function unwrap(Fr value) internal pure returns (uint256) {
|
|
221
|
-
|
|
238
|
+
unchecked {
|
|
239
|
+
return Fr.unwrap(value);
|
|
240
|
+
}
|
|
222
241
|
}
|
|
223
242
|
|
|
224
243
|
function neg(Fr value) internal pure returns (Fr) {
|
|
225
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
265
|
-
uint256 constant NUMBER_UNSHIFTED =
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
412
|
+
G1Point w1;
|
|
413
|
+
G1Point w2;
|
|
414
|
+
G1Point w3;
|
|
415
|
+
G1Point w4;
|
|
387
416
|
// Lookup helpers - Permutations
|
|
388
|
-
|
|
417
|
+
G1Point zPerm;
|
|
389
418
|
// Lookup helpers - logup
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
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
|
-
|
|
426
|
+
G1Point[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms;
|
|
398
427
|
Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations;
|
|
399
|
-
|
|
400
|
-
|
|
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
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
436
|
+
G1Point w1;
|
|
437
|
+
G1Point w2;
|
|
438
|
+
G1Point w3;
|
|
439
|
+
G1Point w4;
|
|
411
440
|
// Commitments to logup witness polynomials
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
441
|
+
G1Point lookupReadCounts;
|
|
442
|
+
G1Point lookupReadTags;
|
|
443
|
+
G1Point lookupInverses;
|
|
415
444
|
// Commitment to grand permutation polynomial
|
|
416
|
-
|
|
417
|
-
|
|
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
|
-
|
|
453
|
+
G1Point geminiMaskingPoly;
|
|
425
454
|
Fr geminiMaskingEval;
|
|
426
455
|
// Shplemini
|
|
427
|
-
|
|
456
|
+
G1Point[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms;
|
|
428
457
|
Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations;
|
|
429
458
|
Fr[4] libraPolyEvals;
|
|
430
|
-
|
|
431
|
-
|
|
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
|
|
484
|
+
uint256 vkHash,
|
|
456
485
|
uint256 publicInputsSize,
|
|
457
|
-
uint256
|
|
458
|
-
) internal
|
|
486
|
+
uint256 logN
|
|
487
|
+
) internal view returns (Transcript memory t) {
|
|
459
488
|
Fr previousChallenge;
|
|
460
|
-
(t.relationParameters, previousChallenge) =
|
|
461
|
-
proof, publicInputs,
|
|
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
|
|
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,
|
|
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
|
|
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[](
|
|
511
|
-
round0[0] = bytes32(
|
|
512
|
-
|
|
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[
|
|
540
|
+
round0[1 + i] = bytes32(publicInputs[i]);
|
|
516
541
|
}
|
|
517
542
|
for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) {
|
|
518
|
-
round0[
|
|
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[
|
|
524
|
-
round0[
|
|
525
|
-
round0[
|
|
526
|
-
round0[
|
|
527
|
-
round0[
|
|
528
|
-
round0[
|
|
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[
|
|
568
|
+
bytes32[7] memory round1;
|
|
549
569
|
round1[0] = FrLib.toBytes32(previousChallenge);
|
|
550
|
-
round1[1] = bytes32(proof.lookupReadCounts.
|
|
551
|
-
round1[2] = bytes32(proof.lookupReadCounts.
|
|
552
|
-
round1[3] = bytes32(proof.
|
|
553
|
-
round1[4] = bytes32(proof.
|
|
554
|
-
round1[5] = bytes32(proof.
|
|
555
|
-
round1[6] = bytes32(proof.
|
|
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[
|
|
588
|
+
uint256[5] memory alpha0;
|
|
575
589
|
alpha0[0] = Fr.unwrap(previousChallenge);
|
|
576
|
-
alpha0[1] = proof.lookupInverses.
|
|
577
|
-
alpha0[2] = proof.lookupInverses.
|
|
578
|
-
alpha0[3] = proof.
|
|
579
|
-
alpha0[4] = proof.
|
|
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 <
|
|
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 <
|
|
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[(
|
|
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 <
|
|
657
|
-
gR[1 + i *
|
|
658
|
-
gR[2 + i *
|
|
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[(
|
|
681
|
+
uint256[] memory shplonkNuChallengeElements = new uint256[](logN + 1);
|
|
674
682
|
shplonkNuChallengeElements[0] = Fr.unwrap(prevChallenge);
|
|
675
683
|
|
|
676
|
-
for (uint256 i = 0; 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
|
-
|
|
695
|
+
view
|
|
688
696
|
returns (Fr shplonkZ, Fr nextPreviousChallenge)
|
|
689
697
|
{
|
|
690
|
-
uint256[
|
|
698
|
+
uint256[3] memory shplonkZChallengeElements;
|
|
691
699
|
shplonkZChallengeElements[0] = Fr.unwrap(prevChallenge);
|
|
692
700
|
|
|
693
|
-
shplonkZChallengeElements[1] = proof.shplonkQ.
|
|
694
|
-
shplonkZChallengeElements[2] = proof.shplonkQ.
|
|
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 =
|
|
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 +
|
|
709
|
-
boundary +=
|
|
714
|
+
p.pairingPointObject[i] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]);
|
|
715
|
+
boundary += FIELD_ELEMENT_SIZE;
|
|
710
716
|
}
|
|
711
717
|
// Commitments
|
|
712
|
-
p.w1 =
|
|
713
|
-
boundary +=
|
|
714
|
-
p.w2 =
|
|
715
|
-
boundary +=
|
|
716
|
-
p.w3 =
|
|
717
|
-
boundary +=
|
|
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 =
|
|
721
|
-
boundary +=
|
|
722
|
-
p.lookupReadTags =
|
|
723
|
-
boundary +=
|
|
724
|
-
p.w4 =
|
|
725
|
-
boundary +=
|
|
726
|
-
p.lookupInverses =
|
|
727
|
-
boundary +=
|
|
728
|
-
p.zPerm =
|
|
729
|
-
boundary +=
|
|
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 <
|
|
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 +
|
|
735
|
-
boundary +=
|
|
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 +
|
|
741
|
-
boundary +=
|
|
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 <
|
|
747
|
-
p.geminiFoldComms[i] =
|
|
748
|
-
boundary +=
|
|
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 <
|
|
753
|
-
p.geminiAEvaluations[i] = bytesToFr(proof[boundary:boundary +
|
|
754
|
-
boundary +=
|
|
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 =
|
|
759
|
-
boundary +=
|
|
764
|
+
p.shplonkQ = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]);
|
|
765
|
+
boundary += GROUP_ELEMENT_SIZE;
|
|
760
766
|
// KZG
|
|
761
|
-
p.kzgQuotient =
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
|
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
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
1294
|
-
evals[17] = ap.index_is_monotonically_increasing * (wire(p, WIRE.
|
|
1295
|
-
evals[18] = ap.next_gate_access_type_is_boolean * (wire(p, WIRE.
|
|
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.
|
|
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.
|
|
1326
|
-
|
|
1327
|
-
|
|
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[
|
|
1406
|
+
evals[20] = evals[20] + ep.q_pos_by_scaling * (ep.v1 - wire(p, WIRE.W_L_SHIFT));
|
|
1384
1407
|
|
|
1385
|
-
evals[
|
|
1408
|
+
evals[21] = evals[21] + ep.q_pos_by_scaling * (ep.v2 - wire(p, WIRE.W_R_SHIFT));
|
|
1386
1409
|
|
|
1387
|
-
evals[
|
|
1410
|
+
evals[22] = evals[22] + ep.q_pos_by_scaling * (ep.v3 - wire(p, WIRE.W_O_SHIFT));
|
|
1388
1411
|
|
|
1389
|
-
evals[
|
|
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[
|
|
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[
|
|
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[
|
|
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[
|
|
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[
|
|
1510
|
+
Fr[] foldPosEvaluations;
|
|
1486
1511
|
}
|
|
1487
1512
|
|
|
1488
|
-
function computeSquares(Fr r) internal pure returns (Fr[
|
|
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 <
|
|
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[
|
|
1527
|
+
Fr[] memory geminiEvalChallengePowers,
|
|
1501
1528
|
uint256 logSize
|
|
1502
|
-
) internal view returns (Fr[
|
|
1503
|
-
|
|
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
|
-
|
|
1548
|
-
|
|
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
|
-
//
|
|
1614
|
-
uint256 constant
|
|
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 !=
|
|
1621
|
-
revert
|
|
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,
|
|
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(
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
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[
|
|
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[
|
|
1784
|
-
Honk.G1Point[
|
|
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] =
|
|
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.
|
|
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
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
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.
|
|
1849
|
-
commitments[12] = vk.
|
|
1850
|
-
commitments[13] = vk.
|
|
1851
|
-
commitments[14] = vk.
|
|
1852
|
-
commitments[15] = vk.
|
|
1853
|
-
commitments[16] = vk.
|
|
1854
|
-
commitments[17] = vk.
|
|
1855
|
-
commitments[18] = vk.
|
|
1856
|
-
commitments[19] = vk.
|
|
1857
|
-
commitments[20] = vk.
|
|
1858
|
-
commitments[21] = vk.
|
|
1859
|
-
commitments[22] = vk.
|
|
1860
|
-
commitments[23] = vk.
|
|
1861
|
-
commitments[24] = vk.
|
|
1862
|
-
commitments[25] = vk.
|
|
1863
|
-
commitments[26] = vk.
|
|
1864
|
-
commitments[27] = vk.
|
|
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[
|
|
1868
|
-
commitments[
|
|
1869
|
-
commitments[
|
|
1870
|
-
commitments[
|
|
1871
|
-
commitments[
|
|
1872
|
-
commitments[
|
|
1873
|
-
commitments[
|
|
1874
|
-
commitments[
|
|
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[
|
|
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 <
|
|
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[
|
|
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[
|
|
2213
|
+
commitments[NUMBER_UNSHIFTED + 1 + i] = proof.geminiFoldComms[i];
|
|
1948
2214
|
}
|
|
1949
2215
|
|
|
1950
2216
|
// Finalise the batch opening claim
|
|
1951
|
-
commitments[
|
|
1952
|
-
scalars[
|
|
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
|
-
|
|
2222
|
+
commitments[NUMBER_UNSHIFTED + $LOG_N + 1] = quotient_commitment;
|
|
2223
|
+
scalars[NUMBER_UNSHIFTED + $LOG_N + 1] = tp.shplonkZ; // evaluation challenge
|
|
1955
2224
|
|
|
1956
|
-
|
|
1957
|
-
|
|
2225
|
+
Honk.G1Point memory P_0_agg = batchMul(commitments, scalars);
|
|
2226
|
+
Honk.G1Point memory P_1_agg = negateInplace(quotient_commitment);
|
|
1958
2227
|
|
|
1959
|
-
|
|
1960
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
uint256 limit =
|
|
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
|
|
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
|
}
|