@lfdecentralizedtrust/zeto-contracts 0.2.2 → 0.5.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 +70 -162
- package/contracts/factory.sol +30 -34
- package/contracts/factory_upgradeable.sol +11 -7
- package/contracts/lib/common/util.sol +40 -0
- package/contracts/lib/interfaces/ILockableCapability.sol +318 -0
- package/contracts/lib/interfaces/{izeto.sol → IZeto.sol} +13 -1
- package/contracts/lib/interfaces/{izeto_initializable.sol → IZetoInitializable.sol} +14 -12
- package/contracts/lib/interfaces/{izeto_kyc.sol → IZetoKyc.sol} +3 -3
- package/contracts/lib/interfaces/IZetoLockableCapability.sol +237 -0
- package/contracts/lib/interfaces/IZetoStorage.sol +106 -0
- package/contracts/lib/interfaces/{izeto_lockable.sol → IZetoVerifier.sol} +8 -21
- package/contracts/lib/registry.sol +74 -26
- package/contracts/lib/storage/base.sol +210 -0
- package/contracts/lib/storage/nullifier.sol +166 -0
- package/contracts/lib/zeto_common.sol +277 -28
- package/contracts/lib/zeto_fungible.sol +451 -33
- package/contracts/lib/zeto_fungible_base.sol +69 -0
- package/contracts/lib/zeto_fungible_burn.sol +83 -53
- package/contracts/lib/zeto_fungible_burn_nullifier.sol +115 -72
- package/contracts/lib/zeto_fungible_nullifier.sol +167 -0
- package/contracts/lib/zeto_lockable.sol +613 -0
- package/contracts/lib/zeto_non_fungible.sol +236 -0
- package/contracts/lib/zeto_non_fungible_base.sol +61 -0
- package/contracts/lib/zeto_non_fungible_nullifier.sol +61 -0
- package/contracts/test/escrow1.sol +90 -34
- package/contracts/test/escrow2.sol +64 -29
- package/contracts/test/qurrency.sol +10 -2
- package/contracts/test/smt.sol +6 -1
- package/contracts/test/tendecimals.sol +14 -12
- package/contracts/verifiers/impl/anon.sol +189 -0
- package/contracts/verifiers/impl/anon_batch.sol +301 -0
- package/contracts/verifiers/impl/anon_enc.sol +266 -0
- package/contracts/verifiers/impl/anon_enc_batch.sol +602 -0
- package/contracts/verifiers/impl/anon_enc_nullifier.sol +287 -0
- package/contracts/verifiers/impl/anon_enc_nullifier_batch.sol +679 -0
- package/contracts/verifiers/impl/anon_enc_nullifier_kyc.sol +294 -0
- package/contracts/verifiers/impl/anon_enc_nullifier_kyc_batch.sol +686 -0
- package/contracts/verifiers/impl/anon_enc_nullifier_non_repudiation.sol +413 -0
- package/contracts/verifiers/impl/anon_enc_nullifier_non_repudiation_batch.sol +1141 -0
- package/contracts/verifiers/impl/anon_nullifier_kyc_transfer.sol +217 -0
- package/contracts/verifiers/impl/anon_nullifier_kyc_transferLocked.sol +196 -0
- package/contracts/verifiers/impl/anon_nullifier_kyc_transferLocked_batch.sol +308 -0
- package/contracts/verifiers/impl/anon_nullifier_kyc_transfer_batch.sol +385 -0
- package/contracts/verifiers/impl/anon_nullifier_qurrency_transfer.sol +497 -0
- package/contracts/verifiers/impl/anon_nullifier_qurrency_transfer_batch.sol +1001 -0
- package/contracts/verifiers/{verifier_anon_nullifier_transferLocked.sol → impl/anon_nullifier_transfer.sol} +12 -19
- package/contracts/verifiers/{verifier_anon_nullifier_transferLocked_batch.sol → impl/anon_nullifier_transfer_batch.sol} +44 -51
- package/contracts/verifiers/impl/burn.sol +182 -0
- package/contracts/verifiers/impl/burn_batch.sol +238 -0
- package/contracts/verifiers/impl/burn_nullifier.sol +203 -0
- package/contracts/verifiers/impl/burn_nullifier_batch.sol +315 -0
- package/contracts/verifiers/impl/deposit.sol +182 -0
- package/contracts/verifiers/impl/deposit_kyc.sol +189 -0
- package/contracts/verifiers/impl/nf_anon.sol +175 -0
- package/contracts/verifiers/{verifier_nf_anon_nullifier_transferLocked.sol → impl/nf_anon_nullifier_transfer.sol} +6 -13
- package/contracts/verifiers/impl/withdraw.sol +189 -0
- package/contracts/verifiers/impl/withdraw_batch.sol +245 -0
- package/contracts/verifiers/impl/withdraw_nullifier.sol +210 -0
- package/contracts/verifiers/impl/withdraw_nullifier_batch.sol +322 -0
- package/contracts/verifiers/verifier_anon.sol +31 -186
- package/contracts/verifiers/verifier_anon_batch.sol +31 -298
- package/contracts/verifiers/verifier_anon_enc.sol +31 -263
- package/contracts/verifiers/verifier_anon_enc_batch.sol +31 -599
- package/contracts/verifiers/verifier_anon_enc_nullifier.sol +31 -284
- package/contracts/verifiers/verifier_anon_enc_nullifier_batch.sol +33 -676
- package/contracts/verifiers/verifier_anon_enc_nullifier_kyc.sol +31 -291
- package/contracts/verifiers/verifier_anon_enc_nullifier_kyc_batch.sol +33 -683
- package/contracts/verifiers/verifier_anon_enc_nullifier_non_repudiation.sol +33 -410
- package/contracts/verifiers/verifier_anon_enc_nullifier_non_repudiation_batch.sol +33 -1138
- package/contracts/verifiers/verifier_anon_nullifier_kyc_transfer.sol +33 -214
- package/contracts/verifiers/verifier_anon_nullifier_kyc_transferLocked.sol +33 -221
- package/contracts/verifiers/verifier_anon_nullifier_kyc_transferLocked_batch.sol +33 -389
- package/contracts/verifiers/verifier_anon_nullifier_kyc_transfer_batch.sol +33 -382
- package/contracts/verifiers/verifier_anon_nullifier_qurrency_transfer.sol +33 -221
- package/contracts/verifiers/verifier_anon_nullifier_qurrency_transfer_batch.sol +33 -389
- package/contracts/verifiers/verifier_anon_nullifier_transfer.sol +33 -207
- package/contracts/verifiers/verifier_anon_nullifier_transfer_batch.sol +33 -375
- package/contracts/verifiers/verifier_burn.sol +31 -179
- package/contracts/verifiers/verifier_burn_batch.sol +31 -235
- package/contracts/verifiers/verifier_burn_nullifier.sol +31 -200
- package/contracts/verifiers/verifier_burn_nullifier_batch.sol +31 -312
- package/contracts/verifiers/verifier_deposit.sol +31 -179
- package/contracts/verifiers/verifier_deposit_kyc.sol +34 -0
- package/contracts/verifiers/verifier_nf_anon.sol +31 -172
- package/contracts/verifiers/verifier_nf_anon_nullifier_transfer.sol +33 -179
- package/contracts/verifiers/verifier_withdraw.sol +31 -186
- package/contracts/verifiers/verifier_withdraw_batch.sol +31 -242
- package/contracts/verifiers/verifier_withdraw_nullifier.sol +31 -207
- package/contracts/verifiers/verifier_withdraw_nullifier_batch.sol +33 -319
- package/contracts/zeto_anon.sol +77 -231
- package/contracts/zeto_anon_burnable.sol +56 -12
- package/contracts/zeto_anon_enc.sol +93 -190
- package/contracts/zeto_anon_enc_nullifier.sol +249 -195
- package/contracts/zeto_anon_enc_nullifier_kyc.sol +51 -232
- package/contracts/zeto_anon_enc_nullifier_non_repudiation.sol +231 -238
- package/contracts/zeto_anon_nullifier.sol +164 -298
- package/contracts/zeto_anon_nullifier_burnable.sol +68 -18
- package/contracts/zeto_anon_nullifier_kyc.sol +40 -345
- package/contracts/zeto_anon_nullifier_qurrency.sol +217 -361
- package/contracts/zeto_nf_anon.sol +55 -130
- package/contracts/zeto_nf_anon_nullifier.sol +90 -152
- package/hardhat.config.ts +9 -3
- package/ignition/modules/lib/deps.ts +8 -0
- package/ignition/modules/zeto_anon_burnable.ts +8 -7
- package/ignition/modules/zeto_anon_enc_nullifier.ts +31 -0
- package/ignition/modules/zeto_anon_enc_nullifier_kyc.ts +2 -2
- package/ignition/modules/zeto_anon_nullifier.ts +28 -4
- package/ignition/modules/zeto_anon_nullifier_burnable.ts +50 -16
- package/ignition/modules/zeto_anon_nullifier_kyc.ts +27 -12
- package/ignition/modules/zeto_nf_anon_nullifier.ts +14 -10
- package/package.json +4 -2
- package/scripts/deploy_cloneable.ts +19 -10
- package/scripts/deploy_upgradeable.ts +9 -5
- package/scripts/tokens/Zeto_Anon.ts +3 -3
- package/scripts/tokens/Zeto_AnonBurnable.ts +1 -1
- package/scripts/tokens/Zeto_AnonEnc.ts +12 -3
- package/scripts/tokens/Zeto_AnonEncNullifier.ts +5 -3
- package/scripts/tokens/Zeto_AnonEncNullifierKyc.ts +1 -1
- package/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts +1 -1
- package/scripts/tokens/Zeto_AnonNullifier.ts +1 -1
- package/scripts/tokens/Zeto_AnonNullifierBurnable.ts +1 -1
- package/scripts/tokens/Zeto_AnonNullifierKyc.ts +1 -1
- package/scripts/tokens/Zeto_AnonNullifierQurrency.ts +1 -1
- package/scripts/tokens/Zeto_NfAnon.ts +2 -2
- package/scripts/tokens/Zeto_NfAnonNullifier.ts +1 -1
- package/test/factory.ts +46 -73
- package/test/lib/anon_nullifier_helpers.ts +89 -0
- package/test/lib/anon_zeto_helpers.ts +76 -0
- package/test/lib/deploy.ts +3 -2
- package/test/lib/utils.ts +74 -35
- package/test/test/escrow1.ts +185 -58
- package/test/test/escrow2.ts +200 -107
- package/test/test/qurrency.ts +13 -33
- package/test/usdc-shielding.ts +39 -26
- package/test/utils.ts +144 -21
- package/test/zeto_anon.ts +956 -465
- package/test/zeto_anon_enc.ts +881 -142
- package/test/zeto_anon_enc_nullifier.ts +847 -38
- package/test/zeto_anon_enc_nullifier_kyc.ts +120 -181
- package/test/zeto_anon_enc_nullifier_non_repudiation.ts +77 -46
- package/test/zeto_anon_nullifier.ts +1212 -953
- package/test/zeto_anon_nullifier_kyc.ts +674 -655
- package/test/zeto_anon_nullifier_qurrency.ts +452 -306
- package/test/zeto_nf_anon.ts +737 -137
- package/test/zeto_nf_anon_nullifier.ts +876 -246
- package/contracts/lib/zeto_base.sol +0 -293
- package/contracts/lib/zeto_fungible_withdraw.sol +0 -132
- package/contracts/lib/zeto_fungible_withdraw_nullifier.sol +0 -144
- package/contracts/lib/zeto_nullifier.sol +0 -340
- package/contracts/zkDvP.sol_ +0 -273
- package/test/zkDvP.ts_ +0 -455
- /package/contracts/lib/{common.sol → common/common.sol} +0 -0
|
@@ -15,7 +15,12 @@
|
|
|
15
15
|
// limitations under the License.
|
|
16
16
|
|
|
17
17
|
import { ethers, network } from "hardhat";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
ContractTransactionReceipt,
|
|
20
|
+
Signer,
|
|
21
|
+
BigNumberish,
|
|
22
|
+
AbiCoder,
|
|
23
|
+
} from "ethers";
|
|
19
24
|
import { expect } from "chai";
|
|
20
25
|
import {
|
|
21
26
|
loadCircuit,
|
|
@@ -46,8 +51,10 @@ import {
|
|
|
46
51
|
} from "./lib/utils";
|
|
47
52
|
import {
|
|
48
53
|
loadProvingKeys,
|
|
49
|
-
|
|
54
|
+
prepareDepositKycProof,
|
|
50
55
|
prepareNullifierWithdrawProof,
|
|
56
|
+
encodeToBytesForDeposit,
|
|
57
|
+
encodeToBytesForWithdraw,
|
|
51
58
|
} from "./utils";
|
|
52
59
|
import { deployZeto } from "./lib/deploy";
|
|
53
60
|
const poseidonHash = Poseidon.poseidon4;
|
|
@@ -91,11 +98,17 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
91
98
|
|
|
92
99
|
({ deployer, zeto, erc20 } = await deployZeto("Zeto_AnonEncNullifierKyc"));
|
|
93
100
|
|
|
94
|
-
const tx2 = await zeto
|
|
101
|
+
const tx2 = await zeto
|
|
102
|
+
.connect(deployer)
|
|
103
|
+
.register(Alice.babyJubPublicKey, "0x");
|
|
95
104
|
const result1 = await tx2.wait();
|
|
96
|
-
const tx3 = await zeto
|
|
105
|
+
const tx3 = await zeto
|
|
106
|
+
.connect(deployer)
|
|
107
|
+
.register(Bob.babyJubPublicKey, "0x");
|
|
97
108
|
const result2 = await tx3.wait();
|
|
98
|
-
const tx4 = await zeto
|
|
109
|
+
const tx4 = await zeto
|
|
110
|
+
.connect(deployer)
|
|
111
|
+
.register(Charlie.babyJubPublicKey, "0x");
|
|
99
112
|
const result3 = await tx4.wait();
|
|
100
113
|
|
|
101
114
|
const storage1 = new InMemoryDB(str2Bytes("alice"));
|
|
@@ -225,12 +238,13 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
225
238
|
|
|
226
239
|
const signerAddress = await Alice.signer.getAddress();
|
|
227
240
|
const events = parseUTXOEvents(zeto, result.txResult!);
|
|
228
|
-
|
|
229
|
-
expect(
|
|
241
|
+
const event = events[0];
|
|
242
|
+
expect(event.submitter).to.equal(signerAddress);
|
|
243
|
+
expect(event.inputs).to.deep.equal(nullifiers.map((n) => n.hash));
|
|
230
244
|
|
|
231
|
-
const incomingUTXOs: any =
|
|
245
|
+
const incomingUTXOs: any = event.outputs;
|
|
232
246
|
|
|
233
|
-
const ecdhPublicKey =
|
|
247
|
+
const ecdhPublicKey = event.ecdhPublicKey;
|
|
234
248
|
// check the non-empty output hashes are correct
|
|
235
249
|
for (let i = 0; i < outputUtxos.length; i++) {
|
|
236
250
|
const utxoOwner = outputOwners[i];
|
|
@@ -239,9 +253,9 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
239
253
|
ecdhPublicKey,
|
|
240
254
|
);
|
|
241
255
|
const plainText = poseidonDecrypt(
|
|
242
|
-
|
|
256
|
+
event.encryptedValues.slice(4 * i, 4 * i + 4),
|
|
243
257
|
sharedKey,
|
|
244
|
-
|
|
258
|
+
event.encryptionNonce,
|
|
245
259
|
2,
|
|
246
260
|
);
|
|
247
261
|
expect(plainText).to.deep.equal(
|
|
@@ -259,11 +273,6 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
259
273
|
await smtUnregistered.add(incomingUTXOs[i], incomingUTXOs[i]);
|
|
260
274
|
}
|
|
261
275
|
|
|
262
|
-
// check empty values, salt and hashes are empty
|
|
263
|
-
for (let i = outputUtxos.length; i < 10; i++) {
|
|
264
|
-
expect(incomingUTXOs[i]).to.equal(0);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
276
|
// mint sufficient balance in Zeto contract address for Alice to withdraw
|
|
268
277
|
const mintTx = await erc20.connect(deployer).mint(zeto, 3);
|
|
269
278
|
await mintTx.wait();
|
|
@@ -316,8 +325,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
316
325
|
3,
|
|
317
326
|
_withdrawNullifiers,
|
|
318
327
|
withdrawCommitments[0],
|
|
319
|
-
root.bigInt(),
|
|
320
|
-
withdrawEncodedProof,
|
|
328
|
+
encodeToBytesForWithdraw(root.bigInt(), withdrawEncodedProof),
|
|
321
329
|
"0x",
|
|
322
330
|
);
|
|
323
331
|
await tx.wait();
|
|
@@ -339,13 +347,29 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
339
347
|
|
|
340
348
|
utxo100 = newUTXO(100, Alice);
|
|
341
349
|
utxo0 = newUTXO(0, Alice);
|
|
342
|
-
const
|
|
350
|
+
const identitiesRoot = await smtKyc.root();
|
|
351
|
+
const proof3 = await smtKyc.generateCircomVerifierProof(
|
|
352
|
+
kycHash(Alice.babyJubPublicKey),
|
|
353
|
+
identitiesRoot,
|
|
354
|
+
);
|
|
355
|
+
const identitiesMerkleProofs = [
|
|
356
|
+
proof3.siblings.map((s) => s.bigInt()),
|
|
357
|
+
proof3.siblings.map((s) => s.bigInt()),
|
|
358
|
+
];
|
|
359
|
+
const { outputCommitments, encodedProof } = await prepareDepositKycProof(
|
|
343
360
|
Alice,
|
|
344
361
|
[utxo100, utxo0],
|
|
362
|
+
identitiesRoot.bigInt(),
|
|
363
|
+
identitiesMerkleProofs,
|
|
345
364
|
);
|
|
346
365
|
const tx2 = await zeto
|
|
347
366
|
.connect(Alice.signer)
|
|
348
|
-
.deposit(
|
|
367
|
+
.deposit(
|
|
368
|
+
100,
|
|
369
|
+
outputCommitments,
|
|
370
|
+
encodeToBytesForDeposit(encodedProof),
|
|
371
|
+
"0x",
|
|
372
|
+
);
|
|
349
373
|
await tx2.wait();
|
|
350
374
|
|
|
351
375
|
await smtAlice.add(utxo100.hash, utxo100.hash);
|
|
@@ -444,20 +468,21 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
444
468
|
// Bob parses the UTXOs from the onchain event
|
|
445
469
|
const signerAddress = await Alice.signer.getAddress();
|
|
446
470
|
const events = parseUTXOEvents(zeto, result2.txResult!);
|
|
447
|
-
|
|
448
|
-
expect(
|
|
449
|
-
expect(
|
|
450
|
-
|
|
451
|
-
await smtBob.add(
|
|
452
|
-
|
|
453
|
-
|
|
471
|
+
const event = events[0];
|
|
472
|
+
expect(event.submitter).to.equal(signerAddress);
|
|
473
|
+
expect(event.inputs).to.deep.equal([nullifier1.hash, nullifier2.hash]);
|
|
474
|
+
expect(event.outputs).to.deep.equal([_utxo3.hash, utxo4.hash]);
|
|
475
|
+
await smtBob.add(event.outputs[0], event.outputs[0]);
|
|
476
|
+
await smtBob.add(event.outputs[1], event.outputs[1]);
|
|
477
|
+
|
|
478
|
+
const ecdhPublicKey = event.ecdhPublicKey;
|
|
454
479
|
// Bob reconstructs the shared key using his private key and ephemeral public key
|
|
455
480
|
|
|
456
481
|
const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey);
|
|
457
482
|
const plainText = poseidonDecrypt(
|
|
458
|
-
|
|
483
|
+
event.encryptedValues.slice(0, 4),
|
|
459
484
|
sharedKey,
|
|
460
|
-
|
|
485
|
+
event.encryptionNonce,
|
|
461
486
|
2,
|
|
462
487
|
);
|
|
463
488
|
expect(plainText).to.deep.equal(result2.expectedPlainText.slice(0, 2));
|
|
@@ -522,8 +547,9 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
522
547
|
|
|
523
548
|
// Alice gets the new UTXOs from the onchain event and keeps the local SMT in sync
|
|
524
549
|
const events = parseUTXOEvents(zeto, result.txResult!);
|
|
525
|
-
|
|
526
|
-
await smtAlice.add(
|
|
550
|
+
const event = events[0];
|
|
551
|
+
await smtAlice.add(event.outputs[0], event.outputs[0]);
|
|
552
|
+
await smtAlice.add(event.outputs[1], event.outputs[1]);
|
|
527
553
|
}).timeout(600000);
|
|
528
554
|
|
|
529
555
|
it("Alice withdraws her UTXOs to ERC20 tokens should succeed", async function () {
|
|
@@ -564,8 +590,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
564
590
|
80,
|
|
565
591
|
nullifiers,
|
|
566
592
|
outputCommitments[0],
|
|
567
|
-
root.bigInt(),
|
|
568
|
-
encodedProof,
|
|
593
|
+
encodeToBytesForWithdraw(root.bigInt(), encodedProof),
|
|
569
594
|
"0x",
|
|
570
595
|
);
|
|
571
596
|
await tx.wait();
|
|
@@ -583,8 +608,30 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
583
608
|
describe("unregistered user cases", function () {
|
|
584
609
|
let unregisteredUtxo100: UTXO;
|
|
585
610
|
let unregisteredUtxo0: UTXO;
|
|
611
|
+
let smtKycUnregistered: Merkletree;
|
|
612
|
+
|
|
613
|
+
before(async function () {
|
|
614
|
+
const storage5 = new InMemoryDB(str2Bytes("unregisteredKyc"));
|
|
615
|
+
smtKycUnregistered = new Merkletree(storage5, true, 10);
|
|
616
|
+
|
|
617
|
+
// add the unregistered user to the local KYC SMT, but not to the onchain SMT
|
|
618
|
+
await smtKycUnregistered.add(
|
|
619
|
+
kycHash(unregistered.babyJubPublicKey),
|
|
620
|
+
kycHash(unregistered.babyJubPublicKey),
|
|
621
|
+
);
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
it("deposit by an unregistered user should fail", async function () {
|
|
625
|
+
const identitiesRoot = await smtKycUnregistered.root();
|
|
626
|
+
const proof3 = await smtKycUnregistered.generateCircomVerifierProof(
|
|
627
|
+
kycHash(unregistered.babyJubPublicKey),
|
|
628
|
+
identitiesRoot,
|
|
629
|
+
);
|
|
630
|
+
const identitiesMerkleProofs = [
|
|
631
|
+
proof3.siblings.map((s) => s.bigInt()),
|
|
632
|
+
proof3.siblings.map((s) => s.bigInt()),
|
|
633
|
+
];
|
|
586
634
|
|
|
587
|
-
it("deposit by an unregistered user should succeed", async function () {
|
|
588
635
|
const tx = await erc20
|
|
589
636
|
.connect(deployer)
|
|
590
637
|
.mint(unregistered.ethAddress, 100);
|
|
@@ -596,150 +643,22 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
596
643
|
|
|
597
644
|
unregisteredUtxo100 = newUTXO(100, unregistered);
|
|
598
645
|
unregisteredUtxo0 = newUTXO(0, unregistered);
|
|
599
|
-
const { outputCommitments, encodedProof } = await
|
|
646
|
+
const { outputCommitments, encodedProof } = await prepareDepositKycProof(
|
|
600
647
|
unregistered,
|
|
601
648
|
[unregisteredUtxo100, unregisteredUtxo0],
|
|
649
|
+
identitiesRoot.bigInt(),
|
|
650
|
+
identitiesMerkleProofs,
|
|
602
651
|
);
|
|
603
|
-
const tx2 = await zeto
|
|
604
|
-
.connect(unregistered.signer)
|
|
605
|
-
.deposit(100, outputCommitments, encodedProof, "0x");
|
|
606
|
-
await tx2.wait();
|
|
607
|
-
|
|
608
|
-
// Alice tracks the UTXO inside the SMT
|
|
609
|
-
await smtAlice.add(unregisteredUtxo100.hash, unregisteredUtxo100.hash);
|
|
610
|
-
await smtAlice.add(unregisteredUtxo0.hash, unregisteredUtxo0.hash);
|
|
611
|
-
// Bob also locally tracks the UTXOs inside the SMT
|
|
612
|
-
await smtBob.add(unregisteredUtxo100.hash, unregisteredUtxo100.hash);
|
|
613
|
-
await smtBob.add(unregisteredUtxo0.hash, unregisteredUtxo0.hash);
|
|
614
|
-
});
|
|
615
|
-
|
|
616
|
-
it("transfer from an unregistered user should fail", async function () {
|
|
617
|
-
// catch up the local SMT for the unregistered user
|
|
618
|
-
await smtUnregistered.add(utxo100.hash, utxo100.hash);
|
|
619
|
-
await smtUnregistered.add(utxo0.hash, utxo0.hash);
|
|
620
|
-
await smtUnregistered.add(utxo1.hash, utxo1.hash);
|
|
621
|
-
await smtUnregistered.add(utxo2.hash, utxo2.hash);
|
|
622
|
-
await smtUnregistered.add(_utxo3.hash, _utxo3.hash);
|
|
623
|
-
await smtUnregistered.add(utxo4.hash, utxo4.hash);
|
|
624
|
-
await smtUnregistered.add(utxo6.hash, utxo6.hash);
|
|
625
|
-
await smtUnregistered.add(utxo7.hash, utxo7.hash);
|
|
626
|
-
await smtUnregistered.add(
|
|
627
|
-
withdrawChangeUTXO.hash,
|
|
628
|
-
withdrawChangeUTXO.hash,
|
|
629
|
-
);
|
|
630
|
-
await smtUnregistered.add(
|
|
631
|
-
unregisteredUtxo100.hash,
|
|
632
|
-
unregisteredUtxo100.hash,
|
|
633
|
-
);
|
|
634
|
-
await smtUnregistered.add(unregisteredUtxo0.hash, unregisteredUtxo0.hash);
|
|
635
|
-
const utxosRoot = await smtUnregistered.root();
|
|
636
|
-
|
|
637
|
-
const nullifier = newNullifier(unregisteredUtxo100, unregistered);
|
|
638
|
-
const output1 = newUTXO(100, Bob);
|
|
639
|
-
const output2 = newUTXO(0, unregistered);
|
|
640
|
-
const proof = await smtUnregistered.generateCircomVerifierProof(
|
|
641
|
-
unregisteredUtxo100.hash,
|
|
642
|
-
utxosRoot,
|
|
643
|
-
);
|
|
644
|
-
const merkleProofs = [
|
|
645
|
-
proof.siblings.map((s) => s.bigInt()),
|
|
646
|
-
proof.siblings.map((s) => s.bigInt()),
|
|
647
|
-
];
|
|
648
|
-
|
|
649
|
-
// add the unregistered user to the local KYC SMT, but not to the onchain SMT
|
|
650
|
-
await smtKyc.add(
|
|
651
|
-
kycHash(unregistered.babyJubPublicKey),
|
|
652
|
-
kycHash(unregistered.babyJubPublicKey),
|
|
653
|
-
);
|
|
654
|
-
const identitiesRoot = await smtKyc.root();
|
|
655
|
-
const proof3 = await smtKyc.generateCircomVerifierProof(
|
|
656
|
-
kycHash(unregistered.babyJubPublicKey),
|
|
657
|
-
identitiesRoot,
|
|
658
|
-
);
|
|
659
|
-
const proof4 = await smtKyc.generateCircomVerifierProof(
|
|
660
|
-
kycHash(Bob.babyJubPublicKey),
|
|
661
|
-
identitiesRoot,
|
|
662
|
-
);
|
|
663
|
-
const identitiesMerkleProofs = [
|
|
664
|
-
proof3.siblings.map((s) => s.bigInt()), // identity proof for the sender (unregistered)
|
|
665
|
-
proof4.siblings.map((s) => s.bigInt()), // identity proof for the 1st owner of the output UTXO (Bob)
|
|
666
|
-
proof3.siblings.map((s) => s.bigInt()), // identity proof for the 2nd owner of the output UTXO (unregistered)
|
|
667
|
-
];
|
|
668
652
|
await expect(
|
|
669
|
-
|
|
670
|
-
unregistered
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
[Bob, unregistered],
|
|
679
|
-
),
|
|
680
|
-
).rejectedWith("Invalid proof");
|
|
681
|
-
});
|
|
682
|
-
|
|
683
|
-
it("the unregistered user can still withdraw their UTXOs to ERC20 tokens", async function () {
|
|
684
|
-
const startingBalance = await erc20.balanceOf(unregistered.ethAddress);
|
|
685
|
-
// unregistered user generates the nullifiers for the UTXOs to be spent
|
|
686
|
-
const nullifier1 = newNullifier(unregisteredUtxo100, unregistered);
|
|
687
|
-
|
|
688
|
-
// unregistered user generates inclusion proofs for the UTXOs to be spent
|
|
689
|
-
let root = await smtUnregistered.root();
|
|
690
|
-
const proof1 = await smtUnregistered.generateCircomVerifierProof(
|
|
691
|
-
unregisteredUtxo100.hash,
|
|
692
|
-
root,
|
|
693
|
-
);
|
|
694
|
-
const proof2 = await smtUnregistered.generateCircomVerifierProof(
|
|
695
|
-
0n,
|
|
696
|
-
root,
|
|
697
|
-
);
|
|
698
|
-
const merkleProofs = [
|
|
699
|
-
proof1.siblings.map((s) => s.bigInt()),
|
|
700
|
-
proof2.siblings.map((s) => s.bigInt()),
|
|
701
|
-
];
|
|
702
|
-
|
|
703
|
-
// unregistered user proposes the output ERC20 tokens
|
|
704
|
-
const unregisteredWithdrawChangeUTXO = newUTXO(0, unregistered);
|
|
705
|
-
|
|
706
|
-
const { nullifiers, outputCommitments, encodedProof } =
|
|
707
|
-
await prepareNullifierWithdrawProof(
|
|
708
|
-
unregistered,
|
|
709
|
-
[unregisteredUtxo100, ZERO_UTXO],
|
|
710
|
-
[nullifier1, ZERO_UTXO],
|
|
711
|
-
unregisteredWithdrawChangeUTXO,
|
|
712
|
-
root.bigInt(),
|
|
713
|
-
merkleProofs,
|
|
714
|
-
);
|
|
715
|
-
|
|
716
|
-
// unregistered user withdraws her UTXOs to ERC20 tokens
|
|
717
|
-
const tx = await zeto
|
|
718
|
-
.connect(unregistered.signer)
|
|
719
|
-
.withdraw(
|
|
720
|
-
100,
|
|
721
|
-
nullifiers,
|
|
722
|
-
outputCommitments[0],
|
|
723
|
-
root.bigInt(),
|
|
724
|
-
encodedProof,
|
|
725
|
-
"0x",
|
|
726
|
-
);
|
|
727
|
-
await tx.wait();
|
|
728
|
-
|
|
729
|
-
// Alice tracks the UTXO inside the SMT
|
|
730
|
-
await smtAlice.add(
|
|
731
|
-
unregisteredWithdrawChangeUTXO.hash,
|
|
732
|
-
unregisteredWithdrawChangeUTXO.hash,
|
|
733
|
-
);
|
|
734
|
-
// Bob also locally tracks the UTXOs inside the SMT
|
|
735
|
-
await smtBob.add(
|
|
736
|
-
unregisteredWithdrawChangeUTXO.hash,
|
|
737
|
-
unregisteredWithdrawChangeUTXO.hash,
|
|
738
|
-
);
|
|
739
|
-
|
|
740
|
-
// unregistered user checks her ERC20 balance
|
|
741
|
-
const endingBalance = await erc20.balanceOf(unregistered.ethAddress);
|
|
742
|
-
expect(endingBalance - startingBalance).to.be.equal(100);
|
|
653
|
+
zeto
|
|
654
|
+
.connect(unregistered.signer)
|
|
655
|
+
.deposit(
|
|
656
|
+
100,
|
|
657
|
+
outputCommitments,
|
|
658
|
+
encodeToBytesForDeposit(encodedProof),
|
|
659
|
+
"0x",
|
|
660
|
+
),
|
|
661
|
+
).to.be.rejectedWith("VM Exception while processing transaction: reverted with custom error 'InvalidProof()'");
|
|
743
662
|
});
|
|
744
663
|
});
|
|
745
664
|
|
|
@@ -788,8 +707,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
788
707
|
10,
|
|
789
708
|
nullifiers,
|
|
790
709
|
outputCommitments[0],
|
|
791
|
-
root.bigInt(),
|
|
792
|
-
encodedProof,
|
|
710
|
+
encodeToBytesForWithdraw(root.bigInt(), encodedProof),
|
|
793
711
|
"0x",
|
|
794
712
|
),
|
|
795
713
|
).rejectedWith("UTXOAlreadySpent");
|
|
@@ -1181,11 +1099,13 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
1181
1099
|
const tx = await zeto.connect(signer.signer).transfer(
|
|
1182
1100
|
nullifiers.filter((ic) => ic !== 0n), // trim off empty utxo hashes to check padding logic for batching works
|
|
1183
1101
|
outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1102
|
+
encodeToBytes(
|
|
1103
|
+
root,
|
|
1104
|
+
encryptionNonce,
|
|
1105
|
+
ecdhPublicKey,
|
|
1106
|
+
encryptedValues,
|
|
1107
|
+
encodedProof,
|
|
1108
|
+
),
|
|
1189
1109
|
"0x",
|
|
1190
1110
|
);
|
|
1191
1111
|
const results: ContractTransactionReceipt | null = await tx.wait();
|
|
@@ -1195,3 +1115,22 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
1195
1115
|
return results;
|
|
1196
1116
|
}
|
|
1197
1117
|
});
|
|
1118
|
+
|
|
1119
|
+
function encodeToBytes(
|
|
1120
|
+
root: any,
|
|
1121
|
+
encryptionNonce: any,
|
|
1122
|
+
ecdhPublicKey: any,
|
|
1123
|
+
encryptedValues: any,
|
|
1124
|
+
proof: any,
|
|
1125
|
+
) {
|
|
1126
|
+
return new AbiCoder().encode(
|
|
1127
|
+
[
|
|
1128
|
+
"uint256 root",
|
|
1129
|
+
"uint256 encryptionNonce",
|
|
1130
|
+
"uint256[2] ecdhPublicKey",
|
|
1131
|
+
"uint256[] encryptedValues",
|
|
1132
|
+
"tuple(uint256[2] pA, uint256[2][2] pB, uint256[2] pC)",
|
|
1133
|
+
],
|
|
1134
|
+
[root, encryptionNonce, ecdhPublicKey, encryptedValues, proof],
|
|
1135
|
+
);
|
|
1136
|
+
}
|
|
@@ -15,7 +15,12 @@
|
|
|
15
15
|
// limitations under the License.
|
|
16
16
|
|
|
17
17
|
import { ethers, network } from "hardhat";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
ContractTransactionReceipt,
|
|
20
|
+
Signer,
|
|
21
|
+
BigNumberish,
|
|
22
|
+
AbiCoder,
|
|
23
|
+
} from "ethers";
|
|
19
24
|
import { expect } from "chai";
|
|
20
25
|
import {
|
|
21
26
|
loadCircuit,
|
|
@@ -46,6 +51,8 @@ import {
|
|
|
46
51
|
loadProvingKeys,
|
|
47
52
|
prepareDepositProof,
|
|
48
53
|
prepareNullifierWithdrawProof,
|
|
54
|
+
encodeToBytesForDeposit,
|
|
55
|
+
encodeToBytesForWithdraw,
|
|
49
56
|
} from "./utils";
|
|
50
57
|
import { deployZeto } from "./lib/deploy";
|
|
51
58
|
const poseidonHash = Poseidon.poseidon4;
|
|
@@ -177,12 +184,13 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
177
184
|
|
|
178
185
|
const signerAddress = await Alice.signer.getAddress();
|
|
179
186
|
const events = parseUTXOEvents(zeto, result.txResult!);
|
|
180
|
-
|
|
181
|
-
expect(
|
|
187
|
+
const event = events[0];
|
|
188
|
+
expect(event.submitter).to.equal(signerAddress);
|
|
189
|
+
expect(event.inputs).to.deep.equal(nullifiers.map((n) => n.hash));
|
|
182
190
|
|
|
183
|
-
const incomingUTXOs: any =
|
|
191
|
+
const incomingUTXOs: any = event.outputs;
|
|
184
192
|
|
|
185
|
-
const ecdhPublicKey =
|
|
193
|
+
const ecdhPublicKey = event.ecdhPublicKey;
|
|
186
194
|
|
|
187
195
|
// check the non-empty output hashes are correct
|
|
188
196
|
for (let i = 0; i < outputUtxos.length; i++) {
|
|
@@ -192,9 +200,9 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
192
200
|
ecdhPublicKey,
|
|
193
201
|
);
|
|
194
202
|
const plainText = poseidonDecrypt(
|
|
195
|
-
|
|
203
|
+
event.encryptedValuesForReceiver.slice(4 * i, 4 * i + 4),
|
|
196
204
|
sharedKey,
|
|
197
|
-
|
|
205
|
+
event.encryptionNonce,
|
|
198
206
|
2,
|
|
199
207
|
);
|
|
200
208
|
expect(plainText).to.deep.equal(
|
|
@@ -210,20 +218,15 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
210
218
|
await smtAlice.add(incomingUTXOs[i], incomingUTXOs[i]);
|
|
211
219
|
await smtBob.add(incomingUTXOs[i], incomingUTXOs[i]);
|
|
212
220
|
}
|
|
213
|
-
|
|
214
|
-
// check empty values, salt and hashes are empty
|
|
215
|
-
for (let i = outputUtxos.length; i < 10; i++) {
|
|
216
|
-
expect(incomingUTXOs[i]).to.equal(0);
|
|
217
|
-
}
|
|
218
221
|
// The regulator uses the encrypted values in the event to decrypt and recover the UTXO value and salt
|
|
219
222
|
const auditKey = genEcdhSharedKey(
|
|
220
223
|
Authority.babyJubPrivateKey,
|
|
221
224
|
ecdhPublicKey,
|
|
222
225
|
);
|
|
223
226
|
const auditPlainText = poseidonDecrypt(
|
|
224
|
-
|
|
227
|
+
event.encryptedValuesForAuthority,
|
|
225
228
|
auditKey,
|
|
226
|
-
|
|
229
|
+
event.encryptionNonce,
|
|
227
230
|
62,
|
|
228
231
|
);
|
|
229
232
|
|
|
@@ -252,12 +255,6 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
252
255
|
expect(calHash).to.equal(outputUtxos[i].hash);
|
|
253
256
|
}
|
|
254
257
|
|
|
255
|
-
// check empty hashes are empty
|
|
256
|
-
for (let i = outputUtxos.length; i < 10; i++) {
|
|
257
|
-
expect(auditPlainText[2 * i + 42]).to.equal(0);
|
|
258
|
-
expect(auditPlainText[2 * i + 43]).to.equal(0);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
258
|
// mint sufficient balance in Zeto contract address for Alice to withdraw
|
|
262
259
|
const mintTx = await erc20.connect(deployer).mint(zeto, 3);
|
|
263
260
|
await mintTx.wait();
|
|
@@ -310,8 +307,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
310
307
|
3,
|
|
311
308
|
_withdrawNullifiers,
|
|
312
309
|
withdrawCommitments[0],
|
|
313
|
-
root.bigInt(),
|
|
314
|
-
withdrawEncodedProof,
|
|
310
|
+
encodeToBytesForWithdraw(root.bigInt(), withdrawEncodedProof),
|
|
315
311
|
"0x",
|
|
316
312
|
);
|
|
317
313
|
await tx.wait();
|
|
@@ -339,7 +335,12 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
339
335
|
);
|
|
340
336
|
const tx2 = await zeto
|
|
341
337
|
.connect(Alice.signer)
|
|
342
|
-
.deposit(
|
|
338
|
+
.deposit(
|
|
339
|
+
100,
|
|
340
|
+
outputCommitments,
|
|
341
|
+
encodeToBytesForDeposit(encodedProof),
|
|
342
|
+
"0x",
|
|
343
|
+
);
|
|
343
344
|
await tx2.wait();
|
|
344
345
|
|
|
345
346
|
await smtAlice.add(utxo100.hash, utxo100.hash);
|
|
@@ -414,20 +415,21 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
414
415
|
// Bob parses the UTXOs from the onchain event
|
|
415
416
|
const signerAddress = await Alice.signer.getAddress();
|
|
416
417
|
const events = parseUTXOEvents(zeto, result2.txResult!);
|
|
417
|
-
|
|
418
|
-
expect(
|
|
419
|
-
expect(
|
|
420
|
-
|
|
421
|
-
await smtBob.add(
|
|
422
|
-
|
|
423
|
-
|
|
418
|
+
const event = events[0];
|
|
419
|
+
expect(event.submitter).to.equal(signerAddress);
|
|
420
|
+
expect(event.inputs).to.deep.equal([nullifier1.hash, nullifier2.hash]);
|
|
421
|
+
expect(event.outputs).to.deep.equal([_utxo3.hash, utxo4.hash]);
|
|
422
|
+
await smtBob.add(event.outputs[0], event.outputs[0]);
|
|
423
|
+
await smtBob.add(event.outputs[1], event.outputs[1]);
|
|
424
|
+
|
|
425
|
+
const ecdhPublicKey = event.ecdhPublicKey;
|
|
424
426
|
// Bob reconstructs the shared key using his private key and ephemeral public key
|
|
425
427
|
|
|
426
428
|
const sharedKey = genEcdhSharedKey(Bob.babyJubPrivateKey, ecdhPublicKey);
|
|
427
429
|
const plainText1 = poseidonDecrypt(
|
|
428
|
-
|
|
430
|
+
event.encryptedValuesForReceiver.slice(0, 4),
|
|
429
431
|
sharedKey,
|
|
430
|
-
|
|
432
|
+
event.encryptionNonce,
|
|
431
433
|
2,
|
|
432
434
|
);
|
|
433
435
|
expect(plainText1).to.deep.equal(result2.expectedPlainText.slice(0, 2));
|
|
@@ -441,9 +443,9 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
441
443
|
ecdhPublicKey,
|
|
442
444
|
);
|
|
443
445
|
const plainText2 = poseidonDecrypt(
|
|
444
|
-
|
|
446
|
+
event.encryptedValuesForAuthority,
|
|
445
447
|
sharedKey2,
|
|
446
|
-
|
|
448
|
+
event.encryptionNonce,
|
|
447
449
|
14,
|
|
448
450
|
);
|
|
449
451
|
expect(plainText2).to.deep.equal([
|
|
@@ -527,8 +529,9 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
527
529
|
|
|
528
530
|
// Alice gets the new UTXOs from the onchain event and keeps the local SMT in sync
|
|
529
531
|
const events = parseUTXOEvents(zeto, result.txResult!);
|
|
530
|
-
|
|
531
|
-
await smtAlice.add(
|
|
532
|
+
const event = events[0];
|
|
533
|
+
await smtAlice.add(event.outputs[0], event.outputs[0]);
|
|
534
|
+
await smtAlice.add(event.outputs[1], event.outputs[1]);
|
|
532
535
|
}).timeout(600000);
|
|
533
536
|
|
|
534
537
|
it("Alice withdraws her UTXOs to ERC20 tokens should succeed", async function () {
|
|
@@ -568,8 +571,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
568
571
|
80,
|
|
569
572
|
nullifiers,
|
|
570
573
|
outputCommitments[0],
|
|
571
|
-
root.bigInt(),
|
|
572
|
-
encodedProof,
|
|
574
|
+
encodeToBytesForWithdraw(root.bigInt(), encodedProof),
|
|
573
575
|
"0x",
|
|
574
576
|
);
|
|
575
577
|
await tx.wait();
|
|
@@ -629,8 +631,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
629
631
|
80,
|
|
630
632
|
nullifiers,
|
|
631
633
|
outputCommitments[0],
|
|
632
|
-
root.bigInt(),
|
|
633
|
-
encodedProof,
|
|
634
|
+
encodeToBytesForWithdraw(root.bigInt(), encodedProof),
|
|
634
635
|
"0x",
|
|
635
636
|
),
|
|
636
637
|
).rejectedWith("UTXOAlreadySpent");
|
|
@@ -944,12 +945,14 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
944
945
|
const tx = await zeto.connect(signer.signer).transfer(
|
|
945
946
|
nullifiers.filter((ic) => ic !== 0n), // trim off empty utxo hashes to check padding logic for batching works
|
|
946
947
|
outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
948
|
+
encodeToBytes(
|
|
949
|
+
root,
|
|
950
|
+
encryptionNonce,
|
|
951
|
+
ecdhPublicKey,
|
|
952
|
+
encryptedValuesForReceiver,
|
|
953
|
+
encryptedValuesForRegulator,
|
|
954
|
+
encodedProof,
|
|
955
|
+
),
|
|
953
956
|
"0x",
|
|
954
957
|
);
|
|
955
958
|
const results: ContractTransactionReceipt | null = await tx.wait();
|
|
@@ -959,3 +962,31 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
|
|
|
959
962
|
return results;
|
|
960
963
|
}
|
|
961
964
|
});
|
|
965
|
+
|
|
966
|
+
function encodeToBytes(
|
|
967
|
+
root: any,
|
|
968
|
+
encryptionNonce: any,
|
|
969
|
+
ecdhPublicKey: any,
|
|
970
|
+
encryptedValuesForReceiver: any,
|
|
971
|
+
encryptedValuesForAuthority: any,
|
|
972
|
+
proof: any,
|
|
973
|
+
) {
|
|
974
|
+
return new AbiCoder().encode(
|
|
975
|
+
[
|
|
976
|
+
"uint256 root",
|
|
977
|
+
"uint256 encryptionNonce",
|
|
978
|
+
"uint256[2] ecdhPublicKey",
|
|
979
|
+
"uint256[] encryptedValuesForReceiver",
|
|
980
|
+
"uint256[] encryptedValuesForAuthority",
|
|
981
|
+
"tuple(uint256[2] pA, uint256[2][2] pB, uint256[2] pC)",
|
|
982
|
+
],
|
|
983
|
+
[
|
|
984
|
+
root,
|
|
985
|
+
encryptionNonce,
|
|
986
|
+
ecdhPublicKey,
|
|
987
|
+
encryptedValuesForReceiver,
|
|
988
|
+
encryptedValuesForAuthority,
|
|
989
|
+
proof,
|
|
990
|
+
],
|
|
991
|
+
);
|
|
992
|
+
}
|