@lfdecentralizedtrust/zeto-contracts 0.2.2 → 0.5.1
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 +76 -162
- package/config/eip170.ts +30 -0
- 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/IZetoLockHooks.sol +42 -0
- 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 +443 -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 +219 -0
- package/contracts/lib/zeto_lockable_lib.sol +460 -0
- package/contracts/lib/zeto_lockable_storage.sol +43 -0
- package/contracts/lib/zeto_non_fungible.sol +228 -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 +18 -3
- package/ignition/modules/lib/deps.ts +13 -0
- package/ignition/modules/test/tendecimals.ts +7 -1
- package/ignition/modules/zeto_anon.ts +3 -0
- package/ignition/modules/zeto_anon_burnable.ts +11 -7
- package/ignition/modules/zeto_anon_enc.ts +3 -0
- package/ignition/modules/zeto_anon_enc_nullifier.ts +34 -0
- package/ignition/modules/zeto_anon_enc_nullifier_kyc.ts +5 -2
- package/ignition/modules/zeto_anon_enc_nullifier_non_repudiation.ts +3 -0
- package/ignition/modules/zeto_anon_nullifier.ts +31 -4
- package/ignition/modules/zeto_anon_nullifier_burnable.ts +53 -16
- package/ignition/modules/zeto_anon_nullifier_kyc.ts +30 -12
- package/ignition/modules/zeto_anon_nullifier_qurrency.ts +3 -0
- package/ignition/modules/zeto_nf_anon.ts +3 -1
- package/ignition/modules/zeto_nf_anon_nullifier.ts +17 -12
- package/package.json +7 -3
- package/scripts/deploy_cloneable.ts +19 -10
- package/scripts/deploy_upgradeable.ts +9 -5
- package/scripts/lib/zeto_libraries.ts +47 -0
- package/scripts/tokens/Zeto_Anon.ts +6 -3
- package/scripts/tokens/Zeto_AnonBurnable.ts +4 -1
- package/scripts/tokens/Zeto_AnonEnc.ts +15 -3
- package/scripts/tokens/Zeto_AnonEncNullifier.ts +11 -8
- package/scripts/tokens/Zeto_AnonEncNullifierKyc.ts +7 -6
- package/scripts/tokens/Zeto_AnonEncNullifierNonRepudiation.ts +7 -6
- package/scripts/tokens/Zeto_AnonNullifier.ts +7 -6
- package/scripts/tokens/Zeto_AnonNullifierBurnable.ts +7 -6
- package/scripts/tokens/Zeto_AnonNullifierKyc.ts +7 -6
- package/scripts/tokens/Zeto_AnonNullifierQurrency.ts +7 -8
- package/scripts/tokens/Zeto_NfAnon.ts +5 -3
- package/scripts/tokens/Zeto_NfAnonNullifier.ts +7 -7
- package/test/factory.ts +55 -73
- package/test/lib/anon_nullifier_helpers.ts +89 -0
- package/test/lib/anon_zeto_helpers.ts +76 -0
- package/test/lib/deploy.ts +5 -2
- package/test/lib/eip170.ts +23 -0
- 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 -27
- package/test/utils.ts +144 -21
- package/test/zeto_anon.ts +956 -465
- package/test/zeto_anon_enc.ts +881 -143
- package/test/zeto_anon_enc_nullifier.ts +850 -39
- package/test/zeto_anon_enc_nullifier_kyc.ts +123 -182
- package/test/zeto_anon_enc_nullifier_non_repudiation.ts +80 -47
- package/test/zeto_anon_nullifier.ts +1212 -954
- package/test/zeto_anon_nullifier_kyc.ts +677 -656
- package/test/zeto_anon_nullifier_qurrency.ts +455 -307
- package/test/zeto_nf_anon.ts +737 -138
- package/test/zeto_nf_anon_nullifier.ts +876 -247
- 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,14 +15,26 @@
|
|
|
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";
|
|
24
|
+
import crypto from "crypto";
|
|
19
25
|
import { expect } from "chai";
|
|
26
|
+
import { MlKem512 } from "mlkem";
|
|
20
27
|
import {
|
|
21
28
|
loadCircuit,
|
|
22
29
|
Poseidon,
|
|
23
30
|
encodeProof,
|
|
24
|
-
|
|
31
|
+
bytesToBits,
|
|
32
|
+
newEncryptionNonce,
|
|
33
|
+
poseidonDecrypt,
|
|
34
|
+
publicKeyFromSeed,
|
|
35
|
+
recoverMlKemCiphertextBytes,
|
|
25
36
|
} from "zeto-js";
|
|
37
|
+
import testKeyPair from "zeto-js/lib/testKeypair.js";
|
|
26
38
|
import { groth16 } from "snarkjs";
|
|
27
39
|
import { Merkletree, InMemoryDB, str2Bytes } from "@iden3/js-merkletree";
|
|
28
40
|
import {
|
|
@@ -39,11 +51,14 @@ import {
|
|
|
39
51
|
loadProvingKeys,
|
|
40
52
|
prepareDepositProof,
|
|
41
53
|
prepareNullifierWithdrawProof,
|
|
42
|
-
|
|
54
|
+
encodeToBytesForDeposit,
|
|
55
|
+
encodeToBytesForWithdraw,
|
|
43
56
|
} from "./utils";
|
|
44
57
|
import { deployZeto } from "./lib/deploy";
|
|
45
58
|
|
|
46
|
-
describe(
|
|
59
|
+
describe(
|
|
60
|
+
"Zeto based fungible token with anonymity using nullifiers with Kyber encryption for auditability",
|
|
61
|
+
function () {
|
|
47
62
|
let deployer: Signer;
|
|
48
63
|
let Alice: User;
|
|
49
64
|
let Bob: User;
|
|
@@ -95,277 +110,326 @@ describe("Zeto based fungible token with anonymity using nullifiers with Kyber e
|
|
|
95
110
|
));
|
|
96
111
|
});
|
|
97
112
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
const mintResult = await doMint(zeto, deployer, inputUtxos);
|
|
118
|
-
|
|
119
|
-
const mintEvents = parseUTXOEvents(zeto, mintResult);
|
|
120
|
-
const mintedHashes = mintEvents[0].outputs;
|
|
121
|
-
for (let i = 0; i < mintedHashes.length; i++) {
|
|
122
|
-
if (mintedHashes[i] !== 0) {
|
|
123
|
-
await smtAlice.add(mintedHashes[i], mintedHashes[i]);
|
|
124
|
-
await smtBob.add(mintedHashes[i], mintedHashes[i]);
|
|
113
|
+
describe("batch transfer", function () {
|
|
114
|
+
it("onchain SMT root should be equal to the offchain SMT root", async function () {
|
|
115
|
+
const root = await smtAlice.root();
|
|
116
|
+
const onchainRoot = await zeto.getRoot();
|
|
117
|
+
expect(onchainRoot).to.equal(0n);
|
|
118
|
+
expect(root.string()).to.equal(onchainRoot.toString());
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("(batch) mint to Alice and batch transfer 10 UTXOs honestly to Bob & Charlie then withdraw should succeed", async function () {
|
|
122
|
+
this.timeout(600000);
|
|
123
|
+
|
|
124
|
+
// first mint the tokens for batch testing
|
|
125
|
+
const inputUtxos = [];
|
|
126
|
+
const nullifiers = [];
|
|
127
|
+
for (let i = 0; i < 10; i++) {
|
|
128
|
+
// mint 10 utxos
|
|
129
|
+
const _utxo = newUTXO(1, Alice);
|
|
130
|
+
nullifiers.push(newNullifier(_utxo, Alice));
|
|
131
|
+
inputUtxos.push(_utxo);
|
|
125
132
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
133
|
+
const mintResult = await doMint(zeto, deployer, inputUtxos);
|
|
134
|
+
|
|
135
|
+
const mintEvents = parseUTXOEvents(zeto, mintResult);
|
|
136
|
+
const mintedHashes = mintEvents[0].outputs;
|
|
137
|
+
for (let i = 0; i < mintedHashes.length; i++) {
|
|
138
|
+
if (mintedHashes[i] !== 0) {
|
|
139
|
+
await smtAlice.add(mintedHashes[i], mintedHashes[i]);
|
|
140
|
+
await smtBob.add(mintedHashes[i], mintedHashes[i]);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Alice generates inclusion proofs for the UTXOs to be spent
|
|
144
|
+
let root = await smtAlice.root();
|
|
145
|
+
const mtps = [];
|
|
146
|
+
for (let i = 0; i < inputUtxos.length; i++) {
|
|
147
|
+
const p = await smtAlice.generateCircomVerifierProof(
|
|
148
|
+
inputUtxos[i].hash,
|
|
149
|
+
root,
|
|
150
|
+
);
|
|
151
|
+
mtps.push(p.siblings.map((s) => s.bigInt()));
|
|
152
|
+
}
|
|
153
|
+
const aliceUTXOsToBeWithdrawn = [
|
|
154
|
+
newUTXO(1, Alice),
|
|
155
|
+
newUTXO(1, Alice),
|
|
156
|
+
newUTXO(1, Alice),
|
|
157
|
+
];
|
|
158
|
+
// Alice proposes the output UTXOs, 1 utxo to bob, 1 utxo to charlie and 3 utxos to alice
|
|
159
|
+
const _bOut1 = newUTXO(6, Bob);
|
|
160
|
+
const _bOut2 = newUTXO(1, Charlie);
|
|
161
|
+
|
|
162
|
+
const outputUtxos = [_bOut1, _bOut2, ...aliceUTXOsToBeWithdrawn];
|
|
163
|
+
const outputOwners = [Bob, Charlie, Alice, Alice, Alice];
|
|
164
|
+
const inflatedOutputUtxos = [...outputUtxos];
|
|
165
|
+
const inflatedOutputOwners = [...outputOwners];
|
|
166
|
+
for (let i = 0; i < 10 - outputUtxos.length; i++) {
|
|
167
|
+
inflatedOutputUtxos.push(ZERO_UTXO);
|
|
168
|
+
inflatedOutputOwners.push(Bob);
|
|
169
|
+
}
|
|
170
|
+
// Alice transfers her UTXOs to Bob
|
|
171
|
+
const result = await doTransfer(
|
|
172
|
+
Alice,
|
|
173
|
+
inputUtxos,
|
|
174
|
+
nullifiers,
|
|
175
|
+
inflatedOutputUtxos,
|
|
176
|
+
root.bigInt(),
|
|
177
|
+
mtps,
|
|
178
|
+
inflatedOutputOwners,
|
|
134
179
|
);
|
|
135
|
-
mtps.push(p.siblings.map((s) => s.bigInt()));
|
|
136
|
-
}
|
|
137
|
-
const aliceUTXOsToBeWithdrawn = [
|
|
138
|
-
newUTXO(1, Alice),
|
|
139
|
-
newUTXO(1, Alice),
|
|
140
|
-
newUTXO(1, Alice),
|
|
141
|
-
];
|
|
142
|
-
// Alice proposes the output UTXOs, 1 utxo to bob, 1 utxo to charlie and 3 utxos to alice
|
|
143
|
-
const _bOut1 = newUTXO(6, Bob);
|
|
144
|
-
const _bOut2 = newUTXO(1, Charlie);
|
|
145
|
-
|
|
146
|
-
const outputUtxos = [_bOut1, _bOut2, ...aliceUTXOsToBeWithdrawn];
|
|
147
|
-
const outputOwners = [Bob, Charlie, Alice, Alice, Alice];
|
|
148
|
-
const inflatedOutputUtxos = [...outputUtxos];
|
|
149
|
-
const inflatedOutputOwners = [...outputOwners];
|
|
150
|
-
for (let i = 0; i < 10 - outputUtxos.length; i++) {
|
|
151
|
-
inflatedOutputUtxos.push(ZERO_UTXO);
|
|
152
|
-
inflatedOutputOwners.push(Bob);
|
|
153
|
-
}
|
|
154
|
-
// Alice transfers her UTXOs to Bob
|
|
155
|
-
const result = await doTransfer(
|
|
156
|
-
Alice,
|
|
157
|
-
inputUtxos,
|
|
158
|
-
nullifiers,
|
|
159
|
-
inflatedOutputUtxos,
|
|
160
|
-
root.bigInt(),
|
|
161
|
-
mtps,
|
|
162
|
-
inflatedOutputOwners,
|
|
163
|
-
);
|
|
164
180
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
181
|
+
const signerAddress = await Alice.signer.getAddress();
|
|
182
|
+
const events = parseUTXOEvents(zeto, result.txResult!);
|
|
183
|
+
const event = events[0];
|
|
184
|
+
expect(event.submitter).to.equal(signerAddress);
|
|
185
|
+
expect(event.inputs).to.deep.equal(nullifiers.map((n) => n.hash));
|
|
186
|
+
|
|
187
|
+
const incomingUTXOs: any = event.outputs;
|
|
188
|
+
// check the non-empty output hashes are correct
|
|
189
|
+
for (let i = 0; i < outputUtxos.length; i++) {
|
|
190
|
+
// Bob uses the information received from Alice to reconstruct the UTXO sent to him
|
|
191
|
+
const receivedValue = outputUtxos[i].value;
|
|
192
|
+
const receivedSalt = outputUtxos[i].salt;
|
|
193
|
+
const hash = Poseidon.poseidon4([
|
|
194
|
+
BigInt(receivedValue),
|
|
195
|
+
receivedSalt,
|
|
196
|
+
outputOwners[i].babyJubPublicKey[0],
|
|
197
|
+
outputOwners[i].babyJubPublicKey[1],
|
|
198
|
+
]);
|
|
199
|
+
expect(incomingUTXOs[i]).to.equal(hash);
|
|
200
|
+
await smtAlice.add(incomingUTXOs[i], incomingUTXOs[i]);
|
|
201
|
+
await smtBob.add(incomingUTXOs[i], incomingUTXOs[i]);
|
|
202
|
+
}
|
|
169
203
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
204
|
+
// mint sufficient balance in Zeto contract address for Alice to withdraw
|
|
205
|
+
const mintTx = await erc20.connect(deployer).mint(zeto, 3);
|
|
206
|
+
await mintTx.wait();
|
|
207
|
+
const startingBalance = await erc20.balanceOf(Alice.ethAddress);
|
|
208
|
+
|
|
209
|
+
// Alice generates the nullifiers for the UTXOs to be spent
|
|
210
|
+
root = await smtAlice.root();
|
|
211
|
+
const inflatedWithdrawNullifiers = [];
|
|
212
|
+
const inflatedWithdrawInputs = [];
|
|
213
|
+
const inflatedWithdrawMTPs = [];
|
|
214
|
+
for (let i = 0; i < aliceUTXOsToBeWithdrawn.length; i++) {
|
|
215
|
+
inflatedWithdrawInputs.push(aliceUTXOsToBeWithdrawn[i]);
|
|
216
|
+
inflatedWithdrawNullifiers.push(
|
|
217
|
+
newNullifier(aliceUTXOsToBeWithdrawn[i], Alice),
|
|
218
|
+
);
|
|
219
|
+
const _withdrawUTXOProof = await smtAlice.generateCircomVerifierProof(
|
|
220
|
+
aliceUTXOsToBeWithdrawn[i].hash,
|
|
221
|
+
root,
|
|
222
|
+
);
|
|
223
|
+
inflatedWithdrawMTPs.push(
|
|
224
|
+
_withdrawUTXOProof.siblings.map((s) => s.bigInt()),
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
// Alice generates inclusion proofs for the UTXOs to be spent
|
|
186
228
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
229
|
+
for (let i = aliceUTXOsToBeWithdrawn.length; i < 10; i++) {
|
|
230
|
+
inflatedWithdrawInputs.push(ZERO_UTXO);
|
|
231
|
+
inflatedWithdrawNullifiers.push(ZERO_UTXO);
|
|
232
|
+
const _zeroProof = await smtAlice.generateCircomVerifierProof(0n, root);
|
|
233
|
+
inflatedWithdrawMTPs.push(_zeroProof.siblings.map((s) => s.bigInt()));
|
|
234
|
+
}
|
|
191
235
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
inflatedWithdrawInputs.push(aliceUTXOsToBeWithdrawn[i]);
|
|
204
|
-
inflatedWithdrawNullifiers.push(
|
|
205
|
-
newNullifier(aliceUTXOsToBeWithdrawn[i], Alice),
|
|
236
|
+
const {
|
|
237
|
+
nullifiers: _withdrawNullifiers,
|
|
238
|
+
outputCommitments: withdrawCommitments,
|
|
239
|
+
encodedProof: withdrawEncodedProof,
|
|
240
|
+
} = await prepareNullifierWithdrawProof(
|
|
241
|
+
Alice,
|
|
242
|
+
inflatedWithdrawInputs,
|
|
243
|
+
inflatedWithdrawNullifiers,
|
|
244
|
+
ZERO_UTXO,
|
|
245
|
+
root.bigInt(),
|
|
246
|
+
inflatedWithdrawMTPs,
|
|
206
247
|
);
|
|
207
|
-
|
|
208
|
-
|
|
248
|
+
|
|
249
|
+
// Alice withdraws her UTXOs to ERC20 tokens
|
|
250
|
+
const tx = await zeto
|
|
251
|
+
.connect(Alice.signer)
|
|
252
|
+
.withdraw(
|
|
253
|
+
3,
|
|
254
|
+
_withdrawNullifiers,
|
|
255
|
+
withdrawCommitments[0],
|
|
256
|
+
encodeToBytesForWithdraw(root.bigInt(), withdrawEncodedProof),
|
|
257
|
+
"0x",
|
|
258
|
+
);
|
|
259
|
+
await tx.wait();
|
|
260
|
+
|
|
261
|
+
// Alice checks her ERC20 balance
|
|
262
|
+
const endingBalance = await erc20.balanceOf(Alice.ethAddress);
|
|
263
|
+
expect(endingBalance - startingBalance).to.be.equal(3);
|
|
264
|
+
}).timeout(60000);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
describe("transfer with verifications by the receiver and the audit authority", function () {
|
|
268
|
+
let event: any;
|
|
269
|
+
let outputUTXOs: UTXO[];
|
|
270
|
+
let outputOwners: User[];
|
|
271
|
+
|
|
272
|
+
it("mint ERC20 tokens to Alice to deposit to Zeto should succeed", async function () {
|
|
273
|
+
const startingBalance = await erc20.balanceOf(Alice.ethAddress);
|
|
274
|
+
const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100);
|
|
275
|
+
await tx.wait();
|
|
276
|
+
const endingBalance = await erc20.balanceOf(Alice.ethAddress);
|
|
277
|
+
expect(endingBalance - startingBalance).to.be.equal(100);
|
|
278
|
+
|
|
279
|
+
const tx1 = await erc20.connect(Alice.signer).approve(zeto.target, 100);
|
|
280
|
+
await tx1.wait();
|
|
281
|
+
|
|
282
|
+
utxo100 = newUTXO(100, Alice);
|
|
283
|
+
const utxo0 = newUTXO(0, Alice);
|
|
284
|
+
const { outputCommitments, encodedProof } = await prepareDepositProof(
|
|
285
|
+
Alice,
|
|
286
|
+
[utxo0, utxo100],
|
|
287
|
+
);
|
|
288
|
+
const tx2 = await zeto
|
|
289
|
+
.connect(Alice.signer)
|
|
290
|
+
.deposit(
|
|
291
|
+
100,
|
|
292
|
+
outputCommitments,
|
|
293
|
+
encodeToBytesForDeposit(encodedProof),
|
|
294
|
+
"0x",
|
|
295
|
+
);
|
|
296
|
+
await tx2.wait();
|
|
297
|
+
|
|
298
|
+
await smtAlice.add(utxo100.hash, utxo100.hash);
|
|
299
|
+
await smtAlice.add(utxo0.hash, utxo0.hash);
|
|
300
|
+
await smtBob.add(utxo100.hash, utxo100.hash);
|
|
301
|
+
await smtBob.add(utxo0.hash, utxo0.hash);
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it("mint to Alice and transfer UTXOs honestly to Bob should succeed", async function () {
|
|
305
|
+
const startingBalance = await erc20.balanceOf(Alice.ethAddress);
|
|
306
|
+
// The authority mints a new UTXO and assigns it to Alice
|
|
307
|
+
utxo1 = newUTXO(10, Alice);
|
|
308
|
+
utxo2 = newUTXO(20, Alice);
|
|
309
|
+
const result1 = await doMint(zeto, deployer, [utxo1, utxo2]);
|
|
310
|
+
|
|
311
|
+
// check the private mint activity is not exposed in the ERC20 contract
|
|
312
|
+
const afterMintBalance = await erc20.balanceOf(Alice.ethAddress);
|
|
313
|
+
expect(afterMintBalance).to.equal(startingBalance);
|
|
314
|
+
|
|
315
|
+
// Alice locally tracks the UTXOs inside the Sparse Merkle Tree
|
|
316
|
+
// hardhat doesn't have a good way to subscribe to events so we have to parse the Tx result object
|
|
317
|
+
const mintEvents = parseUTXOEvents(zeto, result1);
|
|
318
|
+
const [_utxo1, _utxo2] = mintEvents[0].outputs;
|
|
319
|
+
await smtAlice.add(_utxo1, _utxo1);
|
|
320
|
+
await smtAlice.add(_utxo2, _utxo2);
|
|
321
|
+
let root = await smtAlice.root();
|
|
322
|
+
let onchainRoot = await zeto.getRoot();
|
|
323
|
+
expect(root.string()).to.equal(onchainRoot.toString());
|
|
324
|
+
// Bob also locally tracks the UTXOs inside the Sparse Merkle Tree
|
|
325
|
+
await smtBob.add(_utxo1, _utxo1);
|
|
326
|
+
await smtBob.add(_utxo2, _utxo2);
|
|
327
|
+
|
|
328
|
+
// Alice proposes the output UTXOs for the transfer to Bob
|
|
329
|
+
const _utxo3 = newUTXO(25, Bob);
|
|
330
|
+
utxo4 = newUTXO(5, Alice);
|
|
331
|
+
|
|
332
|
+
// Alice generates the nullifiers for the UTXOs to be spent
|
|
333
|
+
const nullifier1 = newNullifier(utxo1, Alice);
|
|
334
|
+
const nullifier2 = newNullifier(utxo2, Alice);
|
|
335
|
+
|
|
336
|
+
// Alice generates inclusion proofs for the UTXOs to be spent
|
|
337
|
+
const proof1 = await smtAlice.generateCircomVerifierProof(
|
|
338
|
+
utxo1.hash,
|
|
209
339
|
root,
|
|
210
340
|
);
|
|
211
|
-
|
|
212
|
-
|
|
341
|
+
const proof2 = await smtAlice.generateCircomVerifierProof(
|
|
342
|
+
utxo2.hash,
|
|
343
|
+
root,
|
|
213
344
|
);
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
encodedProof: withdrawEncodedProof,
|
|
228
|
-
} = await prepareNullifierWithdrawProof(
|
|
229
|
-
Alice,
|
|
230
|
-
inflatedWithdrawInputs,
|
|
231
|
-
inflatedWithdrawNullifiers,
|
|
232
|
-
ZERO_UTXO,
|
|
233
|
-
root.bigInt(),
|
|
234
|
-
inflatedWithdrawMTPs,
|
|
235
|
-
);
|
|
236
|
-
|
|
237
|
-
// Alice withdraws her UTXOs to ERC20 tokens
|
|
238
|
-
const tx = await zeto
|
|
239
|
-
.connect(Alice.signer)
|
|
240
|
-
.withdraw(
|
|
241
|
-
3,
|
|
242
|
-
_withdrawNullifiers,
|
|
243
|
-
withdrawCommitments[0],
|
|
345
|
+
const merkleProofs = [
|
|
346
|
+
proof1.siblings.map((s) => s.bigInt()),
|
|
347
|
+
proof2.siblings.map((s) => s.bigInt()),
|
|
348
|
+
];
|
|
349
|
+
|
|
350
|
+
// Alice transfers her UTXOs to Bob
|
|
351
|
+
outputUTXOs = [_utxo3, utxo4];
|
|
352
|
+
outputOwners = [Bob, Alice];
|
|
353
|
+
const result2 = await doTransfer(
|
|
354
|
+
Alice,
|
|
355
|
+
[utxo1, utxo2],
|
|
356
|
+
[nullifier1, nullifier2],
|
|
357
|
+
outputUTXOs,
|
|
244
358
|
root.bigInt(),
|
|
245
|
-
|
|
246
|
-
|
|
359
|
+
merkleProofs,
|
|
360
|
+
outputOwners,
|
|
247
361
|
);
|
|
248
|
-
await tx.wait();
|
|
249
|
-
|
|
250
|
-
// Alice checks her ERC20 balance
|
|
251
|
-
const endingBalance = await erc20.balanceOf(Alice.ethAddress);
|
|
252
|
-
expect(endingBalance - startingBalance).to.be.equal(3);
|
|
253
|
-
}).timeout(60000);
|
|
254
|
-
|
|
255
|
-
it("mint ERC20 tokens to Alice to deposit to Zeto should succeed", async function () {
|
|
256
|
-
const startingBalance = await erc20.balanceOf(Alice.ethAddress);
|
|
257
|
-
const tx = await erc20.connect(deployer).mint(Alice.ethAddress, 100);
|
|
258
|
-
await tx.wait();
|
|
259
|
-
const endingBalance = await erc20.balanceOf(Alice.ethAddress);
|
|
260
|
-
expect(endingBalance - startingBalance).to.be.equal(100);
|
|
261
|
-
|
|
262
|
-
const tx1 = await erc20.connect(Alice.signer).approve(zeto.target, 100);
|
|
263
|
-
await tx1.wait();
|
|
264
|
-
|
|
265
|
-
utxo100 = newUTXO(100, Alice);
|
|
266
|
-
const utxo0 = newUTXO(0, Alice);
|
|
267
|
-
const { outputCommitments, encodedProof } = await prepareDepositProof(
|
|
268
|
-
Alice,
|
|
269
|
-
[utxo0, utxo100],
|
|
270
|
-
);
|
|
271
|
-
const tx2 = await zeto
|
|
272
|
-
.connect(Alice.signer)
|
|
273
|
-
.deposit(100, outputCommitments, encodedProof, "0x");
|
|
274
|
-
await tx2.wait();
|
|
275
|
-
|
|
276
|
-
await smtAlice.add(utxo100.hash, utxo100.hash);
|
|
277
|
-
await smtAlice.add(utxo0.hash, utxo0.hash);
|
|
278
|
-
await smtBob.add(utxo100.hash, utxo100.hash);
|
|
279
|
-
await smtBob.add(utxo0.hash, utxo0.hash);
|
|
280
|
-
});
|
|
281
362
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
await smtBob.add(_utxo1, _utxo1);
|
|
304
|
-
await smtBob.add(_utxo2, _utxo2);
|
|
305
|
-
|
|
306
|
-
// Alice proposes the output UTXOs for the transfer to Bob
|
|
307
|
-
const _utxo3 = newUTXO(25, Bob);
|
|
308
|
-
utxo4 = newUTXO(5, Alice);
|
|
309
|
-
|
|
310
|
-
// Alice generates the nullifiers for the UTXOs to be spent
|
|
311
|
-
const nullifier1 = newNullifier(utxo1, Alice);
|
|
312
|
-
const nullifier2 = newNullifier(utxo2, Alice);
|
|
313
|
-
|
|
314
|
-
// Alice generates inclusion proofs for the UTXOs to be spent
|
|
315
|
-
const proof1 = await smtAlice.generateCircomVerifierProof(utxo1.hash, root);
|
|
316
|
-
const proof2 = await smtAlice.generateCircomVerifierProof(utxo2.hash, root);
|
|
317
|
-
const merkleProofs = [
|
|
318
|
-
proof1.siblings.map((s) => s.bigInt()),
|
|
319
|
-
proof2.siblings.map((s) => s.bigInt()),
|
|
320
|
-
];
|
|
321
|
-
|
|
322
|
-
// Alice transfers her UTXOs to Bob
|
|
323
|
-
const result2 = await doTransfer(
|
|
324
|
-
Alice,
|
|
325
|
-
[utxo1, utxo2],
|
|
326
|
-
[nullifier1, nullifier2],
|
|
327
|
-
[_utxo3, utxo4],
|
|
328
|
-
root.bigInt(),
|
|
329
|
-
merkleProofs,
|
|
330
|
-
[Bob, Alice],
|
|
331
|
-
);
|
|
363
|
+
// check the private transfer activity is not exposed in the ERC20 contract
|
|
364
|
+
const afterTransferBalance = await erc20.balanceOf(Alice.ethAddress);
|
|
365
|
+
expect(afterTransferBalance).to.equal(startingBalance);
|
|
366
|
+
|
|
367
|
+
// Alice locally tracks the UTXOs inside the Sparse Merkle Tree
|
|
368
|
+
await smtAlice.add(_utxo3.hash, _utxo3.hash);
|
|
369
|
+
await smtAlice.add(utxo4.hash, utxo4.hash);
|
|
370
|
+
root = await smtAlice.root();
|
|
371
|
+
onchainRoot = await zeto.getRoot();
|
|
372
|
+
expect(root.string()).to.equal(onchainRoot.toString());
|
|
373
|
+
|
|
374
|
+
// Bob locally tracks the UTXOs inside the Sparse Merkle Tree
|
|
375
|
+
// Bob parses the UTXOs from the onchain event
|
|
376
|
+
const signerAddress = await Alice.signer.getAddress();
|
|
377
|
+
const events = parseUTXOEvents(zeto, result2.txResult!);
|
|
378
|
+
event = events[0];
|
|
379
|
+
expect(event.submitter).to.equal(signerAddress);
|
|
380
|
+
expect(event.inputs).to.deep.equal([nullifier1.hash, nullifier2.hash]);
|
|
381
|
+
expect(event.outputs).to.deep.equal([_utxo3.hash, utxo4.hash]);
|
|
382
|
+
await smtBob.add(event.outputs[0], event.outputs[0]);
|
|
383
|
+
await smtBob.add(event.outputs[1], event.outputs[1]);
|
|
332
384
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
385
|
+
// Bob uses the information received from Alice to reconstruct the UTXO sent to him
|
|
386
|
+
const receivedValue = _utxo3.value!;
|
|
387
|
+
const receivedSalt = _utxo3.salt;
|
|
388
|
+
const incomingUTXOs: any = event.outputs;
|
|
389
|
+
const hash = Poseidon.poseidon4([
|
|
390
|
+
BigInt(receivedValue),
|
|
391
|
+
receivedSalt,
|
|
392
|
+
Bob.babyJubPublicKey[0],
|
|
393
|
+
Bob.babyJubPublicKey[1],
|
|
394
|
+
]);
|
|
395
|
+
expect(incomingUTXOs[0]).to.equal(hash);
|
|
396
|
+
|
|
397
|
+
// Bob uses the decrypted values to construct the UTXO received from the transaction
|
|
398
|
+
utxo3 = newUTXO(receivedValue, Bob, receivedSalt);
|
|
399
|
+
}).timeout(600000);
|
|
400
|
+
|
|
401
|
+
it("The audit authority can decrypt the encrypted values in the transfer event", async function () {
|
|
402
|
+
// The audit authority can decrypt the encrypted values in the transfer event
|
|
403
|
+
const encapsulatedSharedSecret = event.encapsulatedSharedSecret;
|
|
404
|
+
const cBytes = recoverMlKemCiphertextBytes(encapsulatedSharedSecret);
|
|
405
|
+
// the receiver can decap the ciphertext, and recover the shared secret
|
|
406
|
+
// using the mlkem ciphertext and the receiver's private key
|
|
407
|
+
const receiver = new MlKem512();
|
|
408
|
+
const ssReceiver = await receiver.decap(
|
|
409
|
+
new Uint8Array(cBytes),
|
|
410
|
+
new Uint8Array(testKeyPair.sk),
|
|
411
|
+
);
|
|
412
|
+
// corresponding to the logic in the circuit "pubkey.circom", we derive the symmetric key
|
|
413
|
+
// from the shared secret
|
|
414
|
+
expect(ssReceiver.length).to.equal(32);
|
|
415
|
+
const recoveredKey = publicKeyFromSeed(ssReceiver);
|
|
416
|
+
|
|
417
|
+
const encryptedValues = event.encryptedValues;
|
|
418
|
+
const encryptionNonce = event.encryptionNonce;
|
|
419
|
+
expect(encryptedValues.length).to.equal(16);
|
|
420
|
+
|
|
421
|
+
let plainText = poseidonDecrypt(
|
|
422
|
+
encryptedValues,
|
|
423
|
+
recoveredKey,
|
|
424
|
+
encryptionNonce,
|
|
425
|
+
14,
|
|
426
|
+
);
|
|
427
|
+
expect(plainText[0]).to.equal(Alice.babyJubPublicKey[0]);
|
|
428
|
+
expect(plainText[1]).to.equal(Alice.babyJubPublicKey[1]);
|
|
429
|
+
expect(plainText[2]).to.equal(BigInt(utxo1.value!));
|
|
430
|
+
expect(plainText[3]).to.equal(utxo1.salt!);
|
|
431
|
+
});
|
|
432
|
+
});
|
|
369
433
|
|
|
370
434
|
// describe("lock() tests", function () {
|
|
371
435
|
// let lockedUtxo1: UTXO;
|
|
@@ -539,7 +603,9 @@ describe("Zeto based fungible token with anonymity using nullifiers with Kyber e
|
|
|
539
603
|
) {
|
|
540
604
|
let nullifiers: BigNumberish[];
|
|
541
605
|
let outputCommitments: BigNumberish[];
|
|
542
|
-
let
|
|
606
|
+
let encryptionNonce: BigNumberish;
|
|
607
|
+
let outputsCiphertext: BigNumberish[];
|
|
608
|
+
let encapsulatedSharedSecret: BigNumberish[];
|
|
543
609
|
let encodedProof: any;
|
|
544
610
|
const circuitToUse = lockDelegate
|
|
545
611
|
? circuitForLocked
|
|
@@ -568,14 +634,18 @@ describe("Zeto based fungible token with anonymity using nullifiers with Kyber e
|
|
|
568
634
|
) as BigNumberish[];
|
|
569
635
|
outputCommitments = result.outputCommitments;
|
|
570
636
|
encodedProof = result.encodedProof;
|
|
571
|
-
|
|
637
|
+
encryptionNonce = result.encryptionNonce;
|
|
638
|
+
outputsCiphertext = result.outputsCiphertext;
|
|
639
|
+
encapsulatedSharedSecret = result.encapsulatedSharedSecret;
|
|
572
640
|
|
|
573
641
|
const txResult = await sendTx(
|
|
574
642
|
signer,
|
|
575
643
|
nullifiers,
|
|
576
644
|
outputCommitments,
|
|
577
645
|
root,
|
|
578
|
-
|
|
646
|
+
encryptionNonce,
|
|
647
|
+
outputsCiphertext,
|
|
648
|
+
encapsulatedSharedSecret,
|
|
579
649
|
encodedProof,
|
|
580
650
|
lockDelegate !== undefined,
|
|
581
651
|
);
|
|
@@ -595,33 +665,34 @@ describe("Zeto based fungible token with anonymity using nullifiers with Kyber e
|
|
|
595
665
|
nullifiers: BigNumberish[],
|
|
596
666
|
outputCommitments: BigNumberish[],
|
|
597
667
|
root: BigNumberish,
|
|
598
|
-
|
|
668
|
+
encryptionNonce: BigNumberish,
|
|
669
|
+
outputsCiphertext: BigNumberish[],
|
|
670
|
+
encapsulatedSharedSecret: BigNumberish[],
|
|
599
671
|
encodedProof: any,
|
|
600
672
|
isLocked: boolean = false,
|
|
601
673
|
) {
|
|
602
|
-
const buff = Buffer.alloc(ciphertext.length);
|
|
603
|
-
for (let i = 0; i < ciphertext.length; i++) {
|
|
604
|
-
buff.writeUInt8(Number(ciphertext[i]), i);
|
|
605
|
-
}
|
|
606
|
-
const ciphertextHex = "0x" + buff.toString("hex");
|
|
607
|
-
|
|
608
674
|
const startTx = Date.now();
|
|
609
675
|
let tx: any;
|
|
676
|
+
const proof = encodeToBytes(
|
|
677
|
+
root,
|
|
678
|
+
encryptionNonce,
|
|
679
|
+
outputsCiphertext,
|
|
680
|
+
encapsulatedSharedSecret,
|
|
681
|
+
encodedProof,
|
|
682
|
+
);
|
|
610
683
|
if (!isLocked) {
|
|
611
684
|
tx = await zeto.connect(signer.signer).transfer(
|
|
612
685
|
nullifiers.filter((ic) => ic !== 0n), // trim off empty utxo hashes to check padding logic for batching works
|
|
613
686
|
outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works
|
|
614
|
-
|
|
615
|
-
ciphertextHex,
|
|
616
|
-
encodedProof,
|
|
687
|
+
proof,
|
|
617
688
|
"0x",
|
|
618
689
|
);
|
|
619
690
|
} else {
|
|
620
691
|
tx = await zeto.connect(signer.signer).transferLocked(
|
|
621
692
|
nullifiers.filter((ic) => ic !== 0n), // trim off empty utxo hashes to check padding logic for batching works
|
|
693
|
+
[],
|
|
622
694
|
outputCommitments.filter((oc) => oc !== 0n), // trim off empty utxo hashes to check padding logic for batching works
|
|
623
|
-
|
|
624
|
-
encodedProof,
|
|
695
|
+
proof,
|
|
625
696
|
"0x",
|
|
626
697
|
);
|
|
627
698
|
}
|
|
@@ -662,25 +733,9 @@ async function prepareProof(
|
|
|
662
733
|
(owner) => owner.babyJubPublicKey,
|
|
663
734
|
) as BigNumberish[][];
|
|
664
735
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
const
|
|
668
|
-
1665, 1665, 0, 1665, 0, 1665, 1665, 0, 1665, 0, 0, 1665, 1665, 1665, 1665,
|
|
669
|
-
0, 0, 1665, 0, 0, 0, 1665, 1665, 0, 1665, 0, 1665, 0, 0, 1665, 1665, 0, 0,
|
|
670
|
-
1665, 0, 0, 1665, 1665, 1665, 0, 0, 0, 0, 0, 0, 1665, 0, 0, 1665, 0, 0,
|
|
671
|
-
1665, 0, 1665, 1665, 0, 1665, 1665, 0, 0, 1665, 1665, 1665, 0, 0, 0, 0, 0,
|
|
672
|
-
0, 1665, 0, 0, 1665, 1665, 0, 0, 0, 1665, 1665, 0, 1665, 1665, 1665, 1665,
|
|
673
|
-
0, 1665, 1665, 0, 1665, 1665, 1665, 1665, 0, 1665, 1665, 0, 0, 0, 1665,
|
|
674
|
-
1665, 0, 1665, 1665, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
675
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
676
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
677
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
678
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
679
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
680
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
681
|
-
];
|
|
682
|
-
|
|
683
|
-
const randomness = randomBytesAsDigitArray(32);
|
|
736
|
+
const randomness = crypto.randomBytes(32);
|
|
737
|
+
const r = bytesToBits(randomness);
|
|
738
|
+
const encryptionNonce = newEncryptionNonce();
|
|
684
739
|
const startWitnessCalculation = Date.now();
|
|
685
740
|
const inputObj: any = {
|
|
686
741
|
nullifiers,
|
|
@@ -695,22 +750,13 @@ async function prepareProof(
|
|
|
695
750
|
outputValues,
|
|
696
751
|
outputSalts: outputs.map((output) => output.salt || 0n),
|
|
697
752
|
outputOwnerPublicKeys,
|
|
698
|
-
randomness,
|
|
699
|
-
|
|
753
|
+
randomness: r,
|
|
754
|
+
encryptionNonce,
|
|
700
755
|
};
|
|
701
756
|
if (lockDelegate) {
|
|
702
757
|
inputObj["lockDelegate"] = ethers.toBigInt(lockDelegate);
|
|
703
758
|
}
|
|
704
759
|
|
|
705
|
-
// first call the calculateWitness function which returns
|
|
706
|
-
// the witness as an object, in order to get the ciphertext
|
|
707
|
-
const witnessObj = await circuit.calculateWitness(inputObj, true);
|
|
708
|
-
const circuitName =
|
|
709
|
-
inputs.length > 2
|
|
710
|
-
? "anon_nullifier_qurrency_batch"
|
|
711
|
-
: "anon_nullifier_qurrency";
|
|
712
|
-
const ciphertext = getKyberCipherText(witnessObj, circuitName);
|
|
713
|
-
|
|
714
760
|
const witness = await circuit.calculateWTNSBin(inputObj, true);
|
|
715
761
|
const timeWithnessCalculation = Date.now() - startWitnessCalculation;
|
|
716
762
|
|
|
@@ -721,6 +767,10 @@ async function prepareProof(
|
|
|
721
767
|
)) as { proof: BigNumberish[]; publicSignals: BigNumberish[] };
|
|
722
768
|
const timeProofGeneration = Date.now() - startProofGeneration;
|
|
723
769
|
|
|
770
|
+
const length = outputCommitments.length > 2 ? 64 : 16;
|
|
771
|
+
const encapsulatedSharedSecret = publicSignals.slice(0, 25);
|
|
772
|
+
const outputsCiphertext = publicSignals.slice(25, 25 + length);
|
|
773
|
+
|
|
724
774
|
console.log(
|
|
725
775
|
`Witness calculation time: ${timeWithnessCalculation}ms. Proof generation time: ${timeProofGeneration}ms.`,
|
|
726
776
|
);
|
|
@@ -730,10 +780,108 @@ async function prepareProof(
|
|
|
730
780
|
inputCommitments,
|
|
731
781
|
outputCommitments,
|
|
732
782
|
encodedProof,
|
|
733
|
-
|
|
783
|
+
encryptionNonce,
|
|
784
|
+
outputsCiphertext,
|
|
785
|
+
encapsulatedSharedSecret,
|
|
734
786
|
};
|
|
735
787
|
}
|
|
736
788
|
|
|
789
|
+
function encodeToBytes(
|
|
790
|
+
root: any,
|
|
791
|
+
encryptionNonce: any,
|
|
792
|
+
encryptedValues: any,
|
|
793
|
+
encapsulatedSharedSecret: any,
|
|
794
|
+
proof: any,
|
|
795
|
+
) {
|
|
796
|
+
return new AbiCoder().encode(
|
|
797
|
+
[
|
|
798
|
+
"uint256 root",
|
|
799
|
+
"uint256 encryptionNonce",
|
|
800
|
+
"uint256[] encryptedValues",
|
|
801
|
+
"uint256[25] encapsulatedSharedSecret",
|
|
802
|
+
"tuple(uint256[2] pA, uint256[2][2] pB, uint256[2] pC)",
|
|
803
|
+
],
|
|
804
|
+
[root, encryptionNonce, encryptedValues, encapsulatedSharedSecret, proof],
|
|
805
|
+
);
|
|
806
|
+
}
|
|
807
|
+
|
|
737
808
|
module.exports = {
|
|
738
809
|
prepareProof,
|
|
739
810
|
};
|
|
811
|
+
|
|
812
|
+
describe("encoding test", function () {
|
|
813
|
+
it("should encode the proof correctly", function () {
|
|
814
|
+
const proof = encodeToBytes(
|
|
815
|
+
2185945469173281998543795100239332646380217964035682609677494700854501229435n, // root
|
|
816
|
+
275390031262136596949503856056006740272n, // encryptionNonce
|
|
817
|
+
[
|
|
818
|
+
13715591515004609688233255520139366968347229879226987447392926581641315410365n,
|
|
819
|
+
12225040792969183937477801836359093706337068545022080407734986798228486880459n,
|
|
820
|
+
13011843324002630531326495134664720300521666217887617808427836215465667928692n,
|
|
821
|
+
19856495997717871827317781271670963924363352390548953270211310380014460390334n,
|
|
822
|
+
10604073410745110687091665574819448938663378994798073962869528739665232014421n,
|
|
823
|
+
4435178295556424656324960575659262079598790982598728711009699368000570989336n,
|
|
824
|
+
4933836950213445512336611933470005675174051517599168194217630597808234407822n,
|
|
825
|
+
4214225226975003066728797596550538286539095487779015468026667054118086708667n,
|
|
826
|
+
5024576208387901066062709265269626900637589025955141460411534463069531901891n,
|
|
827
|
+
703973997727387811759298044568434494690485054474094541129706149430879630884n,
|
|
828
|
+
14507146421329688672993934183526210401463938041762433569084930573959882425326n,
|
|
829
|
+
14012438595855534325416420918184230363976318221634661889145359708752658755207n,
|
|
830
|
+
8754932719802650626162524741856226517982355523480941833310179558554675571452n,
|
|
831
|
+
14352194087842591409364852158942330879045556303811584255462682741598400114507n,
|
|
832
|
+
930427648599696993608342770250501205956137552217414712238549287557300544904n,
|
|
833
|
+
21394278059543057034208592185307596281934697437416095108050934185203559222712n,
|
|
834
|
+
], // encryptedValues
|
|
835
|
+
[
|
|
836
|
+
288126790059318346139824202713129652229348576996464001952408714015513463993n,
|
|
837
|
+
237407267603824073552608687931930991963999394428366555167539009382905388537n,
|
|
838
|
+
114764209448275499414271899760871155095571139138912032913196740291197144696n,
|
|
839
|
+
436995396164250682578369063006271991698559693192849862783563046924655949369n,
|
|
840
|
+
240591981726723986881909418996515793567853950883197759098846148099856667367n,
|
|
841
|
+
423589442784611103138623838389086946618384967919367390938087104637737788216n,
|
|
842
|
+
145462886897996314213326681029317456734837820615410128121849599895343382705n,
|
|
843
|
+
389932051522827200062535000655062077695415252609124727680940113692289747665n,
|
|
844
|
+
243675801576408693743852761736871686197324939358886873348705983761231779940n,
|
|
845
|
+
87939610206601698004485673787337315272887533489281795861381157598783844367n,
|
|
846
|
+
11014683993036861793302780310552914749438060162054842543618251146378375526n,
|
|
847
|
+
111614391393324468932660651857272851218377641294817341376507043259517434344n,
|
|
848
|
+
435707583091444288657484999813927778656294844261499799508340404768617948216n,
|
|
849
|
+
256449006844324353610179235842731870600460006591548128221647489805788554815n,
|
|
850
|
+
418634767833052917835192672729088145298440004524459401783387363547257320986n,
|
|
851
|
+
103610780261386527074710704895000705809005120944489697847370877795317539063n,
|
|
852
|
+
127627753495450202619315508879418050934338498775659516820680842878935424334n,
|
|
853
|
+
46384251041970312953604802331459565502839961155990167432349041542488773332n,
|
|
854
|
+
59279347778101058820051248467497773070279609242238499827597758128700405210n,
|
|
855
|
+
401076038589967842843270755588760950994197089793842470053926063226777655114n,
|
|
856
|
+
437055888722697362599388401811652409455332242376917929776279980055423605099n,
|
|
857
|
+
382219076120208743166804616016001837790918283786525158013655719261656086690n,
|
|
858
|
+
412218952494890119014684951992443508961594053505588316664570435208291787650n,
|
|
859
|
+
362621741079924474296483570929701950283961620929630348838376271651154374200n,
|
|
860
|
+
3987927141671093050828825554766656132900595007161822411291n,
|
|
861
|
+
], // encapsulatedSharedSecret
|
|
862
|
+
[
|
|
863
|
+
[
|
|
864
|
+
549287572509790359685716132453355766491815426087194122700979105235739473130n,
|
|
865
|
+
15298123219329538989607681043913355391761570794419278588736377843648111671159n,
|
|
866
|
+
],
|
|
867
|
+
[
|
|
868
|
+
[
|
|
869
|
+
9440038941921968905445133266072988463231863413680655261260818687531566458108n,
|
|
870
|
+
2207698080461885696867541047133088519732009024182544199097906381032204346428n,
|
|
871
|
+
],
|
|
872
|
+
[
|
|
873
|
+
6577776031418234473059205922833530313720519798861738979049253341371055729708n,
|
|
874
|
+
11968330310582097325419116485228879165470205732203147205908830680466052312773n,
|
|
875
|
+
],
|
|
876
|
+
],
|
|
877
|
+
[
|
|
878
|
+
3106716200655790292773114695208727957822992667898408535199502363885960505738n,
|
|
879
|
+
20085498771862832325662320796990160779029948991590746485323346020588480720567n,
|
|
880
|
+
],
|
|
881
|
+
], // proof
|
|
882
|
+
);
|
|
883
|
+
expect(proof).to.equal(
|
|
884
|
+
"0x04d53387cb12538667ced7ce8b1846dbdff33fc38784b2604a08125446b4c37b00000000000000000000000000000000cf2e30d59acb9763a0c1626c5e6a0930000000000000000000000000000000000000000000000000000000000000048000a312f09e6066c7aebc7468b5cf1aafa3151c298175dbd658d5acba17e74cb900865e24f8de2a91bdfaaaa40792466eab7b9767f8e8fa1903b80825f3c99df90040f4491d9acb71301b8f394d01b5920669cedd5af8da172226d505d1740e7800f754a41cdcdf6a81a97771a25a885d09c64b8464f53d4b0e0292c8aa9a763900882b9495929d332f40dde4a0ff1b9e162cc2f802a603faabcff12074fc12e700efbe3daa599448fdc6c90e7919ba04a86b0c6accdb304e9f325aafc1ce63380052543e5908a1d6165f2f82e3136c2c95e9e185e2aec7ddf95139401b6ac0b100dcb197a37a65273cf5115a71ab6e24e0a67227303dd03600e34b46d3694ad10089ea65d1df01235226c5985d0e8853f7ba53d641a12948e5a98141aafa18640031c5a56e40a3988cde8b4a2d3baa8a42813226e602951754c3668f8627b00f00063bed560dd4187b7a6ad7e31858dbbf2cf8583c7e1a883124098067387166003f2be7dee087211d4ad509d7385c4cd293052ab7050d6e0ecb224d604af9e800f69a0c789609111b4e125f60324eeb682ee8216ffc19ffec929a77bc2264380091251e55d2b6b1e3b64f803ffac769bba390eee196c95dd718e7d0cb0aa63f00ecf05a8eb06e090213be5b5fd338dbacfc6d18d835dfa7719d763a47b1361a003aa4416f29bc3291dae5fa6dd98e44dc40beef68c6b15e21fb1b15cb7760f700483c187b8e203bf7433a3316ccc9aad2fdcd6aafbb328bf79bf7a2ec9cdd4e001a40a77e1af8c8ac79aa167d1c519a097c76158230b125b9ddd2830905d2d400218d0936c05cae6f1f92d1b5ac105573fd70b2a5f3cb0ac4a0bc6fcab635da00e3004117a1cb79135f18f5de7019a2828ee3f41b1f2b5adf57e891fb16574a00f75d67e80cb479cf92b2ad3c521830c41d1721130d801f6b58f4ffc277d96b00d8540d7b056af7eec2368efb244c68fb684803562bbd14321c2274e33878a200e94ec2bd8059bda202a769b7312c5c194e418cc0eb9b0a27e56fbc627ba38200cd3c93ec8281b7fad9dd5183dd892f98b9b7beae868eb6f8f17d806af32e380000000000000000a2a3e6ee40deb77d25dc4473312ff54bc727758efd4cfa1b0136e2c06cabb082011e47ab176222198f0fa0885e8046650f31aeab65a9f4ea21d26e4f641fe77a3cb7215d4b3c9cec9a1f7148edc75c6b2b9390636f55777714dedf690fa175f2f4a8f9298cead433608482fa3251c9c4df1be18156bf64fc04e18348fd35af148608f6dfccdf42139dd1278a947b119993784074aaf5243c0e8ae3a922c4523d0207bd28e658e37add64feeefcadfcd4feae9b93ceb3ec2c1a75d5bc03c3417b3db41c75a87b563433c27d11efd64439837b0994fcb76ec506de56cc662d32548f11121f83941d43b37a6bdce0c5edf070969dc971c5298a2c67fd4bd7994866b73163e4136ee3d0f6662a529f73c569f8dd606ae7a96eb700000000000000000000000000000000000000000000000000000000000000101e52bfec13e500dee652a10feec8bd596cd62472ad5430ff9b4f3c944780e1bd1b0720bd0450e3d549636d5f23142b50b485f4f4c17323a7809dcf5a1309fccb1cc4713ce4478327e0e5be00dab93879dd260a0d8e2f8f2f905b209d189f22742be660e2dbbd0509b1da03413b66d393cbf348cf51fc2b0fdf7ebf08c876cbbe1771b15f2cbd88f6be76a81e83c776e188643bbafb6dedf729d0ccb0f9842c5509ce38d221fac0e2d5b3ecb54fbdaa45f47a74ed36962b8e882210b132331b180ae873e79f48e142c4ce247a664f22bb5a05872d7c56e5fdb7566f7eecf7a78e09512abd52a1902b33ffdeb72f0fd9b957e52d7b4a30604c47e32471ce2d0dbb0b1bcf31c47aef99da156d515d7b0a7ed4f898bb3580b71f8284de17a70f8fc3018e6f66d2ac7be681123be5cf9f29bdc218250aea1fa2cc20c8905b8170b6242012c0ff596494029442db4331e3e715487b650b39c4342c0c0b34a4eb7543ee1efac25a423edb6db7187e692f0c7d3edd5753d359edd2f35e72ffa4d716ee87135b1dc6ee74854c498020893eeea7047c3dadaf2ff08196f557bdee8289eafc1fbb0dd1dd670fec48828f7aa41bcde200551317cfc3132cdb4e1682a5dd6f4b020e9a7791ce7135d2d847313b73c26cb48ca320f164b12826752d175668e5882f4cbb75ae037a782db136d5e3588575122a44f059298c7148f1482fd89acdb8",
|
|
885
|
+
);
|
|
886
|
+
});
|
|
887
|
+
});
|