@openzeppelin/compact-contracts 0.4.0-alpha.1 → 0.4.0-alpha.3
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/README.md +9 -5
- package/access/AccessControl.compact +13 -13
- package/access/Ownable.compact +15 -9
- package/access/ShieldedAccessControl.compact +25 -1
- package/access/ZOwnablePK.compact +8 -8
- package/crypto/EcdhMask.compact +1 -1
- package/crypto/Ecdsa.compact +4 -4
- package/crypto/Eip712.compact +168 -0
- package/crypto/ElGamal.compact +44 -3
- package/multisig/EcdsaSignerManager.compact +32 -15
- package/multisig/ForwarderPrivate.compact +11 -5
- package/multisig/ForwarderShielded.compact +2 -2
- package/multisig/ForwarderUnshielded.compact +2 -2
- package/multisig/ProposalManager.compact +194 -22
- package/multisig/ShieldedTreasury.compact +28 -1
- package/multisig/ShieldedTreasuryStateless.compact +1 -1
- package/multisig/Signer.compact +27 -79
- package/multisig/UnshieldedTreasury.compact +9 -1
- package/multisig/{presets/forwarder/ForwarderPrivate.compact → examples/ForwarderPrivateExample.compact} +3 -3
- package/multisig/{presets/forwarder/ForwarderShielded.compact → examples/ForwarderShieldedExample.compact} +3 -3
- package/multisig/{presets/forwarder/ForwarderUnshielded.compact → examples/ForwarderUnshieldedExample.compact} +3 -3
- package/multisig/examples/NativeShieldedTokenIssuerExample.compact +143 -0
- package/multisig/examples/ShieldedMultiSigV2Example.compact +77 -0
- package/multisig/presets/NativeShieldedTokenIssuer.compact +557 -0
- package/multisig/presets/ShieldedMultiSigV2.compact +251 -188
- package/package.json +15 -11
- package/security/Allowlist.compact +5 -5
- package/security/Blocklist.compact +5 -5
- package/security/Initializable.compact +8 -4
- package/security/Pausable.compact +10 -6
- package/token/ConfidentialFungibleToken.compact +337 -79
- package/token/FungibleToken.compact +35 -21
- package/token/MultiToken.compact +15 -15
- package/token/NativeShieldedToken.compact +65 -16
- package/token/NativeShieldedTokenCore.compact +57 -15
- package/token/NativeShieldedTokenFamily.compact +66 -16
- package/token/NonFungibleToken.compact +83 -34
- package/token/extensions/ConfidentialFungibleTokenPublicSupply.compact +11 -6
- package/token/extensions/NativeShieldedTokenDerivedNonce.compact +2 -2
- package/token/extensions/NativeShieldedTokenFamilyPublicSupply.compact +7 -7
- package/token/extensions/NativeShieldedTokenPublicSupply.compact +7 -7
- package/token/extensions/NativeShieldedTokenPublicSupplyCore.compact +5 -5
- package/utils/EvmAbi.compact +134 -0
- package/utils/Utils.compact +11 -1
- package/multisig/presets/ShieldedMultiSig.compact +0 -227
- package/multisig/presets/ShieldedMultiSigV3.compact +0 -311
package/README.md
CHANGED
|
@@ -189,11 +189,15 @@ Compiling 14 circuits:
|
|
|
189
189
|
Overall progress [====================] 14/14
|
|
190
190
|
```
|
|
191
191
|
|
|
192
|
-
ZKIR v3: the library targets ZKIR v2, the compiler 0.34.0 default.
|
|
193
|
-
`--feature-zkir-v3` only when the contract
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
192
|
+
ZKIR v3: the library targets ZKIR v2, the compiler 0.34.0 default.
|
|
193
|
+
Pass `--feature-zkir-v3` only when the contract reaches a module that needs it:
|
|
194
|
+
the secp256k1-based `crypto/Ecdsa` and `multisig/EcdsaSignerManager`,
|
|
195
|
+
or the `keccak256`-based `crypto/Eip712`.
|
|
196
|
+
`multisig/presets/ShieldedMultiSigV2`, `multisig/presets/NativeShieldedTokenIssuer`
|
|
197
|
+
and the `multisig/examples/` contracts reach both.
|
|
198
|
+
`utils/EvmAbi` needs no `keccak256` of its own and compiles on either backend.
|
|
199
|
+
Compiling the other modules under v3 currently hits upstream blockers,
|
|
200
|
+
listed under [Known issues](CHANGELOG.md#known-issues).
|
|
197
201
|
|
|
198
202
|
## Development
|
|
199
203
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0-alpha.
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0-alpha.3 (access/AccessControl.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
@@ -168,7 +168,7 @@ module AccessControl {
|
|
|
168
168
|
/**
|
|
169
169
|
* @description Returns `true` if `account` has been granted `roleId`.
|
|
170
170
|
*
|
|
171
|
-
* @
|
|
171
|
+
* @constraints k=10, rows=1017
|
|
172
172
|
*
|
|
173
173
|
* @param {Bytes<32>} roleId - The role identifier.
|
|
174
174
|
* @param {Either<Bytes<32>, ContractAddress>} account - The account to query.
|
|
@@ -206,7 +206,7 @@ module AccessControl {
|
|
|
206
206
|
* In the case of an external (non-contract) caller, the caller’s identity is
|
|
207
207
|
* derived from the `wit_AccessControlSK` witness as `persistentHash(secretKey)`.
|
|
208
208
|
*
|
|
209
|
-
* @
|
|
209
|
+
* @constraints k=13, rows=2660
|
|
210
210
|
*
|
|
211
211
|
* Requirements:
|
|
212
212
|
*
|
|
@@ -225,7 +225,7 @@ module AccessControl {
|
|
|
225
225
|
/**
|
|
226
226
|
* @description Reverts if `account` is missing `roleId`.
|
|
227
227
|
*
|
|
228
|
-
* @
|
|
228
|
+
* @constraints k=10, rows=997
|
|
229
229
|
*
|
|
230
230
|
* Requirements:
|
|
231
231
|
*
|
|
@@ -248,7 +248,7 @@ module AccessControl {
|
|
|
248
248
|
*
|
|
249
249
|
* To change a role's admin use {_setRoleAdmin}.
|
|
250
250
|
*
|
|
251
|
-
* @
|
|
251
|
+
* @constraints k=9, rows=371
|
|
252
252
|
*
|
|
253
253
|
* @param {Bytes<32>} roleId - The role identifier.
|
|
254
254
|
* @return {Bytes<32>} roleAdmin - The admin role that controls `roleId`.
|
|
@@ -263,7 +263,7 @@ module AccessControl {
|
|
|
263
263
|
/**
|
|
264
264
|
* @description Grants `roleId` to `account`.
|
|
265
265
|
*
|
|
266
|
-
* @
|
|
266
|
+
* @constraints k=13, rows=3527
|
|
267
267
|
*
|
|
268
268
|
* Requirements:
|
|
269
269
|
*
|
|
@@ -285,7 +285,7 @@ module AccessControl {
|
|
|
285
285
|
/**
|
|
286
286
|
* @description Revokes `roleId` from `account`.
|
|
287
287
|
*
|
|
288
|
-
* @
|
|
288
|
+
* @constraints k=13, rows=3457
|
|
289
289
|
*
|
|
290
290
|
* Requirements:
|
|
291
291
|
*
|
|
@@ -314,7 +314,7 @@ module AccessControl {
|
|
|
314
314
|
* `persistentHash(secretKey)`. The `callerConfirmation` parameter must match
|
|
315
315
|
* the caller's computed account identifier to prevent accidental renunciation.
|
|
316
316
|
*
|
|
317
|
-
* @
|
|
317
|
+
* @constraints k=13, rows=3313
|
|
318
318
|
*
|
|
319
319
|
* Requirements:
|
|
320
320
|
*
|
|
@@ -339,7 +339,7 @@ module AccessControl {
|
|
|
339
339
|
/**
|
|
340
340
|
* @description Sets `adminRole` as `roleId`'s admin role.
|
|
341
341
|
*
|
|
342
|
-
* @
|
|
342
|
+
* @constraints k=10, rows=579
|
|
343
343
|
*
|
|
344
344
|
* @param {Bytes<32>} roleId - The role identifier.
|
|
345
345
|
* @param {Bytes<32>} adminRole - The admin role identifier.
|
|
@@ -353,7 +353,7 @@ module AccessControl {
|
|
|
353
353
|
* @description Attempts to grant `roleId` to `account` and returns a boolean indicating if `roleId` was granted.
|
|
354
354
|
* Internal circuit without access restriction.
|
|
355
355
|
*
|
|
356
|
-
* @
|
|
356
|
+
* @constraints k=11, rows=1141
|
|
357
357
|
*
|
|
358
358
|
* Requirements:
|
|
359
359
|
*
|
|
@@ -376,7 +376,7 @@ module AccessControl {
|
|
|
376
376
|
* @description Attempts to grant `roleId` to `account` and returns a boolean indicating if `roleId` was granted.
|
|
377
377
|
* Internal circuit without access restriction. It does NOT check if the role is granted to a ContractAddress.
|
|
378
378
|
*
|
|
379
|
-
* @
|
|
379
|
+
* @constraints k=11, rows=1140
|
|
380
380
|
*
|
|
381
381
|
* @notice External smart contracts cannot call the access control contract at this time, so granting a role to a ContractAddress may
|
|
382
382
|
* render a circuit permanently inaccessible.
|
|
@@ -409,7 +409,7 @@ module AccessControl {
|
|
|
409
409
|
* @description Attempts to revoke `roleId` from `account` and returns a boolean indicating if `roleId` was revoked.
|
|
410
410
|
* Internal circuit without access restriction.
|
|
411
411
|
*
|
|
412
|
-
* @
|
|
412
|
+
* @constraints k=11, rows=1071
|
|
413
413
|
*
|
|
414
414
|
* @param {Bytes<32>} roleId - The role identifier.
|
|
415
415
|
* @param {Either<Bytes<32>, ContractAddress>} account - A Bytes<32> or ContractAddress.
|
|
@@ -437,7 +437,7 @@ module AccessControl {
|
|
|
437
437
|
*
|
|
438
438
|
* The result is a 32-byte commitment that uniquely identifies the caller.
|
|
439
439
|
*
|
|
440
|
-
* @
|
|
440
|
+
* @constraints k=13, rows=2294
|
|
441
441
|
*
|
|
442
442
|
* @returns {Bytes<32>} accountId - The computed account identifier.
|
|
443
443
|
*/
|
package/access/Ownable.compact
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0-alpha.
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0-alpha.3 (access/Ownable.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
@@ -94,6 +94,12 @@ module Ownable {
|
|
|
94
94
|
*/
|
|
95
95
|
export ledger _isInitialized: Boolean;
|
|
96
96
|
|
|
97
|
+
/**
|
|
98
|
+
* @description The current owner, canonicalized on write. A `left` holds an
|
|
99
|
+
* account identifier, stored as supplied and never checked against the secret
|
|
100
|
+
* key it should derive from; a `right` holds a contract address. The zero
|
|
101
|
+
* value means ownership has been renounced.
|
|
102
|
+
*/
|
|
97
103
|
export ledger _owner: Either<Bytes<32>, ContractAddress>;
|
|
98
104
|
|
|
99
105
|
/**
|
|
@@ -111,7 +117,7 @@ module Ownable {
|
|
|
111
117
|
* @description Initializes the contract by setting the `initialOwner`.
|
|
112
118
|
* This must be called in the contract's constructor.
|
|
113
119
|
*
|
|
114
|
-
* @
|
|
120
|
+
* @constraints k=10, rows=626
|
|
115
121
|
*
|
|
116
122
|
* Requirements:
|
|
117
123
|
*
|
|
@@ -158,7 +164,7 @@ module Ownable {
|
|
|
158
164
|
/**
|
|
159
165
|
* @description Returns the current contract owner.
|
|
160
166
|
*
|
|
161
|
-
* @
|
|
167
|
+
* @constraints k=7, rows=74
|
|
162
168
|
*
|
|
163
169
|
* Requirements:
|
|
164
170
|
*
|
|
@@ -178,7 +184,7 @@ module Ownable {
|
|
|
178
184
|
* interactions are supported in Compact.
|
|
179
185
|
* This restriction prevents permanently disabling access to a circuit.
|
|
180
186
|
*
|
|
181
|
-
* @
|
|
187
|
+
* @constraints k=13, rows=2947
|
|
182
188
|
*
|
|
183
189
|
* Requirements:
|
|
184
190
|
*
|
|
@@ -205,7 +211,7 @@ module Ownable {
|
|
|
205
211
|
* Ownership privileges sent to a contract address may become uncallable.
|
|
206
212
|
* Once contract-to-contract calls are supported, this circuit may be deprecated.
|
|
207
213
|
*
|
|
208
|
-
* @
|
|
214
|
+
* @constraints k=13, rows=2944
|
|
209
215
|
*
|
|
210
216
|
* Requirements:
|
|
211
217
|
*
|
|
@@ -228,7 +234,7 @@ module Ownable {
|
|
|
228
234
|
* It will not be possible to call `assertOnlyOwner` circuits anymore.
|
|
229
235
|
* Can only be called by the current owner.
|
|
230
236
|
*
|
|
231
|
-
* @
|
|
237
|
+
* @constraints k=13, rows=2353
|
|
232
238
|
*
|
|
233
239
|
* Requirements:
|
|
234
240
|
*
|
|
@@ -256,7 +262,7 @@ module Ownable {
|
|
|
256
262
|
* In the case of an external (non-contract) caller, the caller’s identity is
|
|
257
263
|
* derived from the `wit_OwnableSK` witness as `persistentHash(secretKey)`.
|
|
258
264
|
*
|
|
259
|
-
* @
|
|
265
|
+
* @constraints k=13, rows=2349
|
|
260
266
|
*
|
|
261
267
|
* Requirements:
|
|
262
268
|
*
|
|
@@ -282,7 +288,7 @@ module Ownable {
|
|
|
282
288
|
* interactions are supported in Compact.
|
|
283
289
|
* This restriction prevents circuits from being inadvertently locked in contracts.
|
|
284
290
|
*
|
|
285
|
-
* @
|
|
291
|
+
* @constraints k=10, rows=598
|
|
286
292
|
*
|
|
287
293
|
* Requirements:
|
|
288
294
|
*
|
|
@@ -307,7 +313,7 @@ module Ownable {
|
|
|
307
313
|
* Ownership privileges sent to a contract address may become uncallable.
|
|
308
314
|
* Once contract-to-contract calls are supported, this circuit may be deprecated.
|
|
309
315
|
*
|
|
310
|
-
* @
|
|
316
|
+
* @constraints k=10, rows=595
|
|
311
317
|
*
|
|
312
318
|
* Requirements:
|
|
313
319
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0-alpha.
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0-alpha.3 (access/ShieldedAccessControl.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
@@ -199,6 +199,10 @@ module ShieldedAccessControl {
|
|
|
199
199
|
/**
|
|
200
200
|
* @ledger _adminRoles
|
|
201
201
|
* @description Mapping from a role identifier to an admin role identifier.
|
|
202
|
+
* @type {RoleIdentifier} role - The role being administered.
|
|
203
|
+
* @type {RoleIdentifier} adminRole - The role permitted to grant and revoke it.
|
|
204
|
+
* @type {Map<role, adminRole>}
|
|
205
|
+
* @type {Map<RoleIdentifier, RoleIdentifier>} _adminRoles
|
|
202
206
|
*/
|
|
203
207
|
export ledger _adminRoles: Map<RoleIdentifier, RoleIdentifier>;
|
|
204
208
|
|
|
@@ -311,6 +315,8 @@ module ShieldedAccessControl {
|
|
|
311
315
|
/**
|
|
312
316
|
* @description Reverts if caller cannot provide a valid proof of ownership for `role`.
|
|
313
317
|
*
|
|
318
|
+
* @constraints k=15, rows=16997
|
|
319
|
+
*
|
|
314
320
|
* Requirements:
|
|
315
321
|
*
|
|
316
322
|
* - caller must prove ownership of `role`.
|
|
@@ -337,6 +343,8 @@ module ShieldedAccessControl {
|
|
|
337
343
|
* caller if the proving environment supplies an invalid Merkle path. This circuit will never return true for an
|
|
338
344
|
* unauthorized caller.
|
|
339
345
|
*
|
|
346
|
+
* @constraints k=15, rows=16997
|
|
347
|
+
*
|
|
340
348
|
* Requirements:
|
|
341
349
|
*
|
|
342
350
|
* - caller must not provide valid Merkle tree path for a different `(role, accountId)` pairing.
|
|
@@ -392,6 +400,8 @@ module ShieldedAccessControl {
|
|
|
392
400
|
* limited Merkle tree storage slots. Once revoked, a role cannot be re-granted to the same `accountId`. A new
|
|
393
401
|
* `accountId` must be generated to be re-authorized for a revoked `role`.
|
|
394
402
|
*
|
|
403
|
+
* @constraints k=15, rows=28995
|
|
404
|
+
*
|
|
395
405
|
* Requirements:
|
|
396
406
|
*
|
|
397
407
|
* - caller must prove they're an admin for `role`.
|
|
@@ -434,6 +444,8 @@ module ShieldedAccessControl {
|
|
|
434
444
|
* but are otherwise benign. A single nullifier invalidates all duplicate commitments.
|
|
435
445
|
* Implementing contracts are responsible for mitigating tree exhaustion risk.
|
|
436
446
|
*
|
|
447
|
+
* @constraints k=14, rows=12250
|
|
448
|
+
*
|
|
437
449
|
* Requirements:
|
|
438
450
|
*
|
|
439
451
|
* - The `(role, accountId)` pairing must not be already revoked.
|
|
@@ -466,6 +478,8 @@ module ShieldedAccessControl {
|
|
|
466
478
|
* @warning Outside observers may be able to use timing and pattern analysis to weaken pseudonymity
|
|
467
479
|
* guarantees if renounceRole is used in tandem with other on-chain actions.
|
|
468
480
|
*
|
|
481
|
+
* @constraints k=14, rows=14440
|
|
482
|
+
*
|
|
469
483
|
* Requirements:
|
|
470
484
|
*
|
|
471
485
|
* - The caller must provide a valid `accountId` for the role.
|
|
@@ -497,6 +511,8 @@ module ShieldedAccessControl {
|
|
|
497
511
|
* `role`. At this time, proofs of non-membership on values in the Merkle tree LDT are not possible
|
|
498
512
|
* so a `(role, accountId)` pairing that does not exist can still be revoked.
|
|
499
513
|
*
|
|
514
|
+
* @constraints k=15, rows=27005
|
|
515
|
+
*
|
|
500
516
|
* Requirements:
|
|
501
517
|
*
|
|
502
518
|
* - caller must prove they're an admin for `role`.
|
|
@@ -533,6 +549,8 @@ module ShieldedAccessControl {
|
|
|
533
549
|
* @warning Exposing this circuit directly in an implementing contract would allow anyone to revoke
|
|
534
550
|
* roles without authorization. It must be wrapped with appropriate access control.
|
|
535
551
|
*
|
|
552
|
+
* @constraints k=14, rows=10260
|
|
553
|
+
*
|
|
536
554
|
* Requirements:
|
|
537
555
|
*
|
|
538
556
|
* - The `(role, accountId)` pairing must not be already revoked.
|
|
@@ -599,6 +617,8 @@ module ShieldedAccessControl {
|
|
|
599
617
|
*
|
|
600
618
|
* To change a role's admin use {_setRoleAdmin}.
|
|
601
619
|
*
|
|
620
|
+
* @constraints k=9, rows=374
|
|
621
|
+
*
|
|
602
622
|
* Disclosures:
|
|
603
623
|
*
|
|
604
624
|
* - A role identifier.
|
|
@@ -621,6 +641,8 @@ module ShieldedAccessControl {
|
|
|
621
641
|
* @warning Exposing this circuit directly in an implementing contract would allow anyone to assign
|
|
622
642
|
* arbitrary admin roles without authorization. It must be wrapped with appropriate access control.
|
|
623
643
|
*
|
|
644
|
+
* @constraints k=10, rows=581
|
|
645
|
+
*
|
|
624
646
|
* Disclosures:
|
|
625
647
|
*
|
|
626
648
|
* - The role identifier
|
|
@@ -707,6 +729,8 @@ module ShieldedAccessControl {
|
|
|
707
729
|
* - `commitmentDomain`: Domain separator `"ShieldedAccessControl:commitment"` (padded to 32 bytes) to prevent
|
|
708
730
|
* hash collisions when extending the module or using similar commitment schemes.
|
|
709
731
|
*
|
|
732
|
+
* @constraints k=13, rows=6404
|
|
733
|
+
*
|
|
710
734
|
* @param {RoleIdentifier} role - The role identifier.
|
|
711
735
|
* @param {AccountIdentifier} accountId - The unique identifier of the account.
|
|
712
736
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0-alpha.
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0-alpha.3 (access/ZOwnablePK.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
@@ -99,7 +99,7 @@ module ZOwnablePK {
|
|
|
99
99
|
* @warning The `ownerId` must be calculated prior to contract deployment using the SHA256 hashing algorithm.
|
|
100
100
|
* Using any other algorithm will result in a permanent loss of contract access.
|
|
101
101
|
*
|
|
102
|
-
* @
|
|
102
|
+
* @constraints k=14, rows=14933
|
|
103
103
|
*
|
|
104
104
|
* Requirements:
|
|
105
105
|
*
|
|
@@ -150,7 +150,7 @@ module ZOwnablePK {
|
|
|
150
150
|
* @description Returns the current commitment representing the contract owner.
|
|
151
151
|
* The full commitment is: `SHA256(SHA256(pk, nonce), instanceSalt, counter, domain)`.
|
|
152
152
|
*
|
|
153
|
-
* @
|
|
153
|
+
* @constraints k=6, rows=48
|
|
154
154
|
*
|
|
155
155
|
* Requirements:
|
|
156
156
|
*
|
|
@@ -167,7 +167,7 @@ module ZOwnablePK {
|
|
|
167
167
|
* @description Transfers ownership to `newOwnerId`.
|
|
168
168
|
* `newOwnerId` must be precalculated and given to the current owner off chain.
|
|
169
169
|
*
|
|
170
|
-
* @
|
|
170
|
+
* @constraints k=15, rows=17023
|
|
171
171
|
*
|
|
172
172
|
* Requirements:
|
|
173
173
|
*
|
|
@@ -191,7 +191,7 @@ module ZOwnablePK {
|
|
|
191
191
|
* It will not be possible to call `assertOnlyOwner` circuits anymore.
|
|
192
192
|
* Can only be called by the current owner.
|
|
193
193
|
*
|
|
194
|
-
* @
|
|
194
|
+
* @constraints k=14, rows=10579
|
|
195
195
|
*
|
|
196
196
|
* Requirements:
|
|
197
197
|
*
|
|
@@ -212,7 +212,7 @@ module ZOwnablePK {
|
|
|
212
212
|
* the stored owner commitment.
|
|
213
213
|
* Use this to only allow the owner to call specific circuits.
|
|
214
214
|
*
|
|
215
|
-
* @
|
|
215
|
+
* @constraints k=14, rows=10577
|
|
216
216
|
*
|
|
217
217
|
* Requirements:
|
|
218
218
|
*
|
|
@@ -257,7 +257,7 @@ module ZOwnablePK {
|
|
|
257
257
|
* - `domain`: Domain separator `"ZOwnablePK:shield:"` (padded to 32 bytes) to prevent
|
|
258
258
|
* hash collisions when extending the module or using similar commitment schemes.
|
|
259
259
|
*
|
|
260
|
-
* @
|
|
260
|
+
* @constraints k=13, rows=6544
|
|
261
261
|
*
|
|
262
262
|
* Requirements:
|
|
263
263
|
*
|
|
@@ -320,7 +320,7 @@ module ZOwnablePK {
|
|
|
320
320
|
* @description Transfers ownership to owner id `newOwnerId` without
|
|
321
321
|
* enforcing permission checks on the caller.
|
|
322
322
|
*
|
|
323
|
-
* @
|
|
323
|
+
* @constraints k=13, rows=6460
|
|
324
324
|
*
|
|
325
325
|
* Requirements:
|
|
326
326
|
*
|
package/crypto/EcdhMask.compact
CHANGED
package/crypto/Ecdsa.compact
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0-alpha.
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0-alpha.3 (crypto/Ecdsa.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
@@ -21,7 +21,7 @@ module Ecdsa {
|
|
|
21
21
|
* @description Returns whether `s` is canonical, i.e. `s <= n / 2` where `n`
|
|
22
22
|
* is the secp256k1 group order.
|
|
23
23
|
*
|
|
24
|
-
* @
|
|
24
|
+
* @constraints k=13, rows=5125 (zkir-v3)
|
|
25
25
|
*
|
|
26
26
|
* @param {Secp256k1Scalar} s - The `s` component of a signature.
|
|
27
27
|
* @returns {Boolean} True if `s` is in the low half.
|
|
@@ -72,7 +72,7 @@ module Ecdsa {
|
|
|
72
72
|
/**
|
|
73
73
|
* @description Rejects a signature in the high half.
|
|
74
74
|
*
|
|
75
|
-
* @
|
|
75
|
+
* @constraints k=13, rows=5156 (zkir-v3)
|
|
76
76
|
*
|
|
77
77
|
* Requirements:
|
|
78
78
|
*
|
|
@@ -90,7 +90,7 @@ module Ecdsa {
|
|
|
90
90
|
* low-s encoding. Reports the result instead of asserting, so a caller can
|
|
91
91
|
* fold it into a count or a threshold.
|
|
92
92
|
*
|
|
93
|
-
* @
|
|
93
|
+
* @constraints k=16, rows=34056 (zkir-v3)
|
|
94
94
|
*
|
|
95
95
|
* @param {Bytes<32>} msgHash - The digest that was signed.
|
|
96
96
|
* @param {Secp256k1EcdsaSignature} sig - The signature over `msgHash`.
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0-alpha.3 (crypto/Eip712.compact)
|
|
3
|
+
|
|
4
|
+
pragma language_version >= 0.26.0;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @module Eip712
|
|
8
|
+
* @description The EIP-712 typed-data envelope, for verifying signatures
|
|
9
|
+
* produced by Ethereum signing infrastructure.
|
|
10
|
+
*
|
|
11
|
+
* A typed-data signature covers `keccak256(0x1901 || domainSeparator ||
|
|
12
|
+
* structHash)`. The domain separator binds the signature to one application,
|
|
13
|
+
* so a signature obtained for any other domain cannot be replayed here — the
|
|
14
|
+
* property `personal_sign` does not provide, since it signs an opaque hash
|
|
15
|
+
* with no application binding.
|
|
16
|
+
*
|
|
17
|
+
* Build `structHash` from EVM ABI words (see `utils/EvmAbi`), with the
|
|
18
|
+
* operation's type hash as the first word.
|
|
19
|
+
*
|
|
20
|
+
* @notice The domain is `(name, version, salt)`. `chainId` and
|
|
21
|
+
* `verifyingContract` are omitted, which EIP-712 permits — every domain field
|
|
22
|
+
* is optional. They are omitted because neither is expressible: a Midnight
|
|
23
|
+
* contract address is 32 bytes and does not fit `verifyingContract`'s
|
|
24
|
+
* `address` type, and no network identifier is available in-circuit.
|
|
25
|
+
*
|
|
26
|
+
* On an EVM chain `verifyingContract` is what makes a domain identify one
|
|
27
|
+
* deployment rather than one application. Without it, a consumer has to get
|
|
28
|
+
* that binding elsewhere. There are two places to put it, and they are not
|
|
29
|
+
* equivalent:
|
|
30
|
+
*
|
|
31
|
+
* - As a field of the operation struct, holding the contract's own address.
|
|
32
|
+
* This is the stronger option and the one to reach for by default: a
|
|
33
|
+
* Midnight address is randomised at deployment and cannot be predicted, so
|
|
34
|
+
* no two instances share one, and a signature for one deployment cannot
|
|
35
|
+
* authorise another.
|
|
36
|
+
* - As `salt`, a per-deployment value in the domain. This is weaker, because
|
|
37
|
+
* it separates domains rather than messages. It is worth adding when the
|
|
38
|
+
* signer gates on domains but cannot read struct fields, since that is the
|
|
39
|
+
* only level at which it is visible.
|
|
40
|
+
*
|
|
41
|
+
* A consumer doing neither has one domain shared by every deployment of the
|
|
42
|
+
* contract, and nothing distinguishing them.
|
|
43
|
+
*
|
|
44
|
+
* @notice Requires ZKIR v3: `keccak256` is unavailable on the v2 backend.
|
|
45
|
+
*/
|
|
46
|
+
module Eip712 {
|
|
47
|
+
import CompactStandardLibrary;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @description The 66-byte typed-data preimage: the two-byte prefix, the
|
|
51
|
+
* domain separator, then the struct hash. `Bytes<n>` is emitted at exactly
|
|
52
|
+
* `n` bytes, so this hashes as the concatenation an EVM signer produces.
|
|
53
|
+
*/
|
|
54
|
+
struct TypedDataPreimage {
|
|
55
|
+
prefixBytes: Bytes<2>,
|
|
56
|
+
domainSeparator: Bytes<32>,
|
|
57
|
+
structHash: Bytes<32>
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @description The four words of the domain separator's preimage.
|
|
62
|
+
*/
|
|
63
|
+
struct DomainFields {
|
|
64
|
+
typeHash: Bytes<32>,
|
|
65
|
+
hashedName: Bytes<32>,
|
|
66
|
+
hashedVersion: Bytes<32>,
|
|
67
|
+
salt: Bytes<32>
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @description `0x1901`, the EIP-191 version byte `0x01` behind the `0x19`
|
|
72
|
+
* marker, which is how EIP-712 identifies itself.
|
|
73
|
+
*
|
|
74
|
+
* @dev Written as byte values because the bytes are not printable. The
|
|
75
|
+
* version byte is what keeps a typed-data digest from colliding with a
|
|
76
|
+
* `personal_sign` one (version `0x45`) or an intended-validator one (`0x00`).
|
|
77
|
+
*
|
|
78
|
+
* @returns {Bytes<2>} The typed-data prefix.
|
|
79
|
+
*/
|
|
80
|
+
pure circuit TYPED_DATA_PREFIX(): Bytes<2> {
|
|
81
|
+
const raw: Vector<2, Uint<8>> = [25, 1];
|
|
82
|
+
|
|
83
|
+
return raw as Bytes<2>;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @description `keccak256("EIP712Domain(string name,string version,bytes32 salt)")`.
|
|
88
|
+
*
|
|
89
|
+
* @dev Written as a literal word. `compactc` emits a full keccak
|
|
90
|
+
* permutation even for a constant argument, so hashing the type string
|
|
91
|
+
* in-circuit would roughly double `domainSeparator`. The spec checks this
|
|
92
|
+
* word against the type string above.
|
|
93
|
+
*
|
|
94
|
+
* The string must match the domain's field set exactly: a difference of one
|
|
95
|
+
* character yields a different separator and every signature fails.
|
|
96
|
+
*
|
|
97
|
+
* @returns {Bytes<32>} The domain type hash.
|
|
98
|
+
*/
|
|
99
|
+
pure circuit DOMAIN_TYPEHASH(): Bytes<32> {
|
|
100
|
+
// keccak256("EIP712Domain(string name,string version,bytes32 salt)")
|
|
101
|
+
// = 0x599a80fcaa47b95e2323ab4d34d34e0cc9feda4b843edafcc30c7bdf60ea15bf
|
|
102
|
+
const typeHash: Vector<32, Uint<8>> = [
|
|
103
|
+
0x59, 0x9a, 0x80, 0xfc, 0xaa, 0x47, 0xb9, 0x5e,
|
|
104
|
+
0x23, 0x23, 0xab, 0x4d, 0x34, 0xd3, 0x4e, 0x0c,
|
|
105
|
+
0xc9, 0xfe, 0xda, 0x4b, 0x84, 0x3e, 0xda, 0xfc,
|
|
106
|
+
0xc3, 0x0c, 0x7b, 0xdf, 0x60, 0xea, 0x15, 0xbf
|
|
107
|
+
];
|
|
108
|
+
|
|
109
|
+
return typeHash as Bytes<32>;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @description Computes the domain separator for `(name, version, salt)`.
|
|
114
|
+
*
|
|
115
|
+
* EIP-712 encodes a `string` field as the keccak hash of its UTF-8 bytes,
|
|
116
|
+
* so the name and version arrive already hashed. Compact has no dynamic
|
|
117
|
+
* types, so a consumer hashes its own fixed-length literals.
|
|
118
|
+
*
|
|
119
|
+
* @constraints k=14, rows=4561 (zkir-v3)
|
|
120
|
+
*
|
|
121
|
+
* @param {Bytes<32>} hashedName - `keccak256(bytes(name))`.
|
|
122
|
+
* @param {Bytes<32>} hashedVersion - `keccak256(bytes(version))`.
|
|
123
|
+
* @param {Bytes<32>} salt - Per-deployment, per-network random value.
|
|
124
|
+
* @returns {Bytes<32>} The domain separator.
|
|
125
|
+
*/
|
|
126
|
+
export pure circuit domainSeparator(
|
|
127
|
+
hashedName: Bytes<32>,
|
|
128
|
+
hashedVersion: Bytes<32>,
|
|
129
|
+
salt: Bytes<32>
|
|
130
|
+
): Bytes<32> {
|
|
131
|
+
return keccak256<DomainFields>(DomainFields {
|
|
132
|
+
typeHash: DOMAIN_TYPEHASH(),
|
|
133
|
+
hashedName: hashedName,
|
|
134
|
+
hashedVersion: hashedVersion,
|
|
135
|
+
salt: salt
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @description Wraps a struct hash in the typed-data envelope, yielding the
|
|
141
|
+
* digest an EVM signer actually signs.
|
|
142
|
+
*
|
|
143
|
+
* @constraints k=14, rows=4463 (zkir-v3)
|
|
144
|
+
*
|
|
145
|
+
* Requirements:
|
|
146
|
+
*
|
|
147
|
+
* - `separator` must be non-zero, which an initialized domain always is.
|
|
148
|
+
*
|
|
149
|
+
* @param {Bytes<32>} separator - The domain separator, fixed at deployment.
|
|
150
|
+
* @param {Bytes<32>} structHash - `keccak256(typeHash || the operation's ABI words)`.
|
|
151
|
+
* @returns {Bytes<32>} The digest to verify signatures against.
|
|
152
|
+
*/
|
|
153
|
+
export pure circuit hashTypedData(
|
|
154
|
+
separator: Bytes<32>,
|
|
155
|
+
structHash: Bytes<32>
|
|
156
|
+
): Bytes<32> {
|
|
157
|
+
// A zero separator is what an uninitialized ledger cell reads as, and a
|
|
158
|
+
// digest built from one still verifies signatures. Fail closed rather than
|
|
159
|
+
// authorize an operation under an unset domain.
|
|
160
|
+
assert(separator != pad(32, ""), "Eip712: domain separator not set");
|
|
161
|
+
|
|
162
|
+
return keccak256<TypedDataPreimage>(TypedDataPreimage {
|
|
163
|
+
prefixBytes: TYPED_DATA_PREFIX(),
|
|
164
|
+
domainSeparator: separator,
|
|
165
|
+
structHash: structHash
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
package/crypto/ElGamal.compact
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0-alpha.
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0-alpha.3 (crypto/ElGamal.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
@@ -38,6 +38,13 @@ pragma language_version >= 0.26.0;
|
|
|
38
38
|
* cast reduces modulo the subgroup order, so casting at a call site would
|
|
39
39
|
* silently accept an out-of-range scalar the typed parameter rejects.
|
|
40
40
|
*
|
|
41
|
+
* @dev Domain separation. `persistentHash<Vector<N, Bytes<32>>>` is NOT
|
|
42
|
+
* domain-separating on its own. Two circuits hashing the same arity and
|
|
43
|
+
* element type share one hash domain, and the hash cannot tell which slot was
|
|
44
|
+
* "meant" as a tag. `secretToScalar` therefore prefixes a fixed constant, and
|
|
45
|
+
* that constant is placed FIRST so no call to `expandRandomness` (whose two
|
|
46
|
+
* slots are both caller-supplied) can reproduce the tuple by ordinary use.
|
|
47
|
+
*
|
|
41
48
|
* @dev TRUST ASSUMPTION — subgroup membership. This is the module's most
|
|
42
49
|
* load-bearing assumption. Every `JubjubPoint` reaching a curve operation is
|
|
43
50
|
* assumed to be in the Jubjub prime-order subgroup, including points supplied by
|
|
@@ -105,11 +112,34 @@ module ElGamal {
|
|
|
105
112
|
* @description Maps a 32-byte secret to a valid Jubjub scalar. See the
|
|
106
113
|
* module-level hash-to-scalar note for why `degradeToTransient` is required.
|
|
107
114
|
*
|
|
115
|
+
* @dev Domain separation here is load-bearing, not cosmetic. This output is
|
|
116
|
+
* the private key protecting every ciphertext held under an account. Public
|
|
117
|
+
* account identifiers derived from `Utils.computeAccountId`, for example,
|
|
118
|
+
* are computed as `persistentHash([secretKey])`, and that identifier
|
|
119
|
+
* is stored in the clear as a ledger map key. Untagged, this circuit
|
|
120
|
+
* would compute that same hash, so a secret used in both roles would
|
|
121
|
+
* have its encryption key recoverable from a published identifier by applying
|
|
122
|
+
* `degradeToTransient`. The tag makes the two derivations unrelated, so a
|
|
123
|
+
* wallet MAY safely derive its account secret and its encryption secret from
|
|
124
|
+
* common key material.
|
|
125
|
+
*
|
|
126
|
+
* @dev The tag is FIRST, deliberately. `expandRandomness` hashes
|
|
127
|
+
* `[seed, tag]` with both slots caller-supplied, so tagging this circuit as
|
|
128
|
+
* `[secret, tag]` would make `secretToScalar(x)` identical to
|
|
129
|
+
* `expandRandomness(x, <this tag>)` reachable by passing this domain string
|
|
130
|
+
* to the parameter that exists to receive domain strings. Leading with the
|
|
131
|
+
* tag means reproducing this output through `expandRandomness` would require
|
|
132
|
+
* passing the domain constant as the *seed*. Do not normalise the orderings.
|
|
133
|
+
*
|
|
108
134
|
* @param secret - The 32-byte secret to map.
|
|
109
135
|
* @return A valid Jubjub scalar.
|
|
110
136
|
*/
|
|
111
137
|
export pure circuit secretToScalar(secret: Bytes<32>): JubjubScalar {
|
|
112
|
-
return degradeToTransient(
|
|
138
|
+
return degradeToTransient(
|
|
139
|
+
persistentHash<Vector<2, Bytes<32>>>(
|
|
140
|
+
[pad(32, "ElGamal:secretToScalar"), secret]
|
|
141
|
+
)
|
|
142
|
+
) as JubjubScalar;
|
|
113
143
|
}
|
|
114
144
|
|
|
115
145
|
/**
|
|
@@ -419,6 +449,17 @@ module ElGamal {
|
|
|
419
449
|
* wrong plaintext fails the decryption check. Lifted special case of
|
|
420
450
|
* `assertDecryptsToPoint` with the message point `g^claimedValue`.
|
|
421
451
|
*
|
|
452
|
+
* @notice `claimedValue` is the widest `Uint` Compact offers, so this parameter
|
|
453
|
+
* never bounds a caller. A narrower value costs proportionally fewer rows: the
|
|
454
|
+
* range constraint belongs to where the value is declared, not to this
|
|
455
|
+
* signature.
|
|
456
|
+
*
|
|
457
|
+
* @warning The claim domain must stay below the Jubjub subgroup order `l`:
|
|
458
|
+
* verification compares `g^claimedValue`, so two claims congruent mod `l` are
|
|
459
|
+
* indistinguishable. `Uint<248>` clears `l` (~2^251.86) by under 4 bits, and
|
|
460
|
+
* that width is set by Compact's cap rather than by this bound. 251 is the
|
|
461
|
+
* widest sound `Uint` if the cap ever rises.
|
|
462
|
+
*
|
|
422
463
|
* Requirements:
|
|
423
464
|
*
|
|
424
465
|
* - `ek` is the secret for `pk`.
|
|
@@ -433,7 +474,7 @@ module ElGamal {
|
|
|
433
474
|
ct: Ciphertext,
|
|
434
475
|
pk: JubjubPoint,
|
|
435
476
|
ek: Bytes<32>,
|
|
436
|
-
claimedValue: Uint<
|
|
477
|
+
claimedValue: Uint<248>
|
|
437
478
|
): [] {
|
|
438
479
|
assertDecryptsToPoint(ct, pk, ek, ecMulGenerator(claimedValue as JubjubScalar));
|
|
439
480
|
}
|