Skip to content

Commit b11a608

Browse files
committed
Increase the size of the deposit output to 2 for better tracking-resistance
Signed-off-by: Jim Zhang <[email protected]>
1 parent 9855999 commit b11a608

21 files changed

+192
-156
lines changed

solidity/contracts/lib/verifier_check_hashes_value.sol

+14-7
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,17 @@ contract Groth16Verifier_CheckHashesValue {
4343
uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
4444

4545

46-
uint256 constant IC0x = 7451946452627654831087368244416850811848640051585835431774006564787696394579;
47-
uint256 constant IC0y = 3335938186741695161920937664249081252546904250712465973121885140080729804559;
46+
uint256 constant IC0x = 17792762022125287046321768098607171320071618631211367966788587488825455404458;
47+
uint256 constant IC0y = 11155528019403985287117957011181683282276980330791900414761420530701336492839;
4848

49-
uint256 constant IC1x = 4825167184845404163337490360685409593368334234867416547655377178016060612776;
50-
uint256 constant IC1y = 20216917433859335199329194148245717058149862581677751710529776924054717858789;
49+
uint256 constant IC1x = 6717605603646218844646921196814073522173739325926307699116887265970061883098;
50+
uint256 constant IC1y = 516153472147520123255754218210841627924243470206670179828454953236590121912;
5151

52-
uint256 constant IC2x = 15958914812085923571729409913935907268381565403173614269925036163982984629903;
53-
uint256 constant IC2y = 12537821265017874170836131082487633026846634600904134063136842002739226714069;
52+
uint256 constant IC2x = 8087731838810758210112265887449747110390409349987938026778639089761261395232;
53+
uint256 constant IC2y = 19857276812072296411781253738593366602790857251698964067504889225833057563826;
54+
55+
uint256 constant IC3x = 473105502461913999202734899658281137764286492931790885921074401072316990093;
56+
uint256 constant IC3y = 19795449967604900309902005580999588375004713323386672270649013487860620808493;
5457

5558

5659
// Memory data
@@ -59,7 +62,7 @@ contract Groth16Verifier_CheckHashesValue {
5962

6063
uint16 constant pLastMem = 896;
6164

62-
function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[2] calldata _pubSignals) public view returns (bool) {
65+
function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[3] calldata _pubSignals) public view returns (bool) {
6366
assembly {
6467
function checkField(v) {
6568
if iszero(lt(v, r)) {
@@ -107,6 +110,8 @@ contract Groth16Verifier_CheckHashesValue {
107110

108111
g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32)))
109112

113+
g1_mulAccC(_pVk, IC3x, IC3y, calldataload(add(pubSignals, 64)))
114+
110115

111116
// -A
112117
mstore(_pPairing, calldataload(pA))
@@ -166,6 +171,8 @@ contract Groth16Verifier_CheckHashesValue {
166171

167172
checkField(calldataload(add(_pubSignals, 64)))
168173

174+
checkField(calldataload(add(_pubSignals, 96)))
175+
169176

170177
// Validate all evaluations
171178
let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem)

solidity/contracts/lib/zeto_fungible.sol

+4-3
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,16 @@ abstract contract ZetoFungible is OwnableUpgradeable {
4545

4646
function _deposit(
4747
uint256 amount,
48-
uint256 utxo,
48+
uint256[] memory outputs,
4949
Commonlib.Proof calldata proof
5050
) public virtual {
5151
// verifies that the output UTXOs match the claimed value
5252
// to be deposited
5353
// construct the public inputs
54-
uint256[2] memory publicInputs;
54+
uint256[3] memory publicInputs;
5555
publicInputs[0] = amount;
56-
publicInputs[1] = utxo;
56+
publicInputs[1] = outputs[0];
57+
publicInputs[2] = outputs[1];
5758

5859
// Check the proof
5960
require(

solidity/contracts/zeto_anon.sol

+3-5
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,12 @@ contract Zeto_Anon is IZeto, ZetoBase, ZetoFungibleWithdraw, UUPSUpgradeable {
170170

171171
function deposit(
172172
uint256 amount,
173-
uint256 utxo,
173+
uint256[] memory outputs,
174174
Commonlib.Proof calldata proof,
175175
bytes calldata data
176176
) public {
177-
_deposit(amount, utxo, proof);
178-
uint256[] memory utxos = new uint256[](1);
179-
utxos[0] = utxo;
180-
_mint(utxos, data);
177+
_deposit(amount, outputs, proof);
178+
_mint(outputs, data);
181179
}
182180

183181
function withdraw(

solidity/contracts/zeto_anon_enc.sol

+3-5
Original file line numberDiff line numberDiff line change
@@ -208,14 +208,12 @@ contract Zeto_AnonEnc is
208208

209209
function deposit(
210210
uint256 amount,
211-
uint256 utxo,
211+
uint256[] memory outputs,
212212
Commonlib.Proof calldata proof,
213213
bytes calldata data
214214
) public {
215-
_deposit(amount, utxo, proof);
216-
uint256[] memory utxos = new uint256[](1);
217-
utxos[0] = utxo;
218-
_mint(utxos, data);
215+
_deposit(amount, outputs, proof);
216+
_mint(outputs, data);
219217
}
220218

221219
function withdraw(

solidity/contracts/zeto_anon_enc_nullifier.sol

+3-5
Original file line numberDiff line numberDiff line change
@@ -223,14 +223,12 @@ contract Zeto_AnonEncNullifier is
223223

224224
function deposit(
225225
uint256 amount,
226-
uint256 utxo,
226+
uint256[] memory outputs,
227227
Commonlib.Proof calldata proof,
228228
bytes calldata data
229229
) public {
230-
_deposit(amount, utxo, proof);
231-
uint256[] memory utxos = new uint256[](1);
232-
utxos[0] = utxo;
233-
_mint(utxos, data);
230+
_deposit(amount, outputs, proof);
231+
_mint(outputs, data);
234232
}
235233

236234
function withdraw(

solidity/contracts/zeto_anon_enc_nullifier_kyc.sol

+3-5
Original file line numberDiff line numberDiff line change
@@ -238,14 +238,12 @@ contract Zeto_AnonEncNullifierKyc is
238238
// Therefore, token circulation from & to parties that are not in the KYC list is prevented
239239
function deposit(
240240
uint256 amount,
241-
uint256 utxo,
241+
uint256[] memory outputs,
242242
Commonlib.Proof calldata proof,
243243
bytes calldata data
244244
) public {
245-
_deposit(amount, utxo, proof);
246-
uint256[] memory utxos = new uint256[](1);
247-
utxos[0] = utxo;
248-
_mint(utxos, data);
245+
_deposit(amount, outputs, proof);
246+
_mint(outputs, data);
249247
}
250248

251249
function withdraw(

solidity/contracts/zeto_anon_enc_nullifier_non_repudiation.sol

+3-5
Original file line numberDiff line numberDiff line change
@@ -274,14 +274,12 @@ contract Zeto_AnonEncNullifierNonRepudiation is
274274

275275
function deposit(
276276
uint256 amount,
277-
uint256 utxo,
277+
uint256[] memory outputs,
278278
Commonlib.Proof calldata proof,
279279
bytes calldata data
280280
) public {
281-
_deposit(amount, utxo, proof);
282-
uint256[] memory utxos = new uint256[](1);
283-
utxos[0] = utxo;
284-
_mint(utxos, data);
281+
_deposit(amount, outputs, proof);
282+
_mint(outputs, data);
285283
}
286284

287285
function withdraw(

solidity/contracts/zeto_anon_nullifier.sol

+3-5
Original file line numberDiff line numberDiff line change
@@ -192,14 +192,12 @@ contract Zeto_AnonNullifier is
192192

193193
function deposit(
194194
uint256 amount,
195-
uint256 utxo,
195+
uint256[] memory outputs,
196196
Commonlib.Proof calldata proof,
197197
bytes calldata data
198198
) public {
199-
_deposit(amount, utxo, proof);
200-
uint256[] memory utxos = new uint256[](1);
201-
utxos[0] = utxo;
202-
_mint(utxos, data);
199+
_deposit(amount, outputs, proof);
200+
_mint(outputs, data);
203201
}
204202

205203
function withdraw(

solidity/contracts/zeto_anon_nullifier_kyc.sol

+3-5
Original file line numberDiff line numberDiff line change
@@ -202,14 +202,12 @@ contract Zeto_AnonNullifierKyc is
202202

203203
function deposit(
204204
uint256 amount,
205-
uint256 utxo,
205+
uint256[] memory outputs,
206206
Commonlib.Proof calldata proof,
207207
bytes calldata data
208208
) public {
209-
_deposit(amount, utxo, proof);
210-
uint256[] memory utxos = new uint256[](1);
211-
utxos[0] = utxo;
212-
_mint(utxos, data);
209+
_deposit(amount, outputs, proof);
210+
_mint(outputs, data);
213211
}
214212

215213
function withdraw(

solidity/test/utils.ts

+17-7
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,27 @@ export function loadProvingKeys(type: string) {
4242
};
4343
}
4444

45-
export async function prepareDepositProof(signer: User, output: UTXO) {
46-
const outputCommitments: [BigNumberish] = [output.hash] as [BigNumberish];
47-
const outputValues = [BigInt(output.value || 0n)];
48-
const outputOwnerPublicKeys: [[BigNumberish, BigNumberish]] = [
49-
signer.babyJubPublicKey,
50-
] as [[BigNumberish, BigNumberish]];
45+
export async function prepareDepositProof(signer: User, outputs: [UTXO, UTXO]) {
46+
const outputCommitments: [BigNumberish, BigNumberish] = [
47+
outputs[0].hash,
48+
outputs[1].hash,
49+
] as [BigNumberish, BigNumberish];
50+
const outputValues = [
51+
BigInt(outputs[0].value || 0n),
52+
BigInt(outputs[1].value || 0n),
53+
];
54+
const outputOwnerPublicKeys: [
55+
[BigNumberish, BigNumberish],
56+
[BigNumberish, BigNumberish],
57+
] = [signer.babyJubPublicKey, signer.babyJubPublicKey] as [
58+
[BigNumberish, BigNumberish],
59+
[BigNumberish, BigNumberish],
60+
];
5161

5262
const inputObj = {
5363
outputCommitments,
5464
outputValues,
55-
outputSalts: [output.salt],
65+
outputSalts: [outputs[0].salt, outputs[1].salt],
5666
outputOwnerPublicKeys,
5767
};
5868

solidity/test/zeto_anon.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -170,13 +170,14 @@ describe("Zeto based fungible token with anonymity without encryption or nullifi
170170
await tx1.wait();
171171

172172
utxo100 = newUTXO(100, Alice);
173+
const utxo0 = newUTXO(0, Alice);
173174
const { outputCommitments, encodedProof } = await prepareDepositProof(
174175
Alice,
175-
utxo100,
176+
[utxo100, utxo0],
176177
);
177178
const tx2 = await zeto
178179
.connect(Alice.signer)
179-
.deposit(100, outputCommitments[0], encodedProof, "0x");
180+
.deposit(100, outputCommitments, encodedProof, "0x");
180181
await tx2.wait();
181182
});
182183

solidity/test/zeto_anon_enc.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,14 @@ describe("Zeto based fungible token with anonymity and encryption", function ()
191191
await tx1.wait();
192192

193193
utxo100 = newUTXO(100, Alice);
194+
const utxo0 = newUTXO(0, Alice);
194195
const { outputCommitments, encodedProof } = await prepareDepositProof(
195196
Alice,
196-
utxo100,
197+
[utxo100, utxo0],
197198
);
198199
const tx2 = await zeto
199200
.connect(Alice.signer)
200-
.deposit(100, outputCommitments[0], encodedProof, "0x");
201+
.deposit(100, outputCommitments, encodedProof, "0x");
201202
await tx2.wait();
202203
});
203204

solidity/test/zeto_anon_enc_nullifier.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -275,17 +275,20 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
275275
await tx1.wait();
276276

277277
utxo100 = newUTXO(100, Alice);
278+
const utxo0 = newUTXO(0, Alice);
278279
const { outputCommitments, encodedProof } = await prepareDepositProof(
279280
Alice,
280-
utxo100,
281+
[utxo100, utxo0],
281282
);
282283
const tx2 = await zeto
283284
.connect(Alice.signer)
284-
.deposit(100, outputCommitments[0], encodedProof, "0x");
285+
.deposit(100, outputCommitments, encodedProof, "0x");
285286
await tx2.wait();
286287

287288
await smtAlice.add(utxo100.hash, utxo100.hash);
289+
await smtAlice.add(utxo0.hash, utxo0.hash);
288290
await smtBob.add(utxo100.hash, utxo100.hash);
291+
await smtBob.add(utxo0.hash, utxo0.hash);
289292
});
290293

291294
it("mint to Alice and transfer UTXOs honestly to Bob should succeed", async function () {

solidity/test/zeto_anon_enc_nullifier_kyc.ts

+14-4
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
6161
let erc20: any;
6262
let zeto: any;
6363
let utxo100: UTXO;
64+
let utxo0: UTXO;
6465
let utxo1: UTXO;
6566
let utxo2: UTXO;
6667
let utxo3: UTXO;
@@ -336,17 +337,20 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
336337
await tx1.wait();
337338

338339
utxo100 = newUTXO(100, Alice);
340+
utxo0 = newUTXO(0, Alice);
339341
const { outputCommitments, encodedProof } = await prepareDepositProof(
340342
Alice,
341-
utxo100,
343+
[utxo100, utxo0],
342344
);
343345
const tx2 = await zeto
344346
.connect(Alice.signer)
345-
.deposit(100, outputCommitments[0], encodedProof, "0x");
347+
.deposit(100, outputCommitments, encodedProof, "0x");
346348
await tx2.wait();
347349

348350
await smtAlice.add(utxo100.hash, utxo100.hash);
351+
await smtAlice.add(utxo0.hash, utxo0.hash);
349352
await smtBob.add(utxo100.hash, utxo100.hash);
353+
await smtBob.add(utxo0.hash, utxo0.hash);
350354
});
351355

352356
it("mint to Alice and transfer UTXOs honestly to Bob should succeed", async function () {
@@ -576,6 +580,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
576580

577581
describe("unregistered user cases", function () {
578582
let unregisteredUtxo100: UTXO;
583+
let unregisteredUtxo0: UTXO;
579584

580585
it("deposit by an unregistered user should succeed", async function () {
581586
const tx = await erc20
@@ -588,24 +593,28 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
588593
await tx1.wait();
589594

590595
unregisteredUtxo100 = newUTXO(100, unregistered);
596+
unregisteredUtxo0 = newUTXO(0, unregistered);
591597
const { outputCommitments, encodedProof } = await prepareDepositProof(
592598
unregistered,
593-
unregisteredUtxo100,
599+
[unregisteredUtxo100, unregisteredUtxo0],
594600
);
595601
const tx2 = await zeto
596602
.connect(unregistered.signer)
597-
.deposit(100, outputCommitments[0], encodedProof, "0x");
603+
.deposit(100, outputCommitments, encodedProof, "0x");
598604
await tx2.wait();
599605

600606
// Alice tracks the UTXO inside the SMT
601607
await smtAlice.add(unregisteredUtxo100.hash, unregisteredUtxo100.hash);
608+
await smtAlice.add(unregisteredUtxo0.hash, unregisteredUtxo0.hash);
602609
// Bob also locally tracks the UTXOs inside the SMT
603610
await smtBob.add(unregisteredUtxo100.hash, unregisteredUtxo100.hash);
611+
await smtBob.add(unregisteredUtxo0.hash, unregisteredUtxo0.hash);
604612
});
605613

606614
it("transfer from an unregistered user should fail", async function () {
607615
// catch up the local SMT for the unregistered user
608616
await smtUnregistered.add(utxo100.hash, utxo100.hash);
617+
await smtUnregistered.add(utxo0.hash, utxo0.hash);
609618
await smtUnregistered.add(utxo1.hash, utxo1.hash);
610619
await smtUnregistered.add(utxo2.hash, utxo2.hash);
611620
await smtUnregistered.add(_utxo3.hash, _utxo3.hash);
@@ -620,6 +629,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
620629
unregisteredUtxo100.hash,
621630
unregisteredUtxo100.hash,
622631
);
632+
await smtUnregistered.add(unregisteredUtxo0.hash, unregisteredUtxo0.hash);
623633
const utxosRoot = await smtUnregistered.root();
624634

625635
const nullifier = newNullifier(unregisteredUtxo100, unregistered);

solidity/test/zeto_anon_enc_nullifier_non_repudiation.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
5959
let erc20: any;
6060
let zeto: any;
6161
let utxo100: UTXO;
62+
let utxo0: UTXO;
6263
let utxo1: UTXO;
6364
let utxo2: UTXO;
6465
let utxo3: UTXO;
@@ -330,17 +331,20 @@ describe("Zeto based fungible token with anonymity using nullifiers and encrypti
330331
await tx1.wait();
331332

332333
utxo100 = newUTXO(100, Alice);
334+
utxo0 = newUTXO(0, Alice);
333335
const { outputCommitments, encodedProof } = await prepareDepositProof(
334336
Alice,
335-
utxo100,
337+
[utxo100, utxo0],
336338
);
337339
const tx2 = await zeto
338340
.connect(Alice.signer)
339-
.deposit(100, outputCommitments[0], encodedProof, "0x");
341+
.deposit(100, outputCommitments, encodedProof, "0x");
340342
await tx2.wait();
341343

342344
await smtAlice.add(utxo100.hash, utxo100.hash);
345+
await smtAlice.add(utxo0.hash, utxo0.hash);
343346
await smtBob.add(utxo100.hash, utxo100.hash);
347+
await smtBob.add(utxo0.hash, utxo0.hash);
344348
});
345349

346350
it("mint to Alice and transfer UTXOs honestly to Bob should succeed and verifiable by the regulator", async function () {

0 commit comments

Comments
 (0)