@openzeppelin/compact-contracts 0.4.0-alpha.5 → 0.4.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/README.md +1 -1
- package/access/AccessControl.compact +1 -1
- package/access/Ownable.compact +1 -3
- package/access/ShieldedAccessControl.compact +44 -41
- package/access/ZOwnablePK.compact +12 -5
- package/crypto/EcdhMask.compact +11 -1
- package/crypto/Ecdsa.compact +1 -1
- package/crypto/Eip712.compact +1 -1
- package/crypto/ElGamal.compact +1 -1
- package/multisig/ForwarderPrivate.compact +17 -6
- package/multisig/ForwarderShielded.compact +1 -1
- package/multisig/ForwarderUnshielded.compact +1 -1
- package/multisig/ProposalManager.compact +65 -127
- package/multisig/RecipientTypes.compact +48 -0
- package/multisig/Secp256k1EcdsaMultisig.compact +275 -0
- package/multisig/ShieldedTreasury.compact +20 -8
- package/multisig/ShieldedTreasuryStateless.compact +11 -5
- package/multisig/Signer.compact +1 -1
- package/multisig/UnshieldedTreasury.compact +24 -11
- package/multisig/examples/ForwarderPrivateExample.compact +3 -2
- package/multisig/examples/ForwarderShieldedExample.compact +1 -1
- package/multisig/examples/ForwarderUnshieldedExample.compact +1 -1
- package/multisig/examples/NativeShieldedTokenIssuerExample.compact +4 -4
- package/multisig/examples/ShieldedMultiSigV2Example.compact +7 -9
- package/multisig/presets/NativeShieldedTokenIssuer.compact +88 -84
- package/multisig/presets/ShieldedMultiSigV2.compact +50 -52
- package/package.json +1 -1
- package/security/Allowlist.compact +1 -1
- package/security/Blocklist.compact +1 -1
- package/security/Initializable.compact +1 -3
- package/security/Pausable.compact +1 -1
- package/token/ConfidentialFungibleToken.compact +70 -22
- package/token/FungibleToken.compact +1 -3
- package/token/MultiToken.compact +1 -3
- package/token/NativeShieldedToken.compact +11 -3
- package/token/NativeShieldedTokenCore.compact +1 -1
- package/token/NativeShieldedTokenFamily.compact +1 -1
- package/token/NonFungibleToken.compact +1 -3
- package/token/examples/ZOwnableNativeShieldedTokenExample.compact +109 -0
- package/token/extensions/ConfidentialFungibleTokenPublicSupply.compact +1 -1
- package/token/extensions/NativeShieldedTokenDerivedNonce.compact +1 -1
- package/token/presets/ZOwnableNativeShieldedToken.compact +314 -0
- package/utils/EvmAbi.compact +1 -1
- package/utils/Utils.compact +1 -1
- package/multisig/EcdsaSignerManager.compact +0 -248
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// OpenZeppelin Compact Contracts v0.4.0
|
|
2
|
+
// OpenZeppelin Compact Contracts v0.4.0 (multisig/presets/NativeShieldedTokenIssuer.compact)
|
|
3
3
|
|
|
4
4
|
pragma language_version >= 0.26.0;
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* @module NativeShieldedTokenIssuer
|
|
8
8
|
* @description
|
|
9
|
-
* A
|
|
9
|
+
* A threshold ECDSA multisig that mints and burns one native shielded token,
|
|
10
10
|
* for tokenized deposits. Value enters only through `mint` (to a holder's
|
|
11
11
|
* coin public key) or `mintToSelf` (a coin this contract holds) and leaves
|
|
12
12
|
* only through `burn` (a holder's coin, paid into the tx) or `burnFromSelf`
|
|
13
|
-
* (a coin this contract holds); each is a single tx carrying
|
|
14
|
-
* signers' approvals
|
|
13
|
+
* (a coin this contract holds); each is a single tx carrying `t` registered
|
|
14
|
+
* signers' approvals.
|
|
15
15
|
*
|
|
16
|
-
* Composes `
|
|
16
|
+
* Composes `Secp256k1EcdsaMultisig` (signer commitments, approval checks),
|
|
17
17
|
* `NativeShieldedToken` as `NST_` (one token; domain, `name`, `symbol` and
|
|
18
18
|
* `decimals` fixed at construction) and `NativeShieldedTokenDerivedNonce` as
|
|
19
19
|
* `NSTDerivedNonce_` (coin nonces derived from a counter).
|
|
@@ -58,9 +58,9 @@ pragma language_version >= 0.26.0;
|
|
|
58
58
|
* uint256 amount,bytes32 coinNonce,uint256 coinValue)")`, written as
|
|
59
59
|
* literal words.
|
|
60
60
|
* - Signer commitment: `cm = H<SignerCommitmentInput>({ pkX, pkY, salt,
|
|
61
|
-
* domain: pad(32, "
|
|
62
|
-
* coordinates as `Bytes<32>`. `_calculateSignerId` is the
|
|
63
|
-
* circuit.
|
|
61
|
+
* domain: pad(32, "Secp256k1EcdsaMultisig:signer") })`, `pkX` / `pkY`
|
|
62
|
+
* the affine coordinates as `Bytes<32>`. `_calculateSignerId` is the
|
|
63
|
+
* exported pure circuit.
|
|
64
64
|
* - Coin nonce: `evolveNonce(counter, pad(32, "NativeShieldedToken:nonce"))`
|
|
65
65
|
* over the derived-nonce counter after its increment.
|
|
66
66
|
* - Encoding: `H` hashes the Compact encoding, not a byte concatenation.
|
|
@@ -72,25 +72,31 @@ pragma language_version >= 0.26.0;
|
|
|
72
72
|
*
|
|
73
73
|
* @notice Implementing contracts register the signer set from their
|
|
74
74
|
* constructor by calling this module's `initialize`, and MUST NOT import
|
|
75
|
-
* `
|
|
75
|
+
* `Signer` or `Secp256k1EcdsaMultisig` directly.
|
|
76
76
|
*
|
|
77
77
|
* @dev Parameterization:
|
|
78
|
-
*
|
|
78
|
+
* `t` is the approval width and the threshold, fixed at import
|
|
79
|
+
* (`"../presets/NativeShieldedTokenIssuer"<t>`). The implementing contract
|
|
80
|
+
* fixes the signer count `n` at `initialize`. Import one width per contract:
|
|
81
|
+
* two widths share one signer registry, see `Secp256k1EcdsaMultisig`.
|
|
82
|
+
* `NativeShieldedTokenIssuerExample` fixes 2-of-3. The `@constraints` tags on
|
|
83
|
+
* the gated circuits are measured at `t = 2`.
|
|
79
84
|
*
|
|
80
85
|
* @dev Compatibility:
|
|
81
86
|
* The wire format the custodian's signer implements is the EIP-712 domain
|
|
82
87
|
* (`NativeShieldedTokenIssuer`, version `1`, salt), the `Mint` /
|
|
83
|
-
* `MintToSelf` / `Burn` / `BurnFromSelf` type strings, the
|
|
84
|
-
*
|
|
85
|
-
* `
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
+
* `MintToSelf` / `Burn` / `BurnFromSelf` type strings, the
|
|
89
|
+
* `Secp256k1EcdsaMultisig:signer` commitment domain (owned by
|
|
90
|
+
* `Secp256k1EcdsaMultisig`), the `cm` preimage struct, and the
|
|
91
|
+
* `Vector<t>` / `Vector<n>` shapes the implementing contract fixes. Changing
|
|
92
|
+
* any of them breaks every existing signer setup. The test suite pins them
|
|
93
|
+
* through `EcdsaTestUtils.ts`.
|
|
88
94
|
*
|
|
89
95
|
* @notice Privacy:
|
|
90
96
|
* - Public, per tx:
|
|
91
97
|
* - Entry point: which of the four operations ran.
|
|
92
|
-
* - Approvers: the
|
|
93
|
-
* `Signer_assertSigner`), so WHICH
|
|
98
|
+
* - Approvers: the `t` signer commitments (`disclose(commitment)` in
|
|
99
|
+
* `Signer_assertSigner`), so WHICH signers approved.
|
|
94
100
|
* - Mint: `amount`, as the `shieldedMints` effect under the token domain,
|
|
95
101
|
* and the coin commitment as a spend claim. Recipient and nonce are not
|
|
96
102
|
* published. The nonce is `evolveNonce` of the public
|
|
@@ -149,12 +155,11 @@ pragma language_version >= 0.26.0;
|
|
|
149
155
|
* still refunds the bound `refundTo`.
|
|
150
156
|
* - Low-s: verification goes through `Ecdsa_secp256k1EcdsaVerifyLowS`, so a
|
|
151
157
|
* high-s encoding is an invalid signature.
|
|
152
|
-
* - Distinct signers:
|
|
153
|
-
*
|
|
154
|
-
* required. The threshold `2` is the only value `EcdsaSignerManager` accepts.
|
|
158
|
+
* - Distinct signers: every gated circuit verifies `t` distinct registered
|
|
159
|
+
* signers, so no set of fewer than `t` keys creates or destroys tokens.
|
|
155
160
|
* - Immutable signer set: no signer reconfiguration circuit is exported, so
|
|
156
|
-
* the
|
|
157
|
-
*
|
|
161
|
+
* the commitments and the threshold are fixed. Losing more than `n - t`
|
|
162
|
+
* keys freezes the contract.
|
|
158
163
|
* - Griefing: the derived-nonce mints are the only mint paths and both are
|
|
159
164
|
* threshold-gated, so `NativeShieldedTokenDerivedNonce`'s
|
|
160
165
|
* collision-griefing precondition (a caller-nonce mint at another trust
|
|
@@ -165,8 +170,8 @@ pragma language_version >= 0.26.0;
|
|
|
165
170
|
* @notice Concurrency:
|
|
166
171
|
* - Replay counter: `mint`, `mintToSelf`, `burn` and `burnFromSelf` read
|
|
167
172
|
* `_counter` into the digest. The read is pinned, so any two of them in one block
|
|
168
|
-
* conflict: at most one operation lands per block, and the losing
|
|
169
|
-
*
|
|
173
|
+
* conflict: at most one operation lands per block, and the losing signers
|
|
174
|
+
* re-sign at the next nonce.
|
|
170
175
|
* - Derived-nonce counter: both mints also pin it (`evolveNonce` consumes
|
|
171
176
|
* it); the `_counter` conflict already covers those pairs.
|
|
172
177
|
* - `getNonce`: submitted as a tx it pins `_counter` and conflicts with any
|
|
@@ -178,16 +183,19 @@ pragma language_version >= 0.26.0;
|
|
|
178
183
|
* Mint and burn only. No send, transfer or execute circuit exists, so
|
|
179
184
|
* contract-held coins (from `mintToSelf` or `burnFromSelf` change) leave only
|
|
180
185
|
* through `burnFromSelf`, supplied by the operator as
|
|
181
|
-
* `QualifiedShieldedCoinInfo`.
|
|
186
|
+
* `QualifiedShieldedCoinInfo`. Moving such a coin anywhere else needs a
|
|
187
|
+
* custody module composed by the consumer that records the coin without
|
|
188
|
+
* claiming it a second time; `ShieldedTreasury._deposit` is not that module
|
|
189
|
+
* today (compact-contracts#1112). Coins minted to users are ordinary
|
|
182
190
|
* Zswap coins the contract neither tracks nor restricts; a holder redeems by
|
|
183
191
|
* paying the coin into a `burn` tx. No supply accounting.
|
|
184
192
|
*
|
|
185
193
|
* @notice Client-side duties:
|
|
186
194
|
* - Before deploy: pick a random `instanceSalt`, derive each `cm` with
|
|
187
|
-
* `_calculateSignerId(pk, salt)`, pass
|
|
195
|
+
* `_calculateSignerId(pk, salt)`, pass them as `signerCommitments`.
|
|
188
196
|
* - Per operation: read `getNonce()`, rebuild the digest as
|
|
189
|
-
* `EcdsaTestUtils.ts` does, collect
|
|
190
|
-
* keys and signatures in matching `Vector<
|
|
197
|
+
* `EcdsaTestUtils.ts` does, collect `t` low-s signatures off-chain, submit
|
|
198
|
+
* keys and signatures in matching `Vector<t>` positions.
|
|
191
199
|
* - `mint`: hand the returned `ShieldedCoinInfo` to the recipient out of
|
|
192
200
|
* band; contract-initiated mints create no ciphertext, so a wallet cannot
|
|
193
201
|
* find the coin by scanning.
|
|
@@ -212,7 +220,7 @@ pragma language_version >= 0.26.0;
|
|
|
212
220
|
*
|
|
213
221
|
* @notice Scalability:
|
|
214
222
|
* - Throughput: one operation per block (see Concurrency).
|
|
215
|
-
* - State: constant-size, two counters and
|
|
223
|
+
* - State: constant-size, two counters and an `n`-entry signer set. Nothing
|
|
216
224
|
* grows per operation.
|
|
217
225
|
* - Amounts: mints cap at `Uint<64>` by `mintShieldedToken`. Burns take
|
|
218
226
|
* `Uint<128>`, the coin value range.
|
|
@@ -225,10 +233,10 @@ pragma language_version >= 0.26.0;
|
|
|
225
233
|
*
|
|
226
234
|
* @notice Requires ZKIR v3: `keccak256` is unavailable on the v2 backend.
|
|
227
235
|
*/
|
|
228
|
-
module NativeShieldedTokenIssuer {
|
|
236
|
+
module NativeShieldedTokenIssuer<#t> {
|
|
229
237
|
import CompactStandardLibrary;
|
|
230
238
|
|
|
231
|
-
import "../
|
|
239
|
+
import "../Secp256k1EcdsaMultisig"<t> prefix Secp256k1EcdsaMultisig_;
|
|
232
240
|
import "../../crypto/Eip712" prefix Eip712_;
|
|
233
241
|
import "../../utils/EvmAbi" prefix EvmAbi_;
|
|
234
242
|
import "../../token/NativeShieldedToken" prefix NST_;
|
|
@@ -238,7 +246,7 @@ module NativeShieldedTokenIssuer {
|
|
|
238
246
|
// implementing contract can surface every ledger field under its own key.
|
|
239
247
|
// The circuits stay behind the prefixes above. The derived-nonce counter is
|
|
240
248
|
// aliased because this module's replay counter already owns `_counter`.
|
|
241
|
-
import { _instanceSalt, _signers, _signerCount, _threshold } from "../
|
|
249
|
+
import { _instanceSalt, _signers, _signerCount, _threshold } from "../Secp256k1EcdsaMultisig"<t>;
|
|
242
250
|
import { _domain, _name, _symbol, _decimals, _isInitialized } from "../../token/NativeShieldedToken";
|
|
243
251
|
import { _counter as _derivedNonceCounter } from "../../token/extensions/NativeShieldedTokenDerivedNonce";
|
|
244
252
|
export { _instanceSalt, _signers, _signerCount, _threshold };
|
|
@@ -262,9 +270,8 @@ module NativeShieldedTokenIssuer {
|
|
|
262
270
|
export sealed ledger _domainSeparator: Bytes<32>;
|
|
263
271
|
|
|
264
272
|
/**
|
|
265
|
-
* @description Registers the signer set
|
|
266
|
-
* and domain, and fixes the EIP-712 domain separator.
|
|
267
|
-
* fixed at 2.
|
|
273
|
+
* @description Registers the signer set at threshold `t`, initializes the
|
|
274
|
+
* token metadata and domain, and fixes the EIP-712 domain separator.
|
|
268
275
|
*
|
|
269
276
|
* @notice Call from the implementing contract's constructor only. It writes
|
|
270
277
|
* the token module's `sealed` domain and `_domainSeparator`, so
|
|
@@ -281,24 +288,25 @@ module NativeShieldedTokenIssuer {
|
|
|
281
288
|
*
|
|
282
289
|
* - `instanceSalt` should be cryptographically random.
|
|
283
290
|
* - `signerCommitments` must not contain duplicates.
|
|
291
|
+
* - `n` must be at least `t`.
|
|
284
292
|
*
|
|
285
293
|
* @param {Bytes<32>} instanceSalt - Per-deployment salt for commitment derivation.
|
|
286
294
|
* @param {Bytes<32>} tokenDomain - Domain separator for this contract's token color.
|
|
287
295
|
* @param {Opaque<"string">} name_ - The token name.
|
|
288
296
|
* @param {Opaque<"string">} symbol_ - The token symbol.
|
|
289
297
|
* @param {Uint<8>} decimals_ - The token decimals.
|
|
290
|
-
* @param {Vector<
|
|
298
|
+
* @param {Vector<n, Bytes<32>>} signerCommitments - Hashed signer identities.
|
|
291
299
|
* @returns {[]} Empty tuple.
|
|
292
300
|
*/
|
|
293
|
-
export circuit initialize(
|
|
301
|
+
export circuit initialize<#n>(
|
|
294
302
|
instanceSalt: Bytes<32>,
|
|
295
303
|
tokenDomain: Bytes<32>,
|
|
296
304
|
name_: Opaque<"string">,
|
|
297
305
|
symbol_: Opaque<"string">,
|
|
298
306
|
decimals_: Uint<8>,
|
|
299
|
-
signerCommitments: Vector<
|
|
307
|
+
signerCommitments: Vector<n, Bytes<32>>
|
|
300
308
|
): [] {
|
|
301
|
-
|
|
309
|
+
Secp256k1EcdsaMultisig_initialize<n>(instanceSalt, signerCommitments);
|
|
302
310
|
NST_initialize(tokenDomain, name_, symbol_, decimals_);
|
|
303
311
|
|
|
304
312
|
const hashedName = keccak256<Bytes<25>>(pad(25, "NativeShieldedTokenIssuer"));
|
|
@@ -394,7 +402,7 @@ module NativeShieldedTokenIssuer {
|
|
|
394
402
|
|
|
395
403
|
/**
|
|
396
404
|
* @description Computes a signer commitment from a secp256k1 public key,
|
|
397
|
-
* as `persistentHash(pkX, pkY, salt, "
|
|
405
|
+
* as `persistentHash(pkX, pkY, salt, "Secp256k1EcdsaMultisig:signer")`.
|
|
398
406
|
*
|
|
399
407
|
* Pure, so the deployer can derive constructor commitments off-chain.
|
|
400
408
|
*
|
|
@@ -410,7 +418,7 @@ module NativeShieldedTokenIssuer {
|
|
|
410
418
|
pk: Secp256k1Point,
|
|
411
419
|
salt: Bytes<32>
|
|
412
420
|
): Bytes<32> {
|
|
413
|
-
return
|
|
421
|
+
return Secp256k1EcdsaMultisig_calculateSignerId(pk, salt);
|
|
414
422
|
}
|
|
415
423
|
|
|
416
424
|
/**
|
|
@@ -423,27 +431,26 @@ module NativeShieldedTokenIssuer {
|
|
|
423
431
|
* @notice The returned coin info is the only copy available to the
|
|
424
432
|
* recipient; deliver it out of band.
|
|
425
433
|
*
|
|
426
|
-
* @constraints k=17, rows=
|
|
434
|
+
* @constraints k=17, rows=89807 (zkir-v3)
|
|
427
435
|
*
|
|
428
436
|
* Requirements:
|
|
429
437
|
*
|
|
430
|
-
* -
|
|
431
|
-
* -
|
|
432
|
-
* -
|
|
433
|
-
* - Threshold must be met.
|
|
438
|
+
* - No two entries may be the same signer.
|
|
439
|
+
* - Every public key must hash to a registered signer commitment.
|
|
440
|
+
* - Every signature must be valid over the mint message hash.
|
|
434
441
|
* - `recipient` is not zero.
|
|
435
442
|
*
|
|
436
443
|
* @param {Uint<64>} amount - The token amount to mint.
|
|
437
444
|
* @param {ZswapCoinPublicKey} recipient - The coin public key to receive the minted tokens.
|
|
438
|
-
* @param {Vector<
|
|
439
|
-
* @param {Vector<
|
|
445
|
+
* @param {Vector<t, Secp256k1Point>} pubkeys - Public keys of approving signers.
|
|
446
|
+
* @param {Vector<t, Secp256k1EcdsaSignature>} signatures - ECDSA signatures over the mint hash.
|
|
440
447
|
* @returns {ShieldedCoinInfo} The minted coin (nonce, color, value).
|
|
441
448
|
*/
|
|
442
449
|
export circuit mint(
|
|
443
450
|
amount: Uint<64>,
|
|
444
451
|
recipient: ZswapCoinPublicKey,
|
|
445
|
-
pubkeys: Vector<
|
|
446
|
-
signatures: Vector<
|
|
452
|
+
pubkeys: Vector<t, Secp256k1Point>,
|
|
453
|
+
signatures: Vector<t, Secp256k1EcdsaSignature>
|
|
447
454
|
): ShieldedCoinInfo {
|
|
448
455
|
const opNonce = _counter;
|
|
449
456
|
_counter.increment(1);
|
|
@@ -459,7 +466,7 @@ module NativeShieldedTokenIssuer {
|
|
|
459
466
|
EvmAbi_uint64Word(amount)
|
|
460
467
|
]));
|
|
461
468
|
|
|
462
|
-
|
|
469
|
+
Secp256k1EcdsaMultisig_assertApprovals(msgHash, pubkeys, signatures);
|
|
463
470
|
|
|
464
471
|
return NST__mint(recipient, amount, NSTDerivedNonce__deriveNonce());
|
|
465
472
|
}
|
|
@@ -472,24 +479,23 @@ module NativeShieldedTokenIssuer {
|
|
|
472
479
|
* @notice The returned coin info is the contract's only record of the
|
|
473
480
|
* holding; persist it for `burnFromSelf`.
|
|
474
481
|
*
|
|
475
|
-
* @constraints k=17, rows=
|
|
482
|
+
* @constraints k=17, rows=85586 (zkir-v3)
|
|
476
483
|
*
|
|
477
484
|
* Requirements:
|
|
478
485
|
*
|
|
479
|
-
* -
|
|
480
|
-
* -
|
|
481
|
-
* -
|
|
482
|
-
* - Threshold must be met.
|
|
486
|
+
* - No two entries may be the same signer.
|
|
487
|
+
* - Every public key must hash to a registered signer commitment.
|
|
488
|
+
* - Every signature must be valid over the mint-to-self message hash.
|
|
483
489
|
*
|
|
484
490
|
* @param {Uint<64>} amount - The token amount to mint.
|
|
485
|
-
* @param {Vector<
|
|
486
|
-
* @param {Vector<
|
|
491
|
+
* @param {Vector<t, Secp256k1Point>} pubkeys - Public keys of approving signers.
|
|
492
|
+
* @param {Vector<t, Secp256k1EcdsaSignature>} signatures - ECDSA signatures over the mint-to-self hash.
|
|
487
493
|
* @returns {ShieldedCoinInfo} The minted coin (nonce, color, value).
|
|
488
494
|
*/
|
|
489
495
|
export circuit mintToSelf(
|
|
490
496
|
amount: Uint<64>,
|
|
491
|
-
pubkeys: Vector<
|
|
492
|
-
signatures: Vector<
|
|
497
|
+
pubkeys: Vector<t, Secp256k1Point>,
|
|
498
|
+
signatures: Vector<t, Secp256k1EcdsaSignature>
|
|
493
499
|
): ShieldedCoinInfo {
|
|
494
500
|
const opNonce = _counter;
|
|
495
501
|
_counter.increment(1);
|
|
@@ -504,7 +510,7 @@ module NativeShieldedTokenIssuer {
|
|
|
504
510
|
EvmAbi_uint64Word(amount)
|
|
505
511
|
]));
|
|
506
512
|
|
|
507
|
-
|
|
513
|
+
Secp256k1EcdsaMultisig_assertApprovals(msgHash, pubkeys, signatures);
|
|
508
514
|
|
|
509
515
|
return NST__mintToSelf(amount, NSTDerivedNonce__deriveNonce());
|
|
510
516
|
}
|
|
@@ -517,14 +523,13 @@ module NativeShieldedTokenIssuer {
|
|
|
517
523
|
* @notice The returned refund coin info is the only copy available to
|
|
518
524
|
* `refundTo`; deliver it out of band.
|
|
519
525
|
*
|
|
520
|
-
* @constraints k=17, rows=
|
|
526
|
+
* @constraints k=17, rows=119818 (zkir-v3)
|
|
521
527
|
*
|
|
522
528
|
* Requirements:
|
|
523
529
|
*
|
|
524
|
-
* -
|
|
525
|
-
* -
|
|
526
|
-
* -
|
|
527
|
-
* - Threshold must be met.
|
|
530
|
+
* - No two entries may be the same signer.
|
|
531
|
+
* - Every public key must hash to a registered signer commitment.
|
|
532
|
+
* - Every signature must be valid over the burn message hash.
|
|
528
533
|
* - `coin.color` is this contract's token color.
|
|
529
534
|
* - `amount` is less than or equal to `coin.value`.
|
|
530
535
|
* - `refundTo` is not zero.
|
|
@@ -532,8 +537,8 @@ module NativeShieldedTokenIssuer {
|
|
|
532
537
|
* @param {ShieldedCoinInfo} coin - The holder's coin to burn from.
|
|
533
538
|
* @param {Uint<128>} amount - The token amount to burn.
|
|
534
539
|
* @param {ZswapCoinPublicKey} refundTo - Receives `coin.value - amount`.
|
|
535
|
-
* @param {Vector<
|
|
536
|
-
* @param {Vector<
|
|
540
|
+
* @param {Vector<t, Secp256k1Point>} pubkeys - Public keys of approving signers.
|
|
541
|
+
* @param {Vector<t, Secp256k1EcdsaSignature>} signatures - ECDSA signatures over the burn hash.
|
|
537
542
|
* @returns {Maybe<ShieldedCoinInfo>} The refund coin created for `refundTo`,
|
|
538
543
|
* or `none` if the coin was burned in full.
|
|
539
544
|
*/
|
|
@@ -541,8 +546,8 @@ module NativeShieldedTokenIssuer {
|
|
|
541
546
|
coin: ShieldedCoinInfo,
|
|
542
547
|
amount: Uint<128>,
|
|
543
548
|
refundTo: ZswapCoinPublicKey,
|
|
544
|
-
pubkeys: Vector<
|
|
545
|
-
signatures: Vector<
|
|
549
|
+
pubkeys: Vector<t, Secp256k1Point>,
|
|
550
|
+
signatures: Vector<t, Secp256k1EcdsaSignature>
|
|
546
551
|
): Maybe<ShieldedCoinInfo> {
|
|
547
552
|
const opNonce = _counter;
|
|
548
553
|
_counter.increment(1);
|
|
@@ -558,7 +563,7 @@ module NativeShieldedTokenIssuer {
|
|
|
558
563
|
EvmAbi_uint128Word(amount)
|
|
559
564
|
]));
|
|
560
565
|
|
|
561
|
-
|
|
566
|
+
Secp256k1EcdsaMultisig_assertApprovals(msgHash, pubkeys, signatures);
|
|
562
567
|
|
|
563
568
|
return NST__burn(coin, amount, refundTo);
|
|
564
569
|
}
|
|
@@ -575,30 +580,29 @@ module NativeShieldedTokenIssuer {
|
|
|
575
580
|
* The digest binds `coin.nonce` and `coin.value`, so approvals authorize one
|
|
576
581
|
* specific holding rather than an amount.
|
|
577
582
|
*
|
|
578
|
-
* @constraints k=17, rows=
|
|
583
|
+
* @constraints k=17, rows=104973 (zkir-v3)
|
|
579
584
|
*
|
|
580
585
|
* Requirements:
|
|
581
586
|
*
|
|
582
|
-
* -
|
|
583
|
-
* -
|
|
584
|
-
* -
|
|
585
|
-
* - Threshold must be met.
|
|
587
|
+
* - No two entries may be the same signer.
|
|
588
|
+
* - Every public key must hash to a registered signer commitment.
|
|
589
|
+
* - Every signature must be valid over the burn-from-self message hash.
|
|
586
590
|
* - `coin.color` is this contract's token color.
|
|
587
591
|
* - `amount` is less than or equal to `coin.value`.
|
|
588
592
|
* - `coin.nonce` and `coin.value` match the approved coin.
|
|
589
593
|
*
|
|
590
594
|
* @param {QualifiedShieldedCoinInfo} coin - The contract-held coin to burn from.
|
|
591
595
|
* @param {Uint<128>} amount - The token amount to burn.
|
|
592
|
-
* @param {Vector<
|
|
593
|
-
* @param {Vector<
|
|
596
|
+
* @param {Vector<t, Secp256k1Point>} pubkeys - Public keys of approving signers.
|
|
597
|
+
* @param {Vector<t, Secp256k1EcdsaSignature>} signatures - ECDSA signatures over the burn-from-self hash.
|
|
594
598
|
* @returns {Maybe<ShieldedCoinInfo>} The change coin retained by the
|
|
595
599
|
* contract, or `none` if the coin was burned in full.
|
|
596
600
|
*/
|
|
597
601
|
export circuit burnFromSelf(
|
|
598
602
|
coin: QualifiedShieldedCoinInfo,
|
|
599
603
|
amount: Uint<128>,
|
|
600
|
-
pubkeys: Vector<
|
|
601
|
-
signatures: Vector<
|
|
604
|
+
pubkeys: Vector<t, Secp256k1Point>,
|
|
605
|
+
signatures: Vector<t, Secp256k1EcdsaSignature>
|
|
602
606
|
): Maybe<ShieldedCoinInfo> {
|
|
603
607
|
const opNonce = _counter;
|
|
604
608
|
_counter.increment(1);
|
|
@@ -615,7 +619,7 @@ module NativeShieldedTokenIssuer {
|
|
|
615
619
|
EvmAbi_uint128Word(coin.value)
|
|
616
620
|
]));
|
|
617
621
|
|
|
618
|
-
|
|
622
|
+
Secp256k1EcdsaMultisig_assertApprovals(msgHash, pubkeys, signatures);
|
|
619
623
|
|
|
620
624
|
return NST__burnFromSelf(coin, amount);
|
|
621
625
|
}
|
|
@@ -684,7 +688,7 @@ module NativeShieldedTokenIssuer {
|
|
|
684
688
|
* @returns {Uint<8>} The signer count.
|
|
685
689
|
*/
|
|
686
690
|
export circuit getSignerCount(): Uint<8> {
|
|
687
|
-
return
|
|
691
|
+
return Secp256k1EcdsaMultisig_getSignerCount();
|
|
688
692
|
}
|
|
689
693
|
|
|
690
694
|
/**
|
|
@@ -695,7 +699,7 @@ module NativeShieldedTokenIssuer {
|
|
|
695
699
|
* @returns {Uint<8>} The threshold.
|
|
696
700
|
*/
|
|
697
701
|
export circuit getThreshold(): Uint<8> {
|
|
698
|
-
return
|
|
702
|
+
return Secp256k1EcdsaMultisig_getThreshold();
|
|
699
703
|
}
|
|
700
704
|
|
|
701
705
|
/**
|
|
@@ -707,6 +711,6 @@ module NativeShieldedTokenIssuer {
|
|
|
707
711
|
* @returns {Boolean} True if registered.
|
|
708
712
|
*/
|
|
709
713
|
export circuit isSigner(commitment: Bytes<32>): Boolean {
|
|
710
|
-
return
|
|
714
|
+
return Secp256k1EcdsaMultisig_isSigner(commitment);
|
|
711
715
|
}
|
|
712
716
|
}
|