Skip to content

Commit

Permalink
prettify
Browse files Browse the repository at this point in the history
Signed-off-by: Chengxuan Xing <chengxuan.xing@kaleido.io>
  • Loading branch information
Chengxuan committed Nov 5, 2024
1 parent a571123 commit 17c069f
Showing 1 changed file with 135 additions and 40 deletions.
175 changes: 135 additions & 40 deletions zkp/js/test/anon_nullifier.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.

const { expect } = require('chai');
const { join } = require('path');
const { wasm: wasm_tester } = require('circom_tester');
const { genKeypair, formatPrivKeyForBabyJub } = require('maci-crypto');
const { Merkletree, InMemoryDB, str2Bytes, ZERO_HASH } = require('@iden3/js-merkletree');
const { Poseidon, newSalt } = require('../index.js');
const { expect } = require("chai");
const { join } = require("path");
const { wasm: wasm_tester } = require("circom_tester");
const { genKeypair, formatPrivKeyForBabyJub } = require("maci-crypto");
const {
Merkletree,
InMemoryDB,
str2Bytes,
ZERO_HASH,
} = require("@iden3/js-merkletree");
const { Poseidon, newSalt } = require("../index.js");

const SMT_HEIGHT = 64;
const poseidonHash = Poseidon.poseidon4;
const poseidonHash3 = Poseidon.poseidon3;

describe('main circuit tests for Zeto fungible tokens with anonymity using nullifiers and without encryption', () => {
describe("main circuit tests for Zeto fungible tokens with anonymity using nullifiers and without encryption", () => {
let circuit, smtAlice, smtBob;

const Alice = {};
Expand All @@ -35,7 +40,9 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli
before(async function () {
this.timeout(60000);

circuit = await wasm_tester(join(__dirname, '../../circuits/anon_nullifier.circom'));
circuit = await wasm_tester(
join(__dirname, "../../circuits/anon_nullifier.circom"),
);

let keypair = genKeypair();
Alice.privKey = keypair.privKey;
Expand All @@ -47,43 +54,73 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli
Bob.pubKey = keypair.pubKey;

// initialize the local storage for Alice to manage her UTXOs in the Spart Merkle Tree
const storage1 = new InMemoryDB(str2Bytes(''));
const storage1 = new InMemoryDB(str2Bytes(""));
smtAlice = new Merkletree(storage1, true, SMT_HEIGHT);

// initialize the local storage for Bob to manage his UTXOs in the Spart Merkle Tree
const storage2 = new InMemoryDB(str2Bytes(''));
const storage2 = new InMemoryDB(str2Bytes(""));
smtBob = new Merkletree(storage2, true, SMT_HEIGHT);
});

it('should succeed for valid witness', async () => {
it("should succeed for valid witness", async () => {
const inputValues = [32, 40];
const outputValues = [20, 52];

// create two input UTXOs, each has their own salt, but same owner
const salt1 = newSalt();
const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]);
const input1 = poseidonHash([
BigInt(inputValues[0]),
salt1,
...Alice.pubKey,
]);
const salt2 = newSalt();
const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...Alice.pubKey]);
const input2 = poseidonHash([
BigInt(inputValues[1]),
salt2,
...Alice.pubKey,
]);
const inputCommitments = [input1, input2];

// create the nullifiers for the inputs
const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]);
const nullifier2 = poseidonHash3([BigInt(inputValues[1]), salt2, senderPrivateKey]);
const nullifier1 = poseidonHash3([
BigInt(inputValues[0]),
salt1,
senderPrivateKey,
]);
const nullifier2 = poseidonHash3([
BigInt(inputValues[1]),
salt2,
senderPrivateKey,
]);
const nullifiers = [nullifier1, nullifier2];

// calculate the root of the SMT
await smtAlice.add(input1, input1);
await smtAlice.add(input2, input2);

// generate the merkle proof for the inputs
const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH);
const proof2 = await smtAlice.generateCircomVerifierProof(input2, ZERO_HASH);
const proof1 = await smtAlice.generateCircomVerifierProof(
input1,
ZERO_HASH,
);
const proof2 = await smtAlice.generateCircomVerifierProof(
input2,
ZERO_HASH,
);

// create two output UTXOs, they share the same salt, and different owner
const salt3 = newSalt();
const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Bob.pubKey]);
const output1 = poseidonHash([
BigInt(outputValues[0]),
salt3,
...Bob.pubKey,
]);
const salt4 = newSalt();
const output2 = poseidonHash([BigInt(outputValues[1]), salt4, ...Alice.pubKey]);
const output2 = poseidonHash([
BigInt(outputValues[1]),
salt4,
...Alice.pubKey,
]);
const outputCommitments = [output1, output2];

const witness = await circuit.calculateWitness(
Expand All @@ -94,14 +131,17 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli
inputSalts: [salt1, salt2],
inputOwnerPrivateKey: senderPrivateKey,
root: proof1.root.bigInt(),
merkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())],
merkleProof: [
proof1.siblings.map((s) => s.bigInt()),
proof2.siblings.map((s) => s.bigInt()),
],
enabled: [1, 1],
outputCommitments,
outputValues,
outputSalts: [salt3, salt4],
outputOwnerPublicKeys: [Bob.pubKey, Alice.pubKey],
},
true
true,
);

// console.log('witness', witness.slice(0, 10));
Expand All @@ -120,31 +160,50 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli
expect(witness[3]).to.equal(proof1.root.bigInt());
});

it('should succeed for valid witness - single input', async () => {
it("should succeed for valid witness - single input", async () => {
const inputValues = [72, 0];
const outputValues = [20, 52];

// create two input UTXOs, each has their own salt, but same owner
const salt1 = newSalt();
const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]);
const input1 = poseidonHash([
BigInt(inputValues[0]),
salt1,
...Alice.pubKey,
]);
const inputCommitments = [input1, 0];

// create the nullifiers for the inputs
const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]);
const nullifier1 = poseidonHash3([
BigInt(inputValues[0]),
salt1,
senderPrivateKey,
]);
const nullifiers = [nullifier1, 0];

// calculate the root of the SMT
await smtAlice.add(input1, input1);

// generate the merkle proof for the inputs
const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH);
const proof1 = await smtAlice.generateCircomVerifierProof(
input1,
ZERO_HASH,
);
const proof2 = await smtAlice.generateCircomVerifierProof(0, ZERO_HASH);

// create two output UTXOs, they share the same salt, and different owner
const salt3 = newSalt();
const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Bob.pubKey]);
const output1 = poseidonHash([
BigInt(outputValues[0]),
salt3,
...Bob.pubKey,
]);
const salt4 = newSalt();
const output2 = poseidonHash([BigInt(outputValues[1]), salt4, ...Alice.pubKey]);
const output2 = poseidonHash([
BigInt(outputValues[1]),
salt4,
...Alice.pubKey,
]);
const outputCommitments = [output1, output2];

const witness = await circuit.calculateWitness(
Expand All @@ -155,49 +214,82 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli
inputSalts: [salt1, 0],
inputOwnerPrivateKey: senderPrivateKey,
root: proof1.root.bigInt(),
merkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())],
merkleProof: [
proof1.siblings.map((s) => s.bigInt()),
proof2.siblings.map((s) => s.bigInt()),
],
enabled: [1, 0],
outputCommitments,
outputValues,
outputSalts: [salt3, salt4],
outputOwnerPublicKeys: [Bob.pubKey, Alice.pubKey],
},
true
true,
);

expect(witness[1]).to.equal(BigInt(nullifiers[0]));
expect(witness[2]).to.equal(BigInt(nullifiers[1]));
expect(witness[3]).to.equal(proof1.root.bigInt());
});

it('should fail to generate a witness because mass conservation is not obeyed', async () => {
it("should fail to generate a witness because mass conservation is not obeyed", async () => {
const inputValues = [15, 100];
const outputValues = [90, 35];

// create two input UTXOs, each has their own salt, but same owner
const salt1 = newSalt();
const input1 = poseidonHash([BigInt(inputValues[0]), salt1, ...Alice.pubKey]);
const input1 = poseidonHash([
BigInt(inputValues[0]),
salt1,
...Alice.pubKey,
]);
const salt2 = newSalt();
const input2 = poseidonHash([BigInt(inputValues[1]), salt2, ...Alice.pubKey]);
const input2 = poseidonHash([
BigInt(inputValues[1]),
salt2,
...Alice.pubKey,
]);
const inputCommitments = [input1, input2];

// create the nullifiers for the input UTXOs
const nullifier1 = poseidonHash3([BigInt(inputValues[0]), salt1, senderPrivateKey]);
const nullifier2 = poseidonHash3([BigInt(inputValues[1]), salt2, senderPrivateKey]);
const nullifier1 = poseidonHash3([
BigInt(inputValues[0]),
salt1,
senderPrivateKey,
]);
const nullifier2 = poseidonHash3([
BigInt(inputValues[1]),
salt2,
senderPrivateKey,
]);
const nullifiers = [nullifier1, nullifier2];

// calculate the root of the SMT
await smtAlice.add(input1, input1);
await smtAlice.add(input2, input2);

// generate the merkle proof for the inputs
const proof1 = await smtAlice.generateCircomVerifierProof(input1, ZERO_HASH);
const proof2 = await smtAlice.generateCircomVerifierProof(input2, ZERO_HASH);
const proof1 = await smtAlice.generateCircomVerifierProof(
input1,
ZERO_HASH,
);
const proof2 = await smtAlice.generateCircomVerifierProof(
input2,
ZERO_HASH,
);

// create two output UTXOs, they share the same salt, and different owner
const salt3 = newSalt();
const output1 = poseidonHash([BigInt(outputValues[0]), salt3, ...Bob.pubKey]);
const output2 = poseidonHash([BigInt(outputValues[1]), salt3, ...Alice.pubKey]);
const output1 = poseidonHash([
BigInt(outputValues[0]),
salt3,
...Bob.pubKey,
]);
const output2 = poseidonHash([
BigInt(outputValues[1]),
salt3,
...Alice.pubKey,
]);
const outputCommitments = [output1, output2];

let err;
Expand All @@ -210,14 +302,17 @@ describe('main circuit tests for Zeto fungible tokens with anonymity using nulli
inputSalts: [salt1, salt2],
inputOwnerPrivateKey: senderPrivateKey,
root: proof1.root.bigInt(),
merkleProof: [proof1.siblings.map((s) => s.bigInt()), proof2.siblings.map((s) => s.bigInt())],
merkleProof: [
proof1.siblings.map((s) => s.bigInt()),
proof2.siblings.map((s) => s.bigInt()),
],
enabled: [1, 1],
outputCommitments,
outputValues,
outputSalts: [salt3, salt3],
outputOwnerPublicKeys: [Bob.pubKey, Alice.pubKey],
},
true
true,
);
} catch (e) {
err = e;
Expand Down

0 comments on commit 17c069f

Please sign in to comment.