@aztec/ivc-integration 4.0.0-devnet.1-patch.0 → 4.0.0-devnet.2-patch.0
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 +6 -6
- package/artifacts/app_reader.json +6 -6
- package/artifacts/keys/mock_rollup_root_verifier.sol +331 -309
- package/artifacts/mock_hiding.json +2 -2
- package/artifacts/mock_private_kernel_init.json +2 -2
- package/artifacts/mock_private_kernel_inner.json +2 -2
- package/artifacts/mock_private_kernel_reset.json +2 -2
- package/artifacts/mock_private_kernel_tail.json +2 -2
- package/artifacts/mock_rollup_root.json +48 -48
- package/artifacts/mock_rollup_tx_base_private.json +92 -92
- package/artifacts/mock_rollup_tx_base_public.json +94 -94
- package/artifacts/mock_rollup_tx_merge.json +92 -92
- package/dest/types/index.d.ts +2 -2
- package/package.json +16 -16
- package/src/types/index.ts +2 -2
|
@@ -5,7 +5,7 @@ pragma solidity >=0.8.21;
|
|
|
5
5
|
uint256 constant N = 16777216;
|
|
6
6
|
uint256 constant LOG_N = 24;
|
|
7
7
|
uint256 constant NUMBER_OF_PUBLIC_INPUTS = 9;
|
|
8
|
-
uint256 constant VK_HASH =
|
|
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({
|
|
@@ -13,76 +13,76 @@ library HonkVerificationKey {
|
|
|
13
13
|
logCircuitSize: uint256(24),
|
|
14
14
|
publicInputsSize: uint256(9),
|
|
15
15
|
ql: Honk.G1Point({
|
|
16
|
-
x: uint256(
|
|
17
|
-
y: uint256(
|
|
16
|
+
x: uint256(0x288949ddd65c505eb5cc75f154e5758f88ffca8d2b27ecec1a8c18d64836555e),
|
|
17
|
+
y: uint256(0x16bdc5f6b2acfec698224a75fb369f408f10203d39d18c59f1e7fd2a06cd203e)
|
|
18
18
|
}),
|
|
19
19
|
qr: Honk.G1Point({
|
|
20
|
-
x: uint256(
|
|
21
|
-
y: uint256(
|
|
20
|
+
x: uint256(0x0f00e9b07cdc3cb5ec6c7f0c3f015d52b77d22309cb6ce0231a4969c4ac47488),
|
|
21
|
+
y: uint256(0x173daa0ad01139b438315c03c09114c7054ed90ff4562466afb6e2cc48d69eae)
|
|
22
22
|
}),
|
|
23
23
|
qo: Honk.G1Point({
|
|
24
|
-
x: uint256(
|
|
25
|
-
y: uint256(
|
|
24
|
+
x: uint256(0x2158a434ef091cbe48d362fda5c78de82eaaac1227a0c411ea21ad7c7d09bb89),
|
|
25
|
+
y: uint256(0x11e9f2ece557a9ab50b059decabaa2c3e102080b7389aa51335094c527a4399b)
|
|
26
26
|
}),
|
|
27
27
|
q4: Honk.G1Point({
|
|
28
|
-
x: uint256(
|
|
29
|
-
y: uint256(
|
|
28
|
+
x: uint256(0x0b4c24c473fadd17b6fc761b52fc51cabd6dfb6b93a889128f7d5443d76b4e37),
|
|
29
|
+
y: uint256(0x2bcbb260096016d41e7b099758e6c7a4b2487a30728fa877f64163da404d2aa6)
|
|
30
30
|
}),
|
|
31
31
|
qm: Honk.G1Point({
|
|
32
|
-
x: uint256(
|
|
33
|
-
y: uint256(
|
|
32
|
+
x: uint256(0x305785ae74b36fc97f5cfbfcd19e965f14c3cb5fc07a866b4da8c40dfa43ea09),
|
|
33
|
+
y: uint256(0x1c618b8fb74db18bb65237cd45de3060ae7abd8931f5d6fbc0a3d18019f9a34c)
|
|
34
34
|
}),
|
|
35
35
|
qc: Honk.G1Point({
|
|
36
|
-
x: uint256(
|
|
37
|
-
y: uint256(
|
|
36
|
+
x: uint256(0x1e7d370a010cbec0e4a7a5be0832a59a0ed151216aa2ef780e40945770f04256),
|
|
37
|
+
y: uint256(0x19645746fcec15c93f0b8f620fbaf63b2d973d174b52ac8dc006b0292bc4d75a)
|
|
38
38
|
}),
|
|
39
39
|
qLookup: Honk.G1Point({
|
|
40
40
|
x: uint256(0x22011c91613251ef53fd12a397e4bd6165b1ed309dcd94b33ac4226d34b68889),
|
|
41
41
|
y: uint256(0x1fb02875a3542a3a6f4426ad912b70cf32b444a8e439701da6e8e7b30029cfc7)
|
|
42
42
|
}),
|
|
43
43
|
qArith: Honk.G1Point({
|
|
44
|
-
x: uint256(
|
|
45
|
-
y: uint256(
|
|
44
|
+
x: uint256(0x1d87e7db98f2289def77fcd6917b3195a04c8ea4fba2fbecb4953d53e2a5fa5e),
|
|
45
|
+
y: uint256(0x1e747aa5ce9c23534fba30d6fb86e148f55ff741cdc40aa72669b48fae5e78da)
|
|
46
46
|
}),
|
|
47
47
|
qDeltaRange: Honk.G1Point({
|
|
48
|
-
x: uint256(
|
|
49
|
-
y: uint256(
|
|
48
|
+
x: uint256(0x197382111c5e19efd384fad7b441ab910eea06a90e613c0ac1d3558d5d1fe9bb),
|
|
49
|
+
y: uint256(0x2409d8e704a1df2a931db78f4b9eff415259f325e2c1d91752018ca1367bc813)
|
|
50
50
|
}),
|
|
51
51
|
qElliptic: Honk.G1Point({
|
|
52
|
-
x: uint256(
|
|
53
|
-
y: uint256(
|
|
52
|
+
x: uint256(0x2f7bf7a96beccc2dcb1c979e895a5cf553347e85d3f09ac4ad25968c48ee6c0f),
|
|
53
|
+
y: uint256(0x0b9eb2604a17d6ee22545ecefc418886ee29c45e1f367a73781af51b70b5e59a)
|
|
54
54
|
}),
|
|
55
55
|
qMemory: Honk.G1Point({
|
|
56
|
-
x: uint256(
|
|
57
|
-
y: uint256(
|
|
56
|
+
x: uint256(0x067081ee7301cf94893b575b8a4607a50631612578b3230b0f63434e6ec1dcf3),
|
|
57
|
+
y: uint256(0x12e2288cdb86fd9caa98689e3ad9926b0372d1e7afeeb1ec6f7b251a176eb3e1)
|
|
58
58
|
}),
|
|
59
59
|
qNnf: Honk.G1Point({
|
|
60
|
-
x: uint256(
|
|
61
|
-
y: uint256(
|
|
60
|
+
x: uint256(0x303e26adafa2a01b02f559580ab06f571fe0f80473552ea7f4a47255af7b25f3),
|
|
61
|
+
y: uint256(0x2f599def60b1f4640366dba9daaf25de7a311eed3243dd96004ef5cb76dd4eef)
|
|
62
62
|
}),
|
|
63
63
|
qPoseidon2External: Honk.G1Point({
|
|
64
|
-
x: uint256(
|
|
65
|
-
y: uint256(
|
|
64
|
+
x: uint256(0x26c42fb5290e1f109c68ae1aadb78005efbe391925d37ff2682eb2fb9f673d81),
|
|
65
|
+
y: uint256(0x23d32838bb651192c72a84f8d35ad9ed23bfc60bd6a95aafe5f400ac79bb91a6)
|
|
66
66
|
}),
|
|
67
67
|
qPoseidon2Internal: Honk.G1Point({
|
|
68
|
-
x: uint256(
|
|
69
|
-
y: uint256(
|
|
68
|
+
x: uint256(0x0e257562358c0fa333e2e92fb24893b10b6606582657ac902463c4125a8d76b4),
|
|
69
|
+
y: uint256(0x0a45aedd100c830266aa7501650f16d4c1a340da32528e2dc0ffcfe01de89c65)
|
|
70
70
|
}),
|
|
71
71
|
s1: Honk.G1Point({
|
|
72
|
-
x: uint256(
|
|
73
|
-
y: uint256(
|
|
72
|
+
x: uint256(0x157c4a46714f7cc4bd0065ac8726ead6d925e1c3e2cb03ec167bde135d933eeb),
|
|
73
|
+
y: uint256(0x191e130de881a7b6a3560a6dc7f8f517abcc324c5f16b8e4dc901d5079ec7387)
|
|
74
74
|
}),
|
|
75
75
|
s2: Honk.G1Point({
|
|
76
|
-
x: uint256(
|
|
77
|
-
y: uint256(
|
|
76
|
+
x: uint256(0x0d02a27696ba0a08b32422113dc489b15acc111cb2fcd7f674ef4b903adcbdb3),
|
|
77
|
+
y: uint256(0x03499c1fd603f04963deab2fdbb152e7d8f88267d6ca8c817eea2643e608de29)
|
|
78
78
|
}),
|
|
79
79
|
s3: Honk.G1Point({
|
|
80
|
-
x: uint256(
|
|
81
|
-
y: uint256(
|
|
80
|
+
x: uint256(0x19c00dd88d170187c1717dfa303fe1c20604decf14cc58c4d6fe9ab346ae3f67),
|
|
81
|
+
y: uint256(0x0e3991d6fd47060ba758b4ed58736ffd3f082af15af7b84fafe5041b568dcff2)
|
|
82
82
|
}),
|
|
83
83
|
s4: Honk.G1Point({
|
|
84
|
-
x: uint256(
|
|
85
|
-
y: uint256(
|
|
84
|
+
x: uint256(0x2ddedcc10b1b78151f4638978bc1ed9ceafa34911d7c8a2ffcdecc092f5f53bd),
|
|
85
|
+
y: uint256(0x2fee038cad71230c95a0497bd2a116171a431193a214d5a9677570fa45de2fda)
|
|
86
86
|
}),
|
|
87
87
|
t1: Honk.G1Point({
|
|
88
88
|
x: uint256(0x099e3bd5a0a00ab7fe18040105b9b395b5d8b7b4a63b05df652b0d10ef146d26),
|
|
@@ -101,28 +101,28 @@ library HonkVerificationKey {
|
|
|
101
101
|
y: uint256(0x261522c4089330646aff96736194949330952ae74c573d1686d9cb4a00733854)
|
|
102
102
|
}),
|
|
103
103
|
id1: Honk.G1Point({
|
|
104
|
-
x: uint256(
|
|
105
|
-
y: uint256(
|
|
104
|
+
x: uint256(0x11a02b4dd65f30c8d3b70888267f766e6abaaa0a1a5ad0bfa8cb1b597fedc630),
|
|
105
|
+
y: uint256(0x195cb3d252708ee60a385f0a3a84167322910971be20715e2965a4d97c1d1084)
|
|
106
106
|
}),
|
|
107
107
|
id2: Honk.G1Point({
|
|
108
|
-
x: uint256(
|
|
109
|
-
y: uint256(
|
|
108
|
+
x: uint256(0x2a775e6191621460b6ae8f22d1cef5f92ec91bf820478d9619fc74d4e2956801),
|
|
109
|
+
y: uint256(0x057c47f7fa5fdfe685bd62595390454071e5749841dbabb0bcd45aee00ac9af7)
|
|
110
110
|
}),
|
|
111
111
|
id3: Honk.G1Point({
|
|
112
|
-
x: uint256(
|
|
113
|
-
y: uint256(
|
|
112
|
+
x: uint256(0x2ae753680356fd3211ca6b4210fe2682ebacc40d78c1ac3319be365682860bbd),
|
|
113
|
+
y: uint256(0x18aa3b045ae71c20a8b673b91ccf5ea61ba25bff9c958f9bad138e7e126a257a)
|
|
114
114
|
}),
|
|
115
115
|
id4: Honk.G1Point({
|
|
116
|
-
x: uint256(
|
|
117
|
-
y: uint256(
|
|
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(
|
|
125
|
-
y: uint256(
|
|
124
|
+
x: uint256(0x04a0bdd0751a2184a98670fd8df17f372fac62b55691c8232c1484f51282cd7e),
|
|
125
|
+
y: uint256(0x121349b0521c633e5b12c42ec4f8cb0c1a3bdadcafe6350d901ae7cf13e7b5bd)
|
|
126
126
|
})
|
|
127
127
|
});
|
|
128
128
|
return vk;
|
|
@@ -135,13 +135,37 @@ interface IVerifier {
|
|
|
135
135
|
function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool);
|
|
136
136
|
}
|
|
137
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();
|
|
161
|
+
}
|
|
162
|
+
|
|
138
163
|
type Fr is uint256;
|
|
139
164
|
|
|
140
165
|
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
|
-
|
|
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
|
-
|
|
202
|
+
mstore(0x00, FRLIB_MODEXP_FAILED_SELECTOR)
|
|
203
|
+
revert(0, 0x04)
|
|
193
204
|
}
|
|
194
205
|
result := mload(0x00)
|
|
195
|
-
mstore(0x40, add(free,
|
|
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
|
-
|
|
229
|
+
mstore(0x00, FRLIB_MODEXP_FAILED_SELECTOR)
|
|
230
|
+
revert(0, 0x04)
|
|
217
231
|
}
|
|
218
232
|
result := mload(0x00)
|
|
219
|
-
mstore(0x40, add(free,
|
|
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);
|
|
@@ -486,7 +512,7 @@ library TranscriptLib {
|
|
|
486
512
|
uint256 vkHash,
|
|
487
513
|
uint256 publicInputsSize,
|
|
488
514
|
uint256 logN
|
|
489
|
-
) internal
|
|
515
|
+
) internal pure returns (Transcript memory t) {
|
|
490
516
|
Fr previousChallenge;
|
|
491
517
|
(t.relationParameters, previousChallenge) =
|
|
492
518
|
generateRelationParametersChallenges(proof, publicInputs, vkHash, publicInputsSize, previousChallenge);
|
|
@@ -513,8 +539,8 @@ library TranscriptLib {
|
|
|
513
539
|
// Split into two equal 127-bit chunks (254/2)
|
|
514
540
|
uint256 lo = challengeU256 & 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // 127 bits
|
|
515
541
|
uint256 hi = challengeU256 >> 127;
|
|
516
|
-
first = FrLib.
|
|
517
|
-
second = FrLib.
|
|
542
|
+
first = FrLib.from(lo);
|
|
543
|
+
second = FrLib.from(hi);
|
|
518
544
|
}
|
|
519
545
|
|
|
520
546
|
function generateRelationParametersChallenges(
|
|
@@ -539,7 +565,8 @@ library TranscriptLib {
|
|
|
539
565
|
round0[0] = bytes32(vkHash);
|
|
540
566
|
|
|
541
567
|
for (uint256 i = 0; i < publicInputsSize - PAIRING_POINTS_SIZE; i++) {
|
|
542
|
-
|
|
568
|
+
require(uint256(publicInputs[i]) < P, Errors.ValueGeFieldOrder());
|
|
569
|
+
round0[1 + i] = publicInputs[i];
|
|
543
570
|
}
|
|
544
571
|
for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) {
|
|
545
572
|
round0[1 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]);
|
|
@@ -554,7 +581,7 @@ library TranscriptLib {
|
|
|
554
581
|
round0[1 + publicInputsSize + 4] = bytes32(proof.w3.x);
|
|
555
582
|
round0[1 + publicInputsSize + 5] = bytes32(proof.w3.y);
|
|
556
583
|
|
|
557
|
-
previousChallenge = FrLib.
|
|
584
|
+
previousChallenge = FrLib.from(uint256(keccak256(abi.encodePacked(round0))) % P);
|
|
558
585
|
(eta,) = splitChallenge(previousChallenge);
|
|
559
586
|
}
|
|
560
587
|
|
|
@@ -572,7 +599,7 @@ library TranscriptLib {
|
|
|
572
599
|
round1[5] = bytes32(proof.w4.x);
|
|
573
600
|
round1[6] = bytes32(proof.w4.y);
|
|
574
601
|
|
|
575
|
-
nextPreviousChallenge = FrLib.
|
|
602
|
+
nextPreviousChallenge = FrLib.from(uint256(keccak256(abi.encodePacked(round1))) % P);
|
|
576
603
|
(beta, gamma) = splitChallenge(nextPreviousChallenge);
|
|
577
604
|
}
|
|
578
605
|
|
|
@@ -590,7 +617,7 @@ library TranscriptLib {
|
|
|
590
617
|
alpha0[3] = proof.zPerm.x;
|
|
591
618
|
alpha0[4] = proof.zPerm.y;
|
|
592
619
|
|
|
593
|
-
nextPreviousChallenge = FrLib.
|
|
620
|
+
nextPreviousChallenge = FrLib.from(uint256(keccak256(abi.encodePacked(alpha0))) % P);
|
|
594
621
|
Fr alpha;
|
|
595
622
|
(alpha,) = splitChallenge(nextPreviousChallenge);
|
|
596
623
|
|
|
@@ -606,7 +633,7 @@ library TranscriptLib {
|
|
|
606
633
|
pure
|
|
607
634
|
returns (Fr[CONST_PROOF_SIZE_LOG_N] memory gateChallenges, Fr nextPreviousChallenge)
|
|
608
635
|
{
|
|
609
|
-
previousChallenge = FrLib.
|
|
636
|
+
previousChallenge = FrLib.from(uint256(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))) % P);
|
|
610
637
|
(gateChallenges[0],) = splitChallenge(previousChallenge);
|
|
611
638
|
for (uint256 i = 1; i < logN; i++) {
|
|
612
639
|
gateChallenges[i] = gateChallenges[i - 1] * gateChallenges[i - 1];
|
|
@@ -626,7 +653,7 @@ library TranscriptLib {
|
|
|
626
653
|
for (uint256 j = 0; j < BATCHED_RELATION_PARTIAL_LENGTH; j++) {
|
|
627
654
|
univariateChal[j + 1] = proof.sumcheckUnivariates[i][j];
|
|
628
655
|
}
|
|
629
|
-
prevChallenge = FrLib.
|
|
656
|
+
prevChallenge = FrLib.from(uint256(keccak256(abi.encodePacked(univariateChal))) % P);
|
|
630
657
|
Fr unused;
|
|
631
658
|
(sumcheckChallenges[i], unused) = splitChallenge(prevChallenge);
|
|
632
659
|
}
|
|
@@ -645,7 +672,7 @@ library TranscriptLib {
|
|
|
645
672
|
rhoChallengeElements[i + 1] = proof.sumcheckEvaluations[i];
|
|
646
673
|
}
|
|
647
674
|
|
|
648
|
-
nextPreviousChallenge = FrLib.
|
|
675
|
+
nextPreviousChallenge = FrLib.from(uint256(keccak256(abi.encodePacked(rhoChallengeElements))) % P);
|
|
649
676
|
Fr unused;
|
|
650
677
|
(rho, unused) = splitChallenge(nextPreviousChallenge);
|
|
651
678
|
}
|
|
@@ -663,7 +690,7 @@ library TranscriptLib {
|
|
|
663
690
|
gR[2 + i * 2] = proof.geminiFoldComms[i].y;
|
|
664
691
|
}
|
|
665
692
|
|
|
666
|
-
nextPreviousChallenge = FrLib.
|
|
693
|
+
nextPreviousChallenge = FrLib.from(uint256(keccak256(abi.encodePacked(gR))) % P);
|
|
667
694
|
Fr unused;
|
|
668
695
|
(geminiR, unused) = splitChallenge(nextPreviousChallenge);
|
|
669
696
|
}
|
|
@@ -680,14 +707,14 @@ library TranscriptLib {
|
|
|
680
707
|
shplonkNuChallengeElements[i + 1] = Fr.unwrap(proof.geminiAEvaluations[i]);
|
|
681
708
|
}
|
|
682
709
|
|
|
683
|
-
nextPreviousChallenge = FrLib.
|
|
710
|
+
nextPreviousChallenge = FrLib.from(uint256(keccak256(abi.encodePacked(shplonkNuChallengeElements))) % P);
|
|
684
711
|
Fr unused;
|
|
685
712
|
(shplonkNu, unused) = splitChallenge(nextPreviousChallenge);
|
|
686
713
|
}
|
|
687
714
|
|
|
688
715
|
function generateShplonkZChallenge(Honk.Proof memory proof, Fr prevChallenge)
|
|
689
716
|
internal
|
|
690
|
-
|
|
717
|
+
pure
|
|
691
718
|
returns (Fr shplonkZ, Fr nextPreviousChallenge)
|
|
692
719
|
{
|
|
693
720
|
uint256[3] memory shplonkZChallengeElements;
|
|
@@ -696,7 +723,7 @@ library TranscriptLib {
|
|
|
696
723
|
shplonkZChallengeElements[1] = proof.shplonkQ.x;
|
|
697
724
|
shplonkZChallengeElements[2] = proof.shplonkQ.y;
|
|
698
725
|
|
|
699
|
-
nextPreviousChallenge = FrLib.
|
|
726
|
+
nextPreviousChallenge = FrLib.from(uint256(keccak256(abi.encodePacked(shplonkZChallengeElements))) % P);
|
|
700
727
|
Fr unused;
|
|
701
728
|
(shplonkZ, unused) = splitChallenge(nextPreviousChallenge);
|
|
702
729
|
}
|
|
@@ -706,7 +733,10 @@ library TranscriptLib {
|
|
|
706
733
|
|
|
707
734
|
// Pairing point object
|
|
708
735
|
for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) {
|
|
709
|
-
|
|
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);
|
|
710
740
|
boundary += FIELD_ELEMENT_SIZE;
|
|
711
741
|
}
|
|
712
742
|
// Commitments
|
|
@@ -763,10 +793,91 @@ library TranscriptLib {
|
|
|
763
793
|
}
|
|
764
794
|
}
|
|
765
795
|
|
|
766
|
-
// Field arithmetic libraries
|
|
767
|
-
|
|
768
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
|
+
|
|
769
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);
|
|
770
881
|
|
|
771
882
|
function accumulateRelationEvaluations(
|
|
772
883
|
Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations,
|
|
@@ -800,12 +911,10 @@ library RelationsLib {
|
|
|
800
911
|
return p[uint256(_wire)];
|
|
801
912
|
}
|
|
802
913
|
|
|
803
|
-
uint256 internal constant NEG_HALF_MODULO_P = 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000;
|
|
804
914
|
/**
|
|
805
915
|
* Ultra Arithmetic Relation
|
|
806
916
|
*
|
|
807
917
|
*/
|
|
808
|
-
|
|
809
918
|
function accumulateArithmeticRelation(
|
|
810
919
|
Fr[NUMBER_OF_ENTITIES] memory p,
|
|
811
920
|
Fr[NUMBER_OF_SUBRELATIONS] memory evals,
|
|
@@ -992,18 +1101,6 @@ library RelationsLib {
|
|
|
992
1101
|
}
|
|
993
1102
|
}
|
|
994
1103
|
|
|
995
|
-
struct EllipticParams {
|
|
996
|
-
// Points
|
|
997
|
-
Fr x_1;
|
|
998
|
-
Fr y_1;
|
|
999
|
-
Fr x_2;
|
|
1000
|
-
Fr y_2;
|
|
1001
|
-
Fr y_3;
|
|
1002
|
-
Fr x_3;
|
|
1003
|
-
// push accumulators into memory
|
|
1004
|
-
Fr x_double_identity;
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
1104
|
function accumulateEllipticRelation(
|
|
1008
1105
|
Fr[NUMBER_OF_ENTITIES] memory p,
|
|
1009
1106
|
Fr[NUMBER_OF_SUBRELATIONS] memory evals,
|
|
@@ -1072,26 +1169,6 @@ library RelationsLib {
|
|
|
1072
1169
|
}
|
|
1073
1170
|
}
|
|
1074
1171
|
|
|
1075
|
-
// Parameters used within the Memory Relation
|
|
1076
|
-
// A struct is used to work around stack too deep. This relation has alot of variables
|
|
1077
|
-
struct MemParams {
|
|
1078
|
-
Fr memory_record_check;
|
|
1079
|
-
Fr partial_record_check;
|
|
1080
|
-
Fr next_gate_access_type;
|
|
1081
|
-
Fr record_delta;
|
|
1082
|
-
Fr index_delta;
|
|
1083
|
-
Fr adjacent_values_match_if_adjacent_indices_match;
|
|
1084
|
-
Fr adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation;
|
|
1085
|
-
Fr access_check;
|
|
1086
|
-
Fr next_gate_access_type_is_boolean;
|
|
1087
|
-
Fr ROM_consistency_check_identity;
|
|
1088
|
-
Fr RAM_consistency_check_identity;
|
|
1089
|
-
Fr timestamp_delta;
|
|
1090
|
-
Fr RAM_timestamp_check_identity;
|
|
1091
|
-
Fr memory_identity;
|
|
1092
|
-
Fr index_is_monotonically_increasing;
|
|
1093
|
-
}
|
|
1094
|
-
|
|
1095
1172
|
function accumulateMemoryRelation(
|
|
1096
1173
|
Fr[NUMBER_OF_ENTITIES] memory p,
|
|
1097
1174
|
Honk.RelationParameters memory rp,
|
|
@@ -1261,22 +1338,6 @@ library RelationsLib {
|
|
|
1261
1338
|
evals[13] = ap.memory_identity;
|
|
1262
1339
|
}
|
|
1263
1340
|
|
|
1264
|
-
// Constants for the Non-native Field relation
|
|
1265
|
-
Fr constant LIMB_SIZE = Fr.wrap(uint256(1) << 68);
|
|
1266
|
-
Fr constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14);
|
|
1267
|
-
|
|
1268
|
-
// Parameters used within the Non-Native Field Relation
|
|
1269
|
-
// A struct is used to work around stack too deep. This relation has alot of variables
|
|
1270
|
-
struct NnfParams {
|
|
1271
|
-
Fr limb_subproduct;
|
|
1272
|
-
Fr non_native_field_gate_1;
|
|
1273
|
-
Fr non_native_field_gate_2;
|
|
1274
|
-
Fr non_native_field_gate_3;
|
|
1275
|
-
Fr limb_accumulator_1;
|
|
1276
|
-
Fr limb_accumulator_2;
|
|
1277
|
-
Fr nnf_identity;
|
|
1278
|
-
}
|
|
1279
|
-
|
|
1280
1341
|
function accumulateNnfRelation(
|
|
1281
1342
|
Fr[NUMBER_OF_ENTITIES] memory p,
|
|
1282
1343
|
Fr[NUMBER_OF_SUBRELATIONS] memory evals,
|
|
@@ -1353,26 +1414,6 @@ library RelationsLib {
|
|
|
1353
1414
|
evals[19] = ap.nnf_identity;
|
|
1354
1415
|
}
|
|
1355
1416
|
|
|
1356
|
-
struct PoseidonExternalParams {
|
|
1357
|
-
Fr s1;
|
|
1358
|
-
Fr s2;
|
|
1359
|
-
Fr s3;
|
|
1360
|
-
Fr s4;
|
|
1361
|
-
Fr u1;
|
|
1362
|
-
Fr u2;
|
|
1363
|
-
Fr u3;
|
|
1364
|
-
Fr u4;
|
|
1365
|
-
Fr t0;
|
|
1366
|
-
Fr t1;
|
|
1367
|
-
Fr t2;
|
|
1368
|
-
Fr t3;
|
|
1369
|
-
Fr v1;
|
|
1370
|
-
Fr v2;
|
|
1371
|
-
Fr v3;
|
|
1372
|
-
Fr v4;
|
|
1373
|
-
Fr q_pos_by_scaling;
|
|
1374
|
-
}
|
|
1375
|
-
|
|
1376
1417
|
function accumulatePoseidonExternalRelation(
|
|
1377
1418
|
Fr[NUMBER_OF_ENTITIES] memory p,
|
|
1378
1419
|
Fr[NUMBER_OF_SUBRELATIONS] memory evals,
|
|
@@ -1415,20 +1456,6 @@ library RelationsLib {
|
|
|
1415
1456
|
evals[23] = evals[23] + ep.q_pos_by_scaling * (ep.v4 - wire(p, WIRE.W_4_SHIFT));
|
|
1416
1457
|
}
|
|
1417
1458
|
|
|
1418
|
-
struct PoseidonInternalParams {
|
|
1419
|
-
Fr u1;
|
|
1420
|
-
Fr u2;
|
|
1421
|
-
Fr u3;
|
|
1422
|
-
Fr u4;
|
|
1423
|
-
Fr u_sum;
|
|
1424
|
-
Fr v1;
|
|
1425
|
-
Fr v2;
|
|
1426
|
-
Fr v3;
|
|
1427
|
-
Fr v4;
|
|
1428
|
-
Fr s1;
|
|
1429
|
-
Fr q_pos_by_scaling;
|
|
1430
|
-
}
|
|
1431
|
-
|
|
1432
1459
|
function accumulatePoseidonInternalRelation(
|
|
1433
1460
|
Fr[NUMBER_OF_ENTITIES] memory p,
|
|
1434
1461
|
Fr[NUMBER_OF_SUBRELATIONS] memory evals,
|
|
@@ -1484,8 +1511,6 @@ library RelationsLib {
|
|
|
1484
1511
|
}
|
|
1485
1512
|
}
|
|
1486
1513
|
|
|
1487
|
-
// Field arithmetic libraries - prevent littering the code with modmul / addmul
|
|
1488
|
-
|
|
1489
1514
|
library CommitmentSchemeLib {
|
|
1490
1515
|
using FrLib for Fr;
|
|
1491
1516
|
|
|
@@ -1515,16 +1540,7 @@ library CommitmentSchemeLib {
|
|
|
1515
1540
|
Fr[] foldPosEvaluations;
|
|
1516
1541
|
}
|
|
1517
1542
|
|
|
1518
|
-
function computeSquares(Fr r, uint256 logN) internal pure returns (Fr[] memory) {
|
|
1519
|
-
Fr[] memory squares = new Fr[](logN);
|
|
1520
|
-
squares[0] = r;
|
|
1521
|
-
for (uint256 i = 1; i < logN; ++i) {
|
|
1522
|
-
squares[i] = squares[i - 1].sqr();
|
|
1523
|
-
}
|
|
1524
|
-
return squares;
|
|
1525
|
-
}
|
|
1526
1543
|
// Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., m-1
|
|
1527
|
-
|
|
1528
1544
|
function computeFoldPosEvaluations(
|
|
1529
1545
|
Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckUChallenges,
|
|
1530
1546
|
Fr batchedEvalAccumulator,
|
|
@@ -1547,23 +1563,19 @@ library CommitmentSchemeLib {
|
|
|
1547
1563
|
}
|
|
1548
1564
|
return foldPosEvaluations;
|
|
1549
1565
|
}
|
|
1550
|
-
}
|
|
1551
|
-
|
|
1552
|
-
uint256 constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // EC group order. F_q
|
|
1553
1566
|
|
|
1554
|
-
function
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
str[2 + i * 2] = alphabet[uint8(value[i] >> 4)];
|
|
1562
|
-
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;
|
|
1563
1574
|
}
|
|
1564
|
-
result = string(str);
|
|
1565
1575
|
}
|
|
1566
1576
|
|
|
1577
|
+
uint256 constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // EC group order. F_q
|
|
1578
|
+
|
|
1567
1579
|
// Fr utility
|
|
1568
1580
|
|
|
1569
1581
|
function bytesToFr(bytes calldata proofSection) pure returns (Fr scalar) {
|
|
@@ -1572,20 +1584,31 @@ function bytesToFr(bytes calldata proofSection) pure returns (Fr scalar) {
|
|
|
1572
1584
|
|
|
1573
1585
|
// EC Point utilities
|
|
1574
1586
|
function bytesToG1Point(bytes calldata proofSection) pure returns (Honk.G1Point memory point) {
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
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});
|
|
1578
1598
|
}
|
|
1579
1599
|
|
|
1580
1600
|
function negateInplace(Honk.G1Point memory point) pure returns (Honk.G1Point memory) {
|
|
1581
|
-
|
|
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
|
+
}
|
|
1582
1605
|
return point;
|
|
1583
1606
|
}
|
|
1584
1607
|
|
|
1585
1608
|
/**
|
|
1586
1609
|
* Convert the pairing points to G1 points.
|
|
1587
1610
|
*
|
|
1588
|
-
* The pairing points are serialised as an array of
|
|
1611
|
+
* The pairing points are serialised as an array of 2 limbs representing two points
|
|
1589
1612
|
* (P0 and P1, used for lhs and rhs of pairing operation).
|
|
1590
1613
|
*
|
|
1591
1614
|
* There are 2 limbs (lo, hi) for each coordinate, so 4 limbs per point, 8 total.
|
|
@@ -1599,22 +1622,28 @@ function convertPairingPointsToG1(Fr[PAIRING_POINTS_SIZE] memory pairingPoints)
|
|
|
1599
1622
|
pure
|
|
1600
1623
|
returns (Honk.G1Point memory lhs, Honk.G1Point memory rhs)
|
|
1601
1624
|
{
|
|
1602
|
-
// P0 (lhs): x = lo
|
|
1625
|
+
// P0 (lhs): x = lo | (hi << 136)
|
|
1603
1626
|
uint256 lhsX = Fr.unwrap(pairingPoints[0]);
|
|
1604
1627
|
lhsX |= Fr.unwrap(pairingPoints[1]) << 136;
|
|
1605
|
-
lhs.x = lhsX;
|
|
1606
1628
|
|
|
1607
1629
|
uint256 lhsY = Fr.unwrap(pairingPoints[2]);
|
|
1608
1630
|
lhsY |= Fr.unwrap(pairingPoints[3]) << 136;
|
|
1609
|
-
lhs.y = lhsY;
|
|
1610
1631
|
|
|
1611
|
-
// P1 (rhs): x = lo
|
|
1632
|
+
// P1 (rhs): x = lo | (hi << 136)
|
|
1612
1633
|
uint256 rhsX = Fr.unwrap(pairingPoints[4]);
|
|
1613
1634
|
rhsX |= Fr.unwrap(pairingPoints[5]) << 136;
|
|
1614
|
-
rhs.x = rhsX;
|
|
1615
1635
|
|
|
1616
1636
|
uint256 rhsY = Fr.unwrap(pairingPoints[6]);
|
|
1617
1637
|
rhsY |= Fr.unwrap(pairingPoints[7]) << 136;
|
|
1638
|
+
|
|
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;
|
|
1618
1647
|
rhs.y = rhsY;
|
|
1619
1648
|
}
|
|
1620
1649
|
|
|
@@ -1652,7 +1681,7 @@ function generateRecursionSeparator(
|
|
|
1652
1681
|
recursionSeparatorElements[6] = accRhs.x;
|
|
1653
1682
|
recursionSeparatorElements[7] = accRhs.y;
|
|
1654
1683
|
|
|
1655
|
-
recursionSeparator = FrLib.
|
|
1684
|
+
recursionSeparator = FrLib.from(uint256(keccak256(abi.encodePacked(recursionSeparatorElements))) % P);
|
|
1656
1685
|
}
|
|
1657
1686
|
|
|
1658
1687
|
/**
|
|
@@ -1770,17 +1799,20 @@ function ecAdd(Honk.G1Point memory lhs, Honk.G1Point memory rhs) view returns (H
|
|
|
1770
1799
|
return result;
|
|
1771
1800
|
}
|
|
1772
1801
|
|
|
1773
|
-
function
|
|
1774
|
-
|
|
1775
|
-
|
|
1802
|
+
function rejectPointAtInfinity(Honk.G1Point memory point) pure {
|
|
1803
|
+
require((point.x | point.y) != 0, Errors.PointAtInfinity());
|
|
1804
|
+
}
|
|
1776
1805
|
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
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]);
|
|
1781
1814
|
}
|
|
1782
|
-
|
|
1783
|
-
require(success, "point is not on the curve");
|
|
1815
|
+
return acc == 0;
|
|
1784
1816
|
}
|
|
1785
1817
|
|
|
1786
1818
|
function pairing(Honk.G1Point memory rhs, Honk.G1Point memory lhs) view returns (bool decodedResult) {
|
|
@@ -1805,18 +1837,24 @@ function pairing(Honk.G1Point memory rhs, Honk.G1Point memory lhs) view returns
|
|
|
1805
1837
|
decodedResult = success && abi.decode(result, (bool));
|
|
1806
1838
|
}
|
|
1807
1839
|
|
|
1808
|
-
|
|
1809
|
-
|
|
1840
|
+
abstract contract BaseHonkVerifier is IVerifier {
|
|
1841
|
+
using FrLib for Fr;
|
|
1810
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
|
|
1811
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;
|
|
1812
1851
|
|
|
1813
|
-
|
|
1814
|
-
using FrLib for Fr;
|
|
1852
|
+
uint256 internal constant PERMUTATION_ARGUMENT_VALUE_SEPARATOR = 1 << 28;
|
|
1815
1853
|
|
|
1816
|
-
uint256 immutable $N;
|
|
1817
|
-
uint256 immutable $LOG_N;
|
|
1818
|
-
uint256 immutable $VK_HASH;
|
|
1819
|
-
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;
|
|
1820
1858
|
|
|
1821
1859
|
constructor(uint256 _N, uint256 _logN, uint256 _vkHash, uint256 _numPublicInputs) {
|
|
1822
1860
|
$N = _N;
|
|
@@ -1825,59 +1863,19 @@ abstract contract BaseHonkVerifier is IVerifier {
|
|
|
1825
1863
|
$NUM_PUBLIC_INPUTS = _numPublicInputs;
|
|
1826
1864
|
}
|
|
1827
1865
|
|
|
1828
|
-
// Errors
|
|
1829
|
-
error ProofLengthWrong();
|
|
1830
|
-
error ProofLengthWrongWithLogN(uint256 logN, uint256 actualLength, uint256 expectedLength);
|
|
1831
|
-
error PublicInputsLengthWrong();
|
|
1832
|
-
error SumcheckFailed();
|
|
1833
|
-
error ShpleminiFailed();
|
|
1834
|
-
|
|
1835
|
-
// Constants for proof length calculation (matching UltraKeccakFlavor)
|
|
1836
|
-
uint256 constant NUM_WITNESS_ENTITIES = 8;
|
|
1837
|
-
uint256 constant NUM_ELEMENTS_COMM = 2; // uint256 elements for curve points
|
|
1838
|
-
uint256 constant NUM_ELEMENTS_FR = 1; // uint256 elements for field elements
|
|
1839
|
-
|
|
1840
|
-
// Calculate proof size based on log_n (matching UltraKeccakFlavor formula)
|
|
1841
|
-
function calculateProofSize(uint256 logN) internal pure returns (uint256) {
|
|
1842
|
-
// Witness commitments
|
|
1843
|
-
uint256 proofLength = NUM_WITNESS_ENTITIES * NUM_ELEMENTS_COMM; // witness commitments
|
|
1844
|
-
|
|
1845
|
-
// Sumcheck
|
|
1846
|
-
proofLength += logN * BATCHED_RELATION_PARTIAL_LENGTH * NUM_ELEMENTS_FR; // sumcheck univariates
|
|
1847
|
-
proofLength += NUMBER_OF_ENTITIES * NUM_ELEMENTS_FR; // sumcheck evaluations
|
|
1848
|
-
|
|
1849
|
-
// Gemini
|
|
1850
|
-
proofLength += (logN - 1) * NUM_ELEMENTS_COMM; // Gemini Fold commitments
|
|
1851
|
-
proofLength += logN * NUM_ELEMENTS_FR; // Gemini evaluations
|
|
1852
|
-
|
|
1853
|
-
// Shplonk and KZG commitments
|
|
1854
|
-
proofLength += NUM_ELEMENTS_COMM * 2; // Shplonk Q and KZG W commitments
|
|
1855
|
-
|
|
1856
|
-
// Pairing points
|
|
1857
|
-
proofLength += PAIRING_POINTS_SIZE; // pairing inputs carried on public inputs
|
|
1858
|
-
|
|
1859
|
-
return proofLength;
|
|
1860
|
-
}
|
|
1861
|
-
|
|
1862
|
-
// Number of field elements in a ultra keccak honk proof for log_n = 25, including pairing point object.
|
|
1863
|
-
uint256 constant PROOF_SIZE = 350; // Legacy constant - will be replaced by calculateProofSize($LOG_N)
|
|
1864
|
-
uint256 constant SHIFTED_COMMITMENTS_START = 29;
|
|
1865
|
-
|
|
1866
|
-
function loadVerificationKey() internal pure virtual returns (Honk.VerificationKey memory);
|
|
1867
|
-
|
|
1868
1866
|
function verify(bytes calldata proof, bytes32[] calldata publicInputs) public view override returns (bool) {
|
|
1869
1867
|
// Calculate expected proof size based on $LOG_N
|
|
1870
1868
|
uint256 expectedProofSize = calculateProofSize($LOG_N);
|
|
1871
1869
|
|
|
1872
1870
|
// Check the received proof is the expected size where each field element is 32 bytes
|
|
1873
1871
|
if (proof.length != expectedProofSize * 32) {
|
|
1874
|
-
revert ProofLengthWrongWithLogN($LOG_N, proof.length, expectedProofSize * 32);
|
|
1872
|
+
revert Errors.ProofLengthWrongWithLogN($LOG_N, proof.length, expectedProofSize * 32);
|
|
1875
1873
|
}
|
|
1876
1874
|
|
|
1877
1875
|
Honk.VerificationKey memory vk = loadVerificationKey();
|
|
1878
1876
|
Honk.Proof memory p = TranscriptLib.loadProof(proof, $LOG_N);
|
|
1879
1877
|
if (publicInputs.length != vk.publicInputsSize - PAIRING_POINTS_SIZE) {
|
|
1880
|
-
revert PublicInputsLengthWrong();
|
|
1878
|
+
revert Errors.PublicInputsLengthWrong();
|
|
1881
1879
|
}
|
|
1882
1880
|
|
|
1883
1881
|
// Generate the fiat shamir challenges for the whole protocol
|
|
@@ -1894,16 +1892,14 @@ abstract contract BaseHonkVerifier is IVerifier {
|
|
|
1894
1892
|
|
|
1895
1893
|
// Sumcheck
|
|
1896
1894
|
bool sumcheckVerified = verifySumcheck(p, t);
|
|
1897
|
-
if (!sumcheckVerified) revert SumcheckFailed();
|
|
1895
|
+
if (!sumcheckVerified) revert Errors.SumcheckFailed();
|
|
1898
1896
|
|
|
1899
1897
|
bool shpleminiVerified = verifyShplemini(p, vk, t);
|
|
1900
|
-
if (!shpleminiVerified) revert ShpleminiFailed();
|
|
1898
|
+
if (!shpleminiVerified) revert Errors.ShpleminiFailed();
|
|
1901
1899
|
|
|
1902
1900
|
return sumcheckVerified && shpleminiVerified; // Boolean condition not required - nice for vanity :)
|
|
1903
1901
|
}
|
|
1904
1902
|
|
|
1905
|
-
uint256 constant PERMUTATION_ARGUMENT_VALUE_SEPARATOR = 1 << 28;
|
|
1906
|
-
|
|
1907
1903
|
function computePublicInputDelta(
|
|
1908
1904
|
bytes32[] memory publicInputs,
|
|
1909
1905
|
Fr[PAIRING_POINTS_SIZE] memory pairingPointObject,
|
|
@@ -1950,7 +1946,7 @@ abstract contract BaseHonkVerifier is IVerifier {
|
|
|
1950
1946
|
for (uint256 round = 0; round < $LOG_N; ++round) {
|
|
1951
1947
|
Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariate = proof.sumcheckUnivariates[round];
|
|
1952
1948
|
bool valid = checkSum(roundUnivariate, roundTarget);
|
|
1953
|
-
if (!valid) revert SumcheckFailed();
|
|
1949
|
+
if (!valid) revert Errors.SumcheckFailed();
|
|
1954
1950
|
|
|
1955
1951
|
Fr roundChallenge = tp.sumCheckUChallenges[round];
|
|
1956
1952
|
|
|
@@ -1966,15 +1962,6 @@ abstract contract BaseHonkVerifier is IVerifier {
|
|
|
1966
1962
|
verified = (grandHonkRelationSum == roundTarget);
|
|
1967
1963
|
}
|
|
1968
1964
|
|
|
1969
|
-
function checkSum(Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariate, Fr roundTarget)
|
|
1970
|
-
internal
|
|
1971
|
-
pure
|
|
1972
|
-
returns (bool checked)
|
|
1973
|
-
{
|
|
1974
|
-
Fr totalSum = roundUnivariate[0] + roundUnivariate[1];
|
|
1975
|
-
checked = totalSum == roundTarget;
|
|
1976
|
-
}
|
|
1977
|
-
|
|
1978
1965
|
// Return the new target sum for the next sumcheck round
|
|
1979
1966
|
function computeNextTargetSum(Fr[BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariates, Fr roundChallenge)
|
|
1980
1967
|
internal
|
|
@@ -2018,16 +2005,6 @@ abstract contract BaseHonkVerifier is IVerifier {
|
|
|
2018
2005
|
targetSum = targetSum * numeratorValue;
|
|
2019
2006
|
}
|
|
2020
2007
|
|
|
2021
|
-
// Univariate evaluation of the monomial ((1-X_l) + X_l.B_l) at the challenge point X_l=u_l
|
|
2022
|
-
function partiallyEvaluatePOW(Fr gateChallenge, Fr currentEvaluation, Fr roundChallenge)
|
|
2023
|
-
internal
|
|
2024
|
-
pure
|
|
2025
|
-
returns (Fr newEvaluation)
|
|
2026
|
-
{
|
|
2027
|
-
Fr univariateEval = ONE + (roundChallenge * (gateChallenge - ONE));
|
|
2028
|
-
newEvaluation = currentEvaluation * univariateEval;
|
|
2029
|
-
}
|
|
2030
|
-
|
|
2031
2008
|
function verifyShplemini(Honk.Proof memory proof, Honk.VerificationKey memory vk, Transcript memory tp)
|
|
2032
2009
|
internal
|
|
2033
2010
|
view
|
|
@@ -2220,18 +2197,20 @@ abstract contract BaseHonkVerifier is IVerifier {
|
|
|
2220
2197
|
Honk.G1Point memory P_0_agg = batchMul(commitments, scalars);
|
|
2221
2198
|
Honk.G1Point memory P_1_agg = negateInplace(quotient_commitment);
|
|
2222
2199
|
|
|
2223
|
-
// Aggregate pairing points
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
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);
|
|
2227
2205
|
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2206
|
+
// Validate the points from the proof are on the curve
|
|
2207
|
+
rejectPointAtInfinity(P_0_other);
|
|
2208
|
+
rejectPointAtInfinity(P_1_other);
|
|
2231
2209
|
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
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
|
+
}
|
|
2235
2214
|
|
|
2236
2215
|
return pairing(P_0_agg, P_1_agg);
|
|
2237
2216
|
}
|
|
@@ -2245,7 +2224,7 @@ abstract contract BaseHonkVerifier is IVerifier {
|
|
|
2245
2224
|
|
|
2246
2225
|
// Validate all points are on the curve
|
|
2247
2226
|
for (uint256 i = 0; i < limit; ++i) {
|
|
2248
|
-
|
|
2227
|
+
rejectPointAtInfinity(base[i]);
|
|
2249
2228
|
}
|
|
2250
2229
|
|
|
2251
2230
|
bool success = true;
|
|
@@ -2273,8 +2252,51 @@ abstract contract BaseHonkVerifier is IVerifier {
|
|
|
2273
2252
|
mstore(add(result, 0x20), mload(add(free, 0x20)))
|
|
2274
2253
|
}
|
|
2275
2254
|
|
|
2276
|
-
require(success, ShpleminiFailed());
|
|
2255
|
+
require(success, Errors.ShpleminiFailed());
|
|
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;
|
|
2277
2297
|
}
|
|
2298
|
+
|
|
2299
|
+
function loadVerificationKey() internal pure virtual returns (Honk.VerificationKey memory);
|
|
2278
2300
|
}
|
|
2279
2301
|
|
|
2280
2302
|
contract HonkVerifier is BaseHonkVerifier(N, LOG_N, VK_HASH, NUMBER_OF_PUBLIC_INPUTS) {
|