@pvium/p2id-core 0.1.2 → 0.2.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.
@@ -5,7 +5,7 @@ pragma solidity >=0.8.21;
5
5
  uint256 constant N = 2097152;
6
6
  uint256 constant LOG_N = 21;
7
7
  uint256 constant NUMBER_OF_PUBLIC_INPUTS = 19;
8
- uint256 constant VK_HASH = 0x0e105995ea345a2ad495a8e7707075ad3c49fce617f1391d13c50cd3b0b823aa;
8
+ uint256 constant VK_HASH = 0x0d98c94bcdac10f79e1dbc899f232b9f151eab31b116d644f732cf7693ccb2c7;
9
9
  library HonkVerificationKey {
10
10
  function loadVerificationKey() internal pure returns (Honk.VerificationKey memory) {
11
11
  Honk.VerificationKey memory vk = Honk.VerificationKey({
@@ -13,52 +13,52 @@ library HonkVerificationKey {
13
13
  logCircuitSize: uint256(21),
14
14
  publicInputsSize: uint256(19),
15
15
  ql: Honk.G1Point({
16
- x: uint256(0x0c0fbd2b1460a0b0bccb62d4527f91523b2167690e98976144216c342ddfd54b),
17
- y: uint256(0x11544daf1bcdccd74d55d7cb84308b67f818b5565fb5885960ec5f082e8dc820)
16
+ x: uint256(0x2c1b7ea2b43336dae4184a4801b8c79fffd33d5100ba495a65634baba55320b0),
17
+ y: uint256(0x0f723f6b2e6971c51541d84fb1eb2ee52bb2d43fb795cdbbee170c8bf60133ef)
18
18
  }),
19
19
  qr: Honk.G1Point({
20
- x: uint256(0x28dbee3939797ad1b0f4947260120a96095bc6f8a2efc27dc4e7c6f5b07b8a97),
21
- y: uint256(0x2f76eb999a1f10bc5ca0c5a2ca944e2d9575859a660b068a35a4cd762258ac13)
20
+ x: uint256(0x2c4dfa9fca3821834c1dcd9c2e25d1174a9c3b6f0d6da8e0acb1119fa298ba15),
21
+ y: uint256(0x107a91f3db55144452b243b03094afde1c72dd616bf9197bc224f6fb3344ea8c)
22
22
  }),
23
23
  qo: Honk.G1Point({
24
- x: uint256(0x0db8223a888b42240f95090755c9867ec384f53ea27018038a5931ace533f6b3),
25
- y: uint256(0x0a477836a16431cd37acf0750e34e1194c09332d4832390c7ade2fb126473311)
24
+ x: uint256(0x1d8028efbf5771b66ad4087af7ea6c35f9acc6c921f8f5a9446111303720e435),
25
+ y: uint256(0x13182d6fdb9595517eeccb94fdc1de3f7135d1e558b18f6a876551743842fdc6)
26
26
  }),
27
27
  q4: Honk.G1Point({
28
- x: uint256(0x2065bcb9724f9ee952a41a41e3977d61b192006edddc00c1772e112c1bc03e48),
29
- y: uint256(0x190168907b7d58c8cca95bf235ca510b355c951adecb8fbb7327267ccf52df42)
28
+ x: uint256(0x1fb380e568a40d62e568da9695626cb48b9b8cda059868692a1f5e66f62f5a5c),
29
+ y: uint256(0x20a1e9ec32fee522f0affb8b36473d12cdb4094cf6ee8521b35ed31c5af6fd73)
30
30
  }),
31
31
  qm: Honk.G1Point({
32
- x: uint256(0x2b9cd7175e6a8085b12aa1fefa7f780b4b59aeaa3d77ad7b0c80256db165dc0a),
33
- y: uint256(0x19bd7797f55aad7e70dc26950f398332014eb44a43d7b4d3accb73f2fb81e72a)
32
+ x: uint256(0x173c3b41f6a2e66fb5859fe7d4b3fa6fc3c85496678fcb0da81435f3454cfab4),
33
+ y: uint256(0x2b26dea97c3a9127f3b5d941370746caa7ef18f660f78c69fe4e96f4805835d7)
34
34
  }),
35
35
  qc: Honk.G1Point({
36
- x: uint256(0x1d6198f289227dc183297f8bfcb42f8c66abf8e786260d29e0a362189c794a8c),
37
- y: uint256(0x17c99fef6cc097e7ef6edbb53602d8973c2a037967895bafc6fe771c885767b6)
36
+ x: uint256(0x089128522a7b4a89fe49976e0a150f93a96a2aebe7bb6b771fd43f5fc2a23f43),
37
+ y: uint256(0x1f520fbb2372257258df2ba7dfee35a119a20b27104e5690bc2536ead8b95f55)
38
38
  }),
39
39
  qLookup: Honk.G1Point({
40
- x: uint256(0x1f21d9f47259d55071f21e0a600cce11be50b6261e9b911ffdac6f59f6215e2b),
41
- y: uint256(0x2745f5f6e1b51445152840adeb0495c242b71185d64d7fbcde817feeed67993c)
40
+ x: uint256(0x1bf694c2ad84c2e633ad392257d63436e84b1073c582920f33f420b8badb3ab9),
41
+ y: uint256(0x01202c520ff5fde19c77f5a6001adb17063548a8259cf6757071aaf3db033318)
42
42
  }),
43
43
  qArith: Honk.G1Point({
44
- x: uint256(0x2fa49e34485452c477e319ce0b98195742b4bdb3a0f75a35f1f98711fb6552d5),
45
- y: uint256(0x062d5c1410518684f3e85b7e0d75d228378df2c5cc53df106ea7170de36e2ac2)
44
+ x: uint256(0x2c560e8c3de53f23f0e0d8f607a67b8fb08d11ca7a86967157bb77d3539fd5b8),
45
+ y: uint256(0x2653c63366a9d5d42c8c91ac7c1247ee7fa6a3d5e2f05329cd2fc0358ce9933a)
46
46
  }),
47
47
  qDeltaRange: Honk.G1Point({
48
- x: uint256(0x0bea0cfb68dc8f81f2c244a6344319cb27efb8f7109a3ba1dc50ba345f6aa15f),
49
- y: uint256(0x1fea9d5d1eda129a40e56346e0367bcb46e82fae3a847eeb595c4a7893051a6c)
48
+ x: uint256(0x20557135427958307c97e6017f8e6f20a82d9028c26c77fb2b208d688dcafbd5),
49
+ y: uint256(0x12e20d83b19cc767fe8f26e1040d70457db9d9a9eb6b60838ea4b6891ddd0c36)
50
50
  }),
51
51
  qElliptic: Honk.G1Point({
52
52
  x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000),
53
53
  y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000)
54
54
  }),
55
55
  qMemory: Honk.G1Point({
56
- x: uint256(0x1d8486efda2cbf96cee91c579c809f3d1f404b82d8b9c517d35ddcbcfaea20f1),
57
- y: uint256(0x177229d5cabcb16f5e7ca9a56fcd912b345c98d9e2b89a283e0556b185703bdf)
56
+ x: uint256(0x21cdf6a43b0c43854cdd624ce2b81cf4278b7d846c55d7ec5e6d3dbaf9887fe0),
57
+ y: uint256(0x13ea21cb8cb4fe366919786206717c0f6f30120b11731e72a21549f6b8d79321)
58
58
  }),
59
59
  qNnf: Honk.G1Point({
60
- x: uint256(0x04a36167f7e1fa03b2d3b5f85f52dddfef2ed6ed1e89eab9c6d6a7807a30c1a5),
61
- y: uint256(0x11c5181b7f5dcea80d4c44fce4a065c68ed26049e92f54e337cf59c692f84a4c)
60
+ x: uint256(0x2ef3c3abd690cab2fc188207a64429b35983f3c138b34cff5df89c838a921e25),
61
+ y: uint256(0x22e084b6a5c49a607eab5559d8a7b008387949cb1542a2b54bca353e1802700e)
62
62
  }),
63
63
  qPoseidon2External: Honk.G1Point({
64
64
  x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000),
@@ -69,60 +69,60 @@ library HonkVerificationKey {
69
69
  y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000)
70
70
  }),
71
71
  s1: Honk.G1Point({
72
- x: uint256(0x25944439c5706db4d4bf17d0cd03f71be02afd91f9bf1239399b1dc1a4457cc0),
73
- y: uint256(0x1a15f305835907343f73c005ed56ac4eb883d0f52c3fbd09fa9a9498eb510e62)
72
+ x: uint256(0x1e17b6ccf8b8e53b7e608baa1ff7baaebb0d9618ee408ff5aa1066769b5ce099),
73
+ y: uint256(0x20ea265296e1787a7abf45d8679adbda4e0ed6f51d6008273462d8a1683b9c97)
74
74
  }),
75
75
  s2: Honk.G1Point({
76
- x: uint256(0x2fed2d66b9d97e6a101d28c6d37936a013103bc6439b6dedeea05476c2a78743),
77
- y: uint256(0x16ece6ba7dd5f4dba4c042852c1860d65cfd42e2aba596e056ea0b5862ecaadd)
76
+ x: uint256(0x25e022aaad31633e0ae1a860634e4cb30e670c11ea015d7bd18ac4f614cfcdc1),
77
+ y: uint256(0x18725c00f8a4e402cf61d161427cd9749eb89e9ba67f25ce0b4f079aa19c3383)
78
78
  }),
79
79
  s3: Honk.G1Point({
80
- x: uint256(0x029823cc2b4de546d728162738c23fe5f85654f2f262126c38c1f44a94f6159f),
81
- y: uint256(0x1f8fa4b575751192e7e4636d3a804c573f0835bc0d599587b4665d7c16eddc13)
80
+ x: uint256(0x03e207722b9059d570b271412cbc4d39f01522acea22be09d6b4a55ff7007cc5),
81
+ y: uint256(0x1c708dcd032cac64aa3b175b52b1889a2624912f12f9ee1990a37eeabbe7544c)
82
82
  }),
83
83
  s4: Honk.G1Point({
84
- x: uint256(0x15bd3c01ea657ed5332fac7f5d249ed2ab95ff7612998fa2ed97a18e1911aeb2),
85
- y: uint256(0x1bc51c2d4fc014f4b3347da10bf7728cf9e5bbbe4a03fbf8eb6def18abd39743)
84
+ x: uint256(0x1f5f1b4663c078c26c4fadd628674465605d5eaafe37c331333ea0507299601b),
85
+ y: uint256(0x073024ad75b3390f369912b19ffa894a3434cf00110c3db1391064cc60304f74)
86
86
  }),
87
87
  t1: Honk.G1Point({
88
- x: uint256(0x0303f2fae9d426bcacf03a3324f365ab85a56ac0de12398d52a7925ad09a7934),
89
- y: uint256(0x200446d603ee01a4aa4dd1aeea063ac302c4d6fade4212ca043cffb5adb17093)
88
+ x: uint256(0x00a4cfcadaf65bd7f05c8b4513b4b429cef6c157cc855c30f031130f4c7e9879),
89
+ y: uint256(0x12139f1ede1b1b8a2a7754e61743e962c66c66cb83c2951e9d947ee4b5886285)
90
90
  }),
91
91
  t2: Honk.G1Point({
92
- x: uint256(0x2faa880e21816f6e84f9a63c69bd2f641ccf46a3c046edf5bfd8da9445aaef02),
93
- y: uint256(0x1b79ad9778d05ded45f962653dd8b2143aff5c962a60fb865635e76fd26bed28)
92
+ x: uint256(0x179c3371ab328f00f06755a773ffdb63d9f3428b0eb49602aeb8f46b3a93846e),
93
+ y: uint256(0x1e548495de26512389f97243fa06be419425366e6fe3eda4db2243f3eb289343)
94
94
  }),
95
95
  t3: Honk.G1Point({
96
- x: uint256(0x1f890e8812cc36372bc6f2e02f72d826c6735b38b62f4f19476afbb148b46124),
97
- y: uint256(0x291180bac307a9a350ed326f0f8c23dcc8efbb2f2b37c00cde6d0f2a0c8babb8)
96
+ x: uint256(0x08403e53c817b332f25f0ef623566bf0c4a29c01702613bebc26b504887b0067),
97
+ y: uint256(0x0fd72a489dae56d109122252c1af93b807a8d6b1a7e58a2c1c68a88610361c9d)
98
98
  }),
99
99
  t4: Honk.G1Point({
100
- x: uint256(0x1236e0212395b26cd85777136008cc4caf0066037c702b301becb0e0c35d77f4),
101
- y: uint256(0x2bd26f5b3b40d4a7a4d8277693f487d458bd5f784307e93b33de6de026db1366)
100
+ x: uint256(0x1097841f06e277321386ae25322b03fb507f607640a7ffdf6b3361d9d5f61b67),
101
+ y: uint256(0x147da05a1760a1556233a63a2e49e8015aba77f810a260171b4f5995c894c26b)
102
102
  }),
103
103
  id1: Honk.G1Point({
104
- x: uint256(0x26d67c272def0127082be77c31e099a9f9811a35712b6bb1b0d86a9da8ba8682),
105
- y: uint256(0x2393540006d4df8339c1a01889cd436986995291781382e59ce5363c9d91d60c)
104
+ x: uint256(0x2a1f137bb8c60c305275523f9968fff7e9eb285da590d13249655613babe3337),
105
+ y: uint256(0x1727a5cc5937328989b85d7a089fcd7f8b6acd9b5a236e8ecd4b8d5e9a66acf9)
106
106
  }),
107
107
  id2: Honk.G1Point({
108
- x: uint256(0x12e6fe2df8d9f5b64817faa8f113db27de14e800a1dc2ff37b4838fd18023777),
109
- y: uint256(0x018b58768dafe2b28cae54316b30ce28a70f7d257d23b3f85d90c36882e9f911)
108
+ x: uint256(0x06fdc373e611acbc236928ba93f9db893fbc4650e432c53471d604cb29c6996a),
109
+ y: uint256(0x0cb71589eb762de7ce73a8857f824dd73418e6afe241403bc75c89d79b513915)
110
110
  }),
111
111
  id3: Honk.G1Point({
112
- x: uint256(0x263c75326cd89fdd00fb443a4b17b32ee882d427d1254bdb65ddcee2ab059a49),
113
- y: uint256(0x1ff9f006ee2ea95c6c8b003b6f7f1607e06f5234e666d0e61fb780aad36ed85e)
112
+ x: uint256(0x2cddcc6b2824898e1df1136cddd9da391d8aa20b6bef4c3d0e99cd9510936e1b),
113
+ y: uint256(0x129cee475789db6bd598beb441f89215098db1eff7a30e0c3a35a5ba02079393)
114
114
  }),
115
115
  id4: Honk.G1Point({
116
- x: uint256(0x0336650f6db1ba47a4eea770d57476a426fc36b7c33582e94dfcfcc6ad8fdd2c),
117
- y: uint256(0x10116c0793907dad66484d1c071dc462133812c5562aafa3452a1a56ece2778e)
116
+ x: uint256(0x2be0ca8701ccf30e669b2fe921b76c7190ae075df53396368862f695cfbea37a),
117
+ y: uint256(0x29df147c807c9dac924146e8cbac06b948cb568d1dd693324d2576bed1fae740)
118
118
  }),
119
119
  lagrangeFirst: Honk.G1Point({
120
120
  x: uint256(0x2a56ce41f6b0be13b9c26747621b821eee81b23a887f299049b14c11e98460d6),
121
121
  y: uint256(0x1aa98f2de3ddda547d8f6de4e725ded5827d6338c78656c0d12ca1aea6ef2c7c)
122
122
  }),
123
123
  lagrangeLast: Honk.G1Point({
124
- x: uint256(0x14232344c2648e564db86dd72f84cb5435120efb4ba0095da25343c75fe30ddc),
125
- y: uint256(0x24206e1fd8e64ba30eb1c6f720748fd02ef8d915a969596faebec5b98bd0614c)
124
+ x: uint256(0x25e42d0017747becf6182d6739ad9ea07f20a8d507337962155871d23d402611),
125
+ y: uint256(0x13b7c5a27924211c8b1f134228b07798bc35d589d07ceb8ccdcefc6139861095)
126
126
  })
127
127
  });
128
128
  return vk;
@@ -177,6 +177,12 @@ Fr constant SUBGROUP_GENERATOR_INVERSE = Fr.wrap(0x204bd3277422fad364751ad938e2b
177
177
  Fr constant MINUS_ONE = Fr.wrap(MODULUS - 1);
178
178
  Fr constant ONE = Fr.wrap(1);
179
179
  Fr constant ZERO = Fr.wrap(0);
180
+
181
+ // SmallSubgroupIPA opening-claim layout — mirrors SMALL_IPA_CLAIMS in
182
+ // barretenberg/cpp/src/barretenberg/commitment_schemes/small_subgroup_ipa/small_subgroup_ipa_utils.hpp.
183
+ uint256 constant NUM_SMALL_IPA_OPENING_CLAIMS = 5;
184
+ uint256 constant SMALL_IPA_BOUNDARY_OPENING_IDX = 3;
185
+ uint256 constant NUM_SMALL_IPA_TRANSCRIPT_EVALS = 4;
180
186
  // Instantiation
181
187
 
182
188
  library FrLib {
@@ -333,22 +339,8 @@ uint256 constant GROUP_ELEMENT_SIZE = 0x40;
333
339
  // Powers of alpha used to batch subrelations (alpha, alpha^2, ..., alpha^(NUM_SUBRELATIONS-1))
334
340
  uint256 constant NUMBER_OF_ALPHAS = NUMBER_OF_SUBRELATIONS - 1;
335
341
 
336
- // ENUM FOR WIRES
342
+ // Must match UltraFlavor_Generated::EntityId order.
337
343
  enum WIRE {
338
- Q_M,
339
- Q_C,
340
- Q_L,
341
- Q_R,
342
- Q_O,
343
- Q_4,
344
- Q_LOOKUP,
345
- Q_ARITH,
346
- Q_RANGE,
347
- Q_ELLIPTIC,
348
- Q_MEMORY,
349
- Q_NNF,
350
- Q_POSEIDON2_EXTERNAL,
351
- Q_POSEIDON2_INTERNAL,
352
344
  SIGMA_1,
353
345
  SIGMA_2,
354
346
  SIGMA_3,
@@ -357,12 +349,26 @@ enum WIRE {
357
349
  ID_2,
358
350
  ID_3,
359
351
  ID_4,
352
+ LAGRANGE_FIRST,
353
+ LAGRANGE_LAST,
354
+ Q_LOOKUP,
360
355
  TABLE_1,
361
356
  TABLE_2,
362
357
  TABLE_3,
363
358
  TABLE_4,
364
- LAGRANGE_FIRST,
365
- LAGRANGE_LAST,
359
+ Q_M,
360
+ Q_R,
361
+ Q_O,
362
+ Q_C,
363
+ Q_L,
364
+ Q_4,
365
+ Q_ARITH,
366
+ Q_RANGE,
367
+ Q_ELLIPTIC,
368
+ Q_MEMORY,
369
+ Q_NNF,
370
+ Q_POSEIDON2_EXTERNAL,
371
+ Q_POSEIDON2_INTERNAL,
366
372
  W_L,
367
373
  W_R,
368
374
  W_O,
@@ -987,7 +993,7 @@ library RelationsLib {
987
993
  accum = accum + (q_arith - ONE) * wire(p, WIRE.W_4_SHIFT);
988
994
  accum = accum * q_arith;
989
995
  accum = accum * domainSep;
990
- evals[0] = accum;
996
+ evals[6] = accum;
991
997
  }
992
998
 
993
999
  // Relation 1
@@ -997,7 +1003,7 @@ library RelationsLib {
997
1003
  accum = accum * (q_arith - ONE);
998
1004
  accum = accum * q_arith;
999
1005
  accum = accum * domainSep;
1000
- evals[1] = accum;
1006
+ evals[7] = accum;
1001
1007
  }
1002
1008
  }
1003
1009
 
@@ -1035,19 +1041,19 @@ library RelationsLib {
1035
1041
  - ((wire(p, WIRE.Z_PERM_SHIFT) + (wire(p, WIRE.LAGRANGE_LAST) * rp.publicInputsDelta))
1036
1042
  * grand_product_denominator);
1037
1043
  acc = acc * domainSep;
1038
- evals[2] = acc;
1044
+ evals[0] = acc;
1039
1045
  }
1040
1046
 
1041
1047
  // Contribution 3
1042
1048
  {
1043
1049
  Fr acc = (wire(p, WIRE.LAGRANGE_LAST) * wire(p, WIRE.Z_PERM_SHIFT)) * domainSep;
1044
- evals[3] = acc;
1050
+ evals[1] = acc;
1045
1051
  }
1046
1052
 
1047
1053
  // Contribution 4: z_perm initialization check (lagrange_first * z_perm = 0)
1048
1054
  {
1049
1055
  Fr acc = (wire(p, WIRE.LAGRANGE_FIRST) * wire(p, WIRE.Z_PERM)) * domainSep;
1050
- evals[4] = acc;
1056
+ evals[2] = acc;
1051
1057
  }
1052
1058
  }
1053
1059
 
@@ -1098,9 +1104,9 @@ library RelationsLib {
1098
1104
 
1099
1105
  Fr read_tag_boolean_relation = read_tag * read_tag - read_tag;
1100
1106
 
1101
- evals[5] = accumulatorNone;
1102
- evals[6] = accumulatorOne;
1103
- evals[7] = read_tag_boolean_relation * domainSep;
1107
+ evals[3] = accumulatorNone;
1108
+ evals[4] = accumulatorOne;
1109
+ evals[5] = read_tag_boolean_relation * domainSep;
1104
1110
  }
1105
1111
 
1106
1112
  function accumulateDeltaRangeRelation(
@@ -1588,8 +1594,8 @@ library CommitmentSchemeLib {
1588
1594
  Fr batchingChallenge;
1589
1595
  // Linear combination of multilinear (sumcheck) evaluations and powers of rho
1590
1596
  Fr batchedEvaluation;
1591
- Fr[4] denominators;
1592
- Fr[4] batchingScalars;
1597
+ Fr[NUM_SMALL_IPA_OPENING_CLAIMS] denominators;
1598
+ Fr[NUM_SMALL_IPA_OPENING_CLAIMS] batchingScalars;
1593
1599
  // 1/(z - r^{2^i}) for i = 0, ..., logSize, dynamically updated
1594
1600
  Fr posInvertedDenominator;
1595
1601
  // 1/(z + r^{2^i}) for i = 0, ..., logSize, dynamically updated
@@ -2183,34 +2189,34 @@ abstract contract BaseZKHonkVerifier is IVerifier {
2183
2189
 
2184
2190
  commitments[1] = proof.geminiMaskingPoly;
2185
2191
 
2186
- commitments[2] = vk.qm;
2187
- commitments[3] = vk.qc;
2188
- commitments[4] = vk.ql;
2189
- commitments[5] = vk.qr;
2190
- commitments[6] = vk.qo;
2191
- commitments[7] = vk.q4;
2192
- commitments[8] = vk.qLookup;
2193
- commitments[9] = vk.qArith;
2194
- commitments[10] = vk.qDeltaRange;
2195
- commitments[11] = vk.qElliptic;
2196
- commitments[12] = vk.qMemory;
2197
- commitments[13] = vk.qNnf;
2198
- commitments[14] = vk.qPoseidon2External;
2199
- commitments[15] = vk.qPoseidon2Internal;
2200
- commitments[16] = vk.s1;
2201
- commitments[17] = vk.s2;
2202
- commitments[18] = vk.s3;
2203
- commitments[19] = vk.s4;
2204
- commitments[20] = vk.id1;
2205
- commitments[21] = vk.id2;
2206
- commitments[22] = vk.id3;
2207
- commitments[23] = vk.id4;
2208
- commitments[24] = vk.t1;
2209
- commitments[25] = vk.t2;
2210
- commitments[26] = vk.t3;
2211
- commitments[27] = vk.t4;
2212
- commitments[28] = vk.lagrangeFirst;
2213
- commitments[29] = vk.lagrangeLast;
2192
+ commitments[2] = vk.s1;
2193
+ commitments[3] = vk.s2;
2194
+ commitments[4] = vk.s3;
2195
+ commitments[5] = vk.s4;
2196
+ commitments[6] = vk.id1;
2197
+ commitments[7] = vk.id2;
2198
+ commitments[8] = vk.id3;
2199
+ commitments[9] = vk.id4;
2200
+ commitments[10] = vk.lagrangeFirst;
2201
+ commitments[11] = vk.lagrangeLast;
2202
+ commitments[12] = vk.qLookup;
2203
+ commitments[13] = vk.t1;
2204
+ commitments[14] = vk.t2;
2205
+ commitments[15] = vk.t3;
2206
+ commitments[16] = vk.t4;
2207
+ commitments[17] = vk.qm;
2208
+ commitments[18] = vk.qr;
2209
+ commitments[19] = vk.qo;
2210
+ commitments[20] = vk.qc;
2211
+ commitments[21] = vk.ql;
2212
+ commitments[22] = vk.q4;
2213
+ commitments[23] = vk.qArith;
2214
+ commitments[24] = vk.qDeltaRange;
2215
+ commitments[25] = vk.qElliptic;
2216
+ commitments[26] = vk.qMemory;
2217
+ commitments[27] = vk.qNnf;
2218
+ commitments[28] = vk.qPoseidon2External;
2219
+ commitments[29] = vk.qPoseidon2Internal;
2214
2220
 
2215
2221
  // Accumulate proof points
2216
2222
  commitments[30] = proof.w1;
@@ -2291,21 +2297,41 @@ abstract contract BaseZKHonkVerifier is IVerifier {
2291
2297
 
2292
2298
  boundary += $LOG_N - 1;
2293
2299
 
2294
- // Finalize the batch opening claim
2295
- mem.denominators[0] = Fr.wrap(1).div(tp.shplonkZ - tp.geminiR);
2296
- mem.denominators[1] = Fr.wrap(1).div(tp.shplonkZ - SUBGROUP_GENERATOR * tp.geminiR);
2300
+ // Denominators 1/(z - point_i) for the five opening points {r, g*r, r, 1, r}.
2301
+ mem.denominators[0] = ONE.div(tp.shplonkZ - tp.geminiR);
2302
+ mem.denominators[1] = ONE.div(tp.shplonkZ - SUBGROUP_GENERATOR * tp.geminiR);
2297
2303
  mem.denominators[2] = mem.denominators[0];
2298
- mem.denominators[3] = mem.denominators[0];
2304
+ mem.denominators[SMALL_IPA_BOUNDARY_OPENING_IDX] = ONE.div(tp.shplonkZ - ONE);
2305
+ mem.denominators[NUM_SMALL_IPA_OPENING_CLAIMS - 1] = mem.denominators[0];
2299
2306
 
2300
- for (uint256 i = 0; i < LIBRA_EVALUATIONS; i++) {
2307
+ // Iterate the opening claims in three segments — the inner loops can't be merged without an extra induction
2308
+ // variable, which pushes us into stack-too-deep.
2309
+ for (uint256 i = 0; i < SMALL_IPA_BOUNDARY_OPENING_IDX; i++) {
2301
2310
  Fr scalingFactor = mem.denominators[i] * mem.batchingChallenge;
2302
2311
  mem.batchingScalars[i] = scalingFactor.neg();
2303
2312
  mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu;
2304
2313
  mem.constantTermAccumulator = mem.constantTermAccumulator + scalingFactor * proof.libraPolyEvals[i];
2305
2314
  }
2315
+
2316
+ // Boundary slot: claimed value is hardcoded 0, so no constantTermAccumulator contribution.
2317
+ {
2318
+ Fr scalingFactor = mem.denominators[SMALL_IPA_BOUNDARY_OPENING_IDX] * mem.batchingChallenge;
2319
+ mem.batchingScalars[SMALL_IPA_BOUNDARY_OPENING_IDX] = scalingFactor.neg();
2320
+ mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu;
2321
+ }
2322
+
2323
+ for (uint256 i = SMALL_IPA_BOUNDARY_OPENING_IDX + 1; i < NUM_SMALL_IPA_OPENING_CLAIMS; i++) {
2324
+ Fr scalingFactor = mem.denominators[i] * mem.batchingChallenge;
2325
+ mem.batchingScalars[i] = scalingFactor.neg();
2326
+ mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu;
2327
+ mem.constantTermAccumulator = mem.constantTermAccumulator + scalingFactor * proof.libraPolyEvals[i - 1];
2328
+ }
2329
+
2330
+ // Group per-claim batching scalars by commitment: [G], [A] (three openings), [Q].
2306
2331
  scalars[boundary] = mem.batchingScalars[0];
2307
- scalars[boundary + 1] = mem.batchingScalars[1] + mem.batchingScalars[2];
2308
- scalars[boundary + 2] = mem.batchingScalars[3];
2332
+ scalars[boundary + 1] =
2333
+ mem.batchingScalars[1] + mem.batchingScalars[2] + mem.batchingScalars[SMALL_IPA_BOUNDARY_OPENING_IDX];
2334
+ scalars[boundary + 2] = mem.batchingScalars[NUM_SMALL_IPA_OPENING_CLAIMS - 1];
2309
2335
 
2310
2336
  for (uint256 i = 0; i < LIBRA_COMMITMENTS; i++) {
2311
2337
  commitments[boundary++] = proof.libraCommitments[i];
@@ -2,26 +2,11 @@
2
2
  pragma solidity ^0.8.27;
3
3
 
4
4
  /// @title IP2IDPolicy
5
- /// @notice Everything about P2ID vaults that is expected to evolve lives behind this interface,
6
- /// so it can change without changing vault bytecode (and therefore without moving any
7
- /// P2ID address). The vault factory points at one policy and can replace it only through
8
- /// a timelock; every vault consults the factory's current policy on each call.
9
- ///
10
- /// What a policy decides, and the limits the vault enforces on it:
11
- /// - which verifiers deposits may be funded under and claimed through. Gating is the one
12
- /// thing a policy can use to stop claims (by disallowing a verifier), which freezes
13
- /// claims under it but never moves funds; refunds never consult the policy.
14
- /// - the protocol fee on payouts, in basis points. The vault caps it at its own
15
- /// MAX_FEE_BPS, fixes a deposit's rate when the deposit is made, never charges it on
16
- /// refunds, and treats a failing quote as no fee.
17
- /// - how accrued fees are distributed. Fees accrue in each vault per (verifier, token);
18
- /// anyone can have a vault hand them to the policy (withdrawFees), which pulls them and
19
- /// splits them however it chooses, e.g. between a verifier's operator and the protocol.
20
- ///
21
- /// Launch policy: an owner-managed verifier allowlist and no fee. Permissionless,
22
- /// stake-based verifier registration and fees are later policies.
5
+ /// @notice Verifier approval, fee quotation and fee distribution callbacks used by P2IDVault.
6
+ /// @dev P2IDVault caps fee quotes, stores rates on funded deposits and quotes untracked funds at
7
+ /// sweep time. It skips policy approval for claims through the current default verifier.
23
8
  interface IP2IDPolicy {
24
- /// @notice Whether deposits may be funded under, and claimed through, `verifier`.
9
+ /// @notice Approval used for funding and for claims through a non-default verifier.
25
10
  function isVerifierAllowed(address verifier) external view returns (bool);
26
11
 
27
12
  /// @notice Fee on paying out `token` claimed through `verifier`, in basis points. Quoted when a
@@ -31,8 +16,7 @@ interface IP2IDPolicy {
31
16
  /// @notice Called by a vault holding fees earned through `verifier`. For an ERC-20 the vault
32
17
  /// first approves this policy for exactly `amount`: pull the tokens (transferFrom the
33
18
  /// caller) and distribute them; whatever is not pulled stays accrued in the vault, and
34
- /// the allowance is reset afterwards. Pulling from msg.sender makes the amount
35
- /// self-verifying: a caller that is not a vault can only give away its own tokens.
19
+ /// the allowance is reset afterwards.
36
20
  /// For the native coin (token == address(0)) the vault sends `amount` as msg.value
37
21
  /// instead, and all of it counts as distributed.
38
22
  function distributeFee(address verifier, address token, uint256 amount) external payable;
@@ -4,10 +4,8 @@ pragma solidity ^0.8.27;
4
4
  import {IP2IDVerifier} from "./IP2IDVerifier.sol";
5
5
 
6
6
  /// @title IP2IDVault
7
- /// @notice A vault holding ERC-20 tokens and the native coin for one identity until its owner
8
- /// proves it and sweeps. The native coin is the token address(0) in every function.
9
- /// Every deposit names the verifier whose proofs can release it; the factory's policy
10
- /// decides which verifiers are allowed and what (capped) fee applies.
7
+ /// @notice Deposit funding, claims, refunds and accounting for one identity commitment.
8
+ /// Token address(0) denotes native coin. Each deposit records its verifier and fee rate.
11
9
  interface IP2IDVault {
12
10
  /// @dev Field order packs into 5 storage slots:
13
11
  /// [funder, fundedAt, consumed] [token, refundWindow] [verifier, feeBps] [amount] [constraint].
@@ -25,8 +23,7 @@ interface IP2IDVault {
25
23
  }
26
24
 
27
25
  // ------------------------------------------------------------------ events
28
- // Every deposit is Funded once and then either Refunded (by its funder) or Claimed by a sweep.
29
- // Sweeps also emit one aggregate event with the net amount paid and the fee.
26
+ // Funding emits Funded; consumption emits Refunded or Claimed. Sweeps emit aggregate amounts.
30
27
 
31
28
  /// @notice A deposit was recorded via fund()/fundWith()/fundFor().
32
29
  /// @param ref Opaque application reference; zero means absent. Emitted only, not stored or enforced as unique.
@@ -35,15 +32,15 @@ interface IP2IDVault {
35
32
  event Refunded(uint256 indexed depositId, address indexed funder, address indexed token, uint256 amount);
36
33
  /// @notice A deposit was paid out by a sweep: `amount` gross, of which `fee` accrued as a fee.
37
34
  event Claimed(uint256 indexed depositId, address indexed to, uint256 amount, uint256 fee);
38
- /// @notice A proof newer than any seen under `verifier` set that verifier's owner wallet; older proofs are now refused.
35
+ /// @notice The owner cache was set or revalidated under the verifier's current revision.
39
36
  event OwnerRefreshed(address indexed verifier, address indexed owner, uint64 iat);
40
- /// @notice Default-bucket funds under `verifier` were paid to its owner wallet (`amount` net of `fee`).
37
+ /// @notice Default sweep result, including eligible untracked funds; amount is net of fee and may be zero.
41
38
  event Swept(address indexed verifier, address indexed token, uint256 amount, uint256 fee, address indexed to, uint256 depositsConsumed);
42
39
  /// @notice Funds from a constrained bucket were paid to the wallet the proof resolved to (`amount` net of `fee`).
43
40
  event SweptBucket(address indexed verifier, bytes32 indexed constraint, address indexed token, uint256 amount, uint256 fee, address to, uint256 depositsConsumed);
44
41
  /// @notice A fee accrued for `verifier`; it stays in the vault until withdrawFees() hands it to the policy.
45
42
  event FeeAccrued(address indexed verifier, address indexed token, uint256 amount);
46
- /// @notice The policy pulled `amount` of accrued fees to distribute.
43
+ /// @notice Amount deducted from accrued fees after policy distribution, via token pull or native transfer.
47
44
  event FeesDistributed(address indexed verifier, address indexed token, uint256 amount, address policy);
48
45
 
49
46
  // setup (factory only, once)
@@ -56,7 +53,7 @@ interface IP2IDVault {
56
53
  /// @notice Fund under any verifier the factory's policy allows.
57
54
  /// @param ref Opaque application reference emitted in Funded; bytes32(0) for none.
58
55
  function fundWith(address verifier, address token, uint256 amount, bytes32 constraint, uint64 refundWindow, bytes32 ref) external payable returns (uint256 depositId);
59
- /// @notice Factory-only: record a deposit owned by `funder`; tokens are pulled from the factory.
56
+ /// @notice Factory-only: record a deposit for `funder`; pull ERC-20 from the factory or receive native msg.value.
60
57
  /// @param ref Opaque application reference emitted in Funded; bytes32(0) for none.
61
58
  function fundFor(address funder, address verifier, address token, uint256 amount, bytes32 constraint, uint64 refundWindow, bytes32 ref) external payable returns (uint256 depositId);
62
59
  function refund(uint256 depositId) external;
@@ -66,9 +63,16 @@ interface IP2IDVault {
66
63
  /// if the proof is newer than anything seen under it, and retires older proofs.
67
64
  function refreshProof(address verifier, bytes calldata proof) external;
68
65
  function refreshProofAndSweep(address verifier, bytes calldata proof, address token, uint256 depositCountLimit) external returns (uint256 amount, uint256 consumed);
66
+ /// @notice Apply a proof the vault's own proxy has already verified (msg.sender must be this
67
+ /// address): the freshness, revision and owner-cache rules of refreshProof without
68
+ /// re-verifying. Reverts unless `wallet` is the recorded owner under `verifier` afterwards.
69
+ /// Returns its own selector as acknowledgement so the proxy rejects empty fallbacks.
70
+ /// The acknowledgement checks compatibility; implementations remain trusted to apply the result.
71
+ function acceptOwnerProof(address verifier, address wallet, uint64 iat) external returns (bytes4);
69
72
 
70
73
  // claiming (amounts returned are net of fees)
71
- /// @notice Sweep `verifier`'s default bucket to its owner; the default verifier's sweep also takes untracked funds.
74
+ /// @notice Sweep a page of the verifier's default bucket to its cached owner. Eligible untracked
75
+ /// funds are included for the current default verifier when its cache meets the cross-default floor.
72
76
  function sweep(address verifier, address token, uint256 depositCountLimit) external returns (uint256 amount, uint256 consumed);
73
77
  function sweepUntracked(address token) external returns (uint256 amount);
74
78
  function sweepDeposits(address verifier, address token, uint256[] calldata depositIds) external returns (uint256 amount);
@@ -83,9 +87,11 @@ interface IP2IDVault {
83
87
  /// @notice P2ID vault interface version implemented by this contract.
84
88
  function p2idVersion() external pure returns (string memory);
85
89
  function MAX_FEE_BPS() external view returns (uint16);
90
+ /// @notice Record cap for cursor-based sweeps; a zero or above-cap depositCountLimit uses this value.
91
+ function MAX_SWEEP_PAGE() external view returns (uint256);
86
92
  /// @notice address(0): the token address standing for the native coin.
87
93
  function NATIVE() external view returns (address);
88
- /// @notice keccak256 of the address scheme this vault was issued under, e.g. keccak256("pvium.vault.v1").
94
+ /// @notice Namespace value supplied at initialization; not used to recompute this vault's address.
89
95
  function nsHash() external view returns (bytes32);
90
96
  function factory() external view returns (address);
91
97
  function policy() external view returns (address);
@@ -96,17 +102,36 @@ interface IP2IDVault {
96
102
  function untrackedProofIat() external view returns (uint64);
97
103
  function saltCommitment() external view returns (bytes32);
98
104
  function depositCount() external view returns (uint256);
99
- function bucketDepositIds(address verifier, bytes32 constraint, address token) external view returns (uint256[] memory);
105
+ /// @notice A page of the bucket's deposit ids: up to `limit` from `offset` (limit 0 = all from `offset`).
106
+ function bucketDepositIds(address verifier, bytes32 constraint, address token, uint256 offset, uint256 limit) external view returns (uint256[] memory);
100
107
  function bucketDepositCount(address verifier, bytes32 constraint, address token) external view returns (uint256);
101
- /// @notice Whether `funder` has funded under `constraint`, and which deposit. A funder can use a
102
- /// constraint once (refunded or claimed, it stays used), so a signature over it releases
103
- /// at most one of their deposits. Funders must make constraints unique, e.g. by salting.
108
+ /// @notice Deposit recorded for a nonzero constraint and funder in this vault. The record persists
109
+ /// after a refund or claim and prevents the same funder from reusing that constraint here.
104
110
  function constraintDeposit(bytes32 constraint, address funder) external view returns (bool used, uint256 depositId);
105
111
  function bucketTotal(address verifier, bytes32 constraint, address token) external view returns (uint256);
106
112
  function trackedTotal(address token) external view returns (uint256);
107
113
  function feesOwed(address verifier, address token) external view returns (uint256);
108
114
  function feesOwedTotal(address token) external view returns (uint256);
109
- /// @notice Gross amount `sweep(verifier, token, 0)` would release now, before fees.
115
+ /// @notice Total default-bucket amount plus eligible untracked funds, before fees.
116
+ /// Does not apply the sweep page limit or validate default-bucket claimability.
110
117
  function sweepable(address verifier, address token) external view returns (uint256);
111
118
  function untrackedBalance(address token) external view returns (uint256);
119
+
120
+ struct AlphaAttestation {
121
+ uint256 nonce;
122
+ uint256 deadline;
123
+ bytes signature;
124
+ }
125
+
126
+ // Alpha authorization: same vault API, additional signed entry points.
127
+ function supportsAlphaGuard() external pure returns (bool);
128
+ /// @notice Whether a caller-supplied random nonce has been consumed by an alpha business call.
129
+ function alphaNonceUsed(uint256 nonce) external view returns (bool);
130
+ function executeWithAttestation(bytes calldata action, AlphaAttestation calldata attestation) external returns (bytes memory);
131
+ /// @notice Alpha entry points: sign the ABI-encoded ordinary method with its original arguments.
132
+ /// Ordinary methods require no signature when factory.isAlpha(verifier.vkHash()) is false.
133
+ function refreshProofWithAttestation(address verifier, bytes calldata proof, AlphaAttestation calldata attestation) external;
134
+ function refreshProofAndSweepWithAttestation(address verifier, bytes calldata proof, address token, uint256 depositCountLimit, AlphaAttestation calldata attestation) external returns (uint256 amount, uint256 consumed);
135
+ function sweepBucketWithAttestation(address verifier, IP2IDVerifier.Constraint calldata constraint, address token, bytes calldata proof, uint256 depositCountLimit, AlphaAttestation calldata attestation) external returns (uint256 amount, uint256 consumed);
136
+ function sweepBucketDepositsWithAttestation(address verifier, IP2IDVerifier.Constraint calldata constraint, address token, uint256[] calldata depositIds, bytes calldata proof, AlphaAttestation calldata attestation) external returns (uint256 amount);
112
137
  }
@@ -0,0 +1,42 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.27;
3
+
4
+ import {IP2IDVault} from "./IP2IDVault.sol";
5
+
6
+ /// @title IP2IDVaultProxy
7
+ /// @notice A P2ID proxy with creation code fixed for its deployed factory. Its upgradeTo entry
8
+ /// point requires an identity proof and a registered target. Delegated implementations
9
+ /// are trusted with all proxy storage, including the implementation slot.
10
+ interface IP2IDVaultProxy {
11
+ function alphaUpgradeNonceUsed(uint256 nonce) external view returns (bool);
12
+ function upgradeToWithAttestation(bytes32 identityHash, address newImplementation, bytes calldata proof, IP2IDVault.AlphaAttestation calldata attestation) external;
13
+ /// @notice ERC-1967 upgrade event.
14
+ event Upgraded(address indexed implementation);
15
+
16
+ /// @notice The factory that deployed this proxy and whose registry bounds its implementations.
17
+ function factory() external view returns (address);
18
+ /// @notice The implementation used for delegated calls; proxy-defined selectors take precedence.
19
+ function implementation() external view returns (address);
20
+ /// @notice The wallet and issue time of the proof behind the last upgrade (zero before the first).
21
+ /// Later upgrades need a proof at least this recent; an equal time only for the same wallet.
22
+ /// Delegated code can overwrite this record; upgradeTo ignores a record beyond its future-time bound.
23
+ function lastUpgrade() external view returns (address wallet, uint64 iat);
24
+ /// @notice Move this vault to `newImplementation`, which the factory must have registered.
25
+ /// `proof` is verified through the factory's default verifier for `identityHash` (the
26
+ /// identity this address was derived from); the wallet it resolves to must be the caller,
27
+ /// and its issue time must not exceed block.timestamp + 15 minutes or fall below lastUpgrade.
28
+ /// It must also meet the current implementation's latestProofIat for that verifier and
29
+ /// untrackedProofIat; failed, malformed or excessively future-dated floor reads count as zero.
30
+ /// This call writes the implementation slot and lastUpgrade record, then calls
31
+ /// acceptOwnerProof through the new implementation without verifying the proof again.
32
+ /// Hook failure reverts the entire upgrade. P2IDVault's hook requires the proven wallet
33
+ /// to be the resulting cached owner, rejecting conflicting equal-time wallet proofs.
34
+ /// The proxy requires the hook selector as a canonical 32-byte ABI acknowledgement;
35
+ /// absent, malformed or incorrect acknowledgements revert the entire upgrade.
36
+ /// After the hook, the implementation must still match the target, owner(verifier)
37
+ /// must report the proven wallet, and latestProofIat(verifier) must be at least iat.
38
+ /// Nested upgradeTo calls revert while an upgrade is running.
39
+ /// @dev Getters run through delegated code and cannot establish that an implementation is safe.
40
+ /// This entry point performs no separate initialization or storage-migration call.
41
+ function upgradeTo(bytes32 identityHash, address newImplementation, bytes calldata proof) external;
42
+ }