mirror of
https://github.com/0xbow-io/privacy-pools-core.git
synced 2026-01-08 17:13:52 -05:00
chore: update tests with new cases
This commit is contained in:
@@ -4,10 +4,7 @@ import { poseidon } from "../../../node_modules/maci-crypto/build/ts/hashing.js"
|
||||
import { parseEther, hexToBigInt, getAddress } from "viem";
|
||||
|
||||
describe("CommitmentHasher Circuit", () => {
|
||||
let circuit: WitnessTester<
|
||||
["value", "label", "nullifier", "secret"],
|
||||
["commitment", "precommitmentHash", "nullifierHash"]
|
||||
>;
|
||||
let circuit: WitnessTester<["value", "label", "nullifier", "secret"], ["commitment", "nullifierHash"]>;
|
||||
|
||||
const depositor = getAddress("0x9F2db792a6F2dAdf25D894cEd791080950bDE56f");
|
||||
const NONCE = BigInt(1);
|
||||
@@ -29,7 +26,7 @@ describe("CommitmentHasher Circuit", () => {
|
||||
secret: randomBigInt(),
|
||||
};
|
||||
|
||||
const [commitmentHash, precommitmentHash, nullifierHash] = hashCommitment(input);
|
||||
const [commitmentHash, nullifierHash] = hashCommitment(input);
|
||||
|
||||
await circuit.expectPass(
|
||||
{
|
||||
@@ -38,7 +35,7 @@ describe("CommitmentHasher Circuit", () => {
|
||||
nullifier: input.nullifier,
|
||||
secret: input.secret,
|
||||
},
|
||||
{ commitment: commitmentHash, precommitmentHash, nullifierHash },
|
||||
{ commitment: commitmentHash, nullifierHash },
|
||||
);
|
||||
});
|
||||
|
||||
@@ -59,7 +56,7 @@ describe("CommitmentHasher Circuit", () => {
|
||||
secret: randomBigInt(),
|
||||
};
|
||||
|
||||
const [commitmentHash, precommitmentHash, nullifierHash] = hashCommitment(childInput);
|
||||
const [commitmentHash, nullifierHash] = hashCommitment(childInput);
|
||||
|
||||
await circuit.expectPass(
|
||||
{
|
||||
@@ -68,7 +65,7 @@ describe("CommitmentHasher Circuit", () => {
|
||||
nullifier: childInput.nullifier,
|
||||
secret: childInput.secret,
|
||||
},
|
||||
{ commitment: commitmentHash, precommitmentHash, nullifierHash },
|
||||
{ commitment: commitmentHash, nullifierHash },
|
||||
);
|
||||
});
|
||||
|
||||
@@ -81,7 +78,7 @@ describe("CommitmentHasher Circuit", () => {
|
||||
secret: BigInt(0),
|
||||
};
|
||||
|
||||
const [commitmentHash, precommitmentHash, nullifierHash] = hashCommitment(input);
|
||||
const [commitmentHash, nullifierHash] = hashCommitment(input);
|
||||
|
||||
await circuit.expectPass(
|
||||
{
|
||||
@@ -90,7 +87,7 @@ describe("CommitmentHasher Circuit", () => {
|
||||
nullifier: input.nullifier,
|
||||
secret: input.secret,
|
||||
},
|
||||
{ commitment: commitmentHash, precommitmentHash, nullifierHash },
|
||||
{ commitment: commitmentHash, nullifierHash },
|
||||
);
|
||||
});
|
||||
|
||||
@@ -105,7 +102,7 @@ describe("CommitmentHasher Circuit", () => {
|
||||
secret: P - BigInt(1),
|
||||
};
|
||||
|
||||
const [commitmentHash, precommitmentHash, nullifierHash] = hashCommitment(input);
|
||||
const [commitmentHash, nullifierHash] = hashCommitment(input);
|
||||
|
||||
await circuit.expectPass(
|
||||
{
|
||||
@@ -114,7 +111,7 @@ describe("CommitmentHasher Circuit", () => {
|
||||
nullifier: input.nullifier,
|
||||
secret: input.secret,
|
||||
},
|
||||
{ commitment: commitmentHash, precommitmentHash, nullifierHash },
|
||||
{ commitment: commitmentHash, nullifierHash },
|
||||
);
|
||||
});
|
||||
|
||||
@@ -128,8 +125,8 @@ describe("CommitmentHasher Circuit", () => {
|
||||
|
||||
const modified = { ...base, value: parseEther("2"), label: randomBigInt(), secret: randomBigInt() };
|
||||
|
||||
const [_, __, nullifierHash1] = hashCommitment(base);
|
||||
const [___, ____, nullifierHash2] = hashCommitment(modified);
|
||||
const [_, nullifierHash1] = hashCommitment(base);
|
||||
const [___, nullifierHash2] = hashCommitment(modified);
|
||||
|
||||
if (nullifierHash1 != nullifierHash2) {
|
||||
throw new Error("Nullifier hashes don't match");
|
||||
@@ -166,18 +163,14 @@ describe("CommitmentHasher Circuit", () => {
|
||||
secret: randomBigInt(),
|
||||
};
|
||||
|
||||
const [hash1, pre1, null1] = hashCommitment(input);
|
||||
const [hash2, pre2, null2] = hashCommitment(input);
|
||||
const [hash3, pre3, null3] = hashCommitment(input);
|
||||
const [hash1, null1] = hashCommitment(input);
|
||||
const [hash2, null2] = hashCommitment(input);
|
||||
const [hash3, null3] = hashCommitment(input);
|
||||
|
||||
if (hash1 != hash2 || hash2 != hash3) {
|
||||
throw new Error("Commitment hashes don't match");
|
||||
}
|
||||
|
||||
if (pre1 != pre2 || pre2 != pre3) {
|
||||
throw new Error("Precommitment hashes don't match");
|
||||
}
|
||||
|
||||
if (null1 != null2 || null2 != null3) {
|
||||
throw new Error("Nullifier hashes don't match");
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@ export const circomkit = new Circomkit({
|
||||
include: ["../../node_modules/circomlib/circuits", "../../node_modules/maci-circuits/circom"],
|
||||
});
|
||||
|
||||
export function hashCommitment(input: Commitment): [bigint, bigint, bigint] {
|
||||
export function hashCommitment(input: Commitment): [bigint, bigint] {
|
||||
const precommitment = poseidon([BigInt(input.nullifier), BigInt(input.secret)]);
|
||||
const nullifierHash = poseidon([BigInt(input.nullifier)]);
|
||||
const commitmentHash = poseidon([BigInt(input.value), BigInt(input.label), precommitment]);
|
||||
return [commitmentHash, precommitment, nullifierHash];
|
||||
return [commitmentHash, nullifierHash];
|
||||
}
|
||||
|
||||
export function randomBigInt(): bigint {
|
||||
|
||||
@@ -49,8 +49,33 @@ describe("LeanIMTInclusionProof Circuit", () => {
|
||||
siblings: padSiblings(stateProof.siblings, maxDepth),
|
||||
actualDepth: tree.depth,
|
||||
},
|
||||
{ out: tree.root }
|
||||
{ out: tree.root },
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should fail when passing a tree depth greater than the max depth", async () => {
|
||||
const LEAVES = 16;
|
||||
|
||||
let leavesIndexes = [];
|
||||
|
||||
// insert leaves
|
||||
for (let i = 0; i < LEAVES; ++i) {
|
||||
let leafValue = randomBigInt();
|
||||
tree!.insert(leafValue);
|
||||
|
||||
leavesIndexes.push(tree.indexOf(leafValue));
|
||||
}
|
||||
|
||||
for (let i = 0; i < LEAVES; ++i) {
|
||||
let stateProof = tree.generateProof(i);
|
||||
|
||||
await circuit.expectFail({
|
||||
leaf: stateProof.leaf,
|
||||
leafIndex: stateProof.index,
|
||||
siblings: padSiblings(stateProof.siblings, maxDepth),
|
||||
actualDepth: maxDepth + 1,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -24,7 +24,7 @@ describe("Withdraw Circuit", () => {
|
||||
"stateSiblings",
|
||||
"stateIndex",
|
||||
"ASPSiblings",
|
||||
"ASPIndex"
|
||||
"ASPIndex",
|
||||
],
|
||||
["newCommitmentHash", "existingNullifierHash"]
|
||||
>;
|
||||
@@ -43,7 +43,7 @@ describe("Withdraw Circuit", () => {
|
||||
};
|
||||
|
||||
// Get deposit commitment hash
|
||||
const [depositHash, , depositNullifierHash] = hashCommitment(deposit);
|
||||
const [depositHash, depositNullifierHash] = hashCommitment(deposit);
|
||||
|
||||
// Using Poseidon for hashing the tree nodes
|
||||
const hash = (a: bigint, b: bigint) => poseidon([a, b]);
|
||||
@@ -119,7 +119,7 @@ describe("Withdraw Circuit", () => {
|
||||
{
|
||||
newCommitmentHash: commitmentHash,
|
||||
existingNullifierHash: depositNullifierHash,
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -146,7 +146,7 @@ describe("Withdraw Circuit", () => {
|
||||
};
|
||||
|
||||
// Hash first withdrawal commitment
|
||||
const [firstChildCommitmentHash, , firstChildNullifierHash] = hashCommitment(firstChild);
|
||||
const [firstChildCommitmentHash, firstChildNullifierHash] = hashCommitment(firstChild);
|
||||
|
||||
// Generate merkle proofs to spend deposit
|
||||
let stateProof = stateTree.generateProof(2);
|
||||
@@ -175,7 +175,7 @@ describe("Withdraw Circuit", () => {
|
||||
{
|
||||
newCommitmentHash: firstChildCommitmentHash,
|
||||
existingNullifierHash: depositNullifierHash,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Insert the new child commitment in the state tree
|
||||
@@ -190,7 +190,7 @@ describe("Withdraw Circuit", () => {
|
||||
};
|
||||
|
||||
// Hash the second child commitment
|
||||
const [secondChildComitmentHash, ,] = hashCommitment(secondChild);
|
||||
const [secondChildComitmentHash] = hashCommitment(secondChild);
|
||||
|
||||
// Regenerate state merkle proof
|
||||
let newStateProof = stateTree.generateProof(3);
|
||||
@@ -218,7 +218,7 @@ describe("Withdraw Circuit", () => {
|
||||
{
|
||||
newCommitmentHash: secondChildComitmentHash,
|
||||
existingNullifierHash: firstChildNullifierHash,
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -246,7 +246,7 @@ describe("Withdraw Circuit", () => {
|
||||
};
|
||||
|
||||
// Hash new commitment of zero value
|
||||
const [commitmentHash, ,] = hashCommitment(fullWithdrawal);
|
||||
const [commitmentHash] = hashCommitment(fullWithdrawal);
|
||||
|
||||
// generate merkle proofs
|
||||
let stateProof = stateTree.generateProof(1);
|
||||
@@ -275,7 +275,7 @@ describe("Withdraw Circuit", () => {
|
||||
{
|
||||
newCommitmentHash: commitmentHash,
|
||||
existingNullifierHash: depositNullifierHash,
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -423,7 +423,7 @@ describe("Withdraw Circuit", () => {
|
||||
{
|
||||
newCommitmentHash: firstWithdrawalHash,
|
||||
existingNullifierHash: depositNullifierHash,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Insert new commitment in tree
|
||||
@@ -464,4 +464,96 @@ describe("Withdraw Circuit", () => {
|
||||
ASPIndex: ASPProof.index,
|
||||
});
|
||||
});
|
||||
|
||||
it("Withdrawal should fail if reusing a nullifier", async () => {
|
||||
// Insert deposit commitment in state tree
|
||||
stateTree!.insert(randomBigInt());
|
||||
stateTree!.insert(randomBigInt());
|
||||
stateTree!.insert(randomBigInt());
|
||||
stateTree!.insert(depositHash);
|
||||
|
||||
// Insert deposit label in ASP tree (deposit is now validated)
|
||||
ASPTree!.insert(randomBigInt());
|
||||
ASPTree!.insert(randomBigInt());
|
||||
ASPTree!.insert(randomBigInt());
|
||||
ASPTree!.insert(LABEL);
|
||||
|
||||
// Withrdaw 1 ETH from deposit
|
||||
const withdrawal = {
|
||||
value: parseEther("4"), // New value after withdrawal
|
||||
label: LABEL,
|
||||
nullifier: deposit.nullifier, // Reusing same nullifier as deposit commitment
|
||||
secret: randomBigInt(),
|
||||
};
|
||||
|
||||
// Generate merkle proofs for commitment and label
|
||||
let stateProof = stateTree.generateProof(3);
|
||||
let ASPProof = ASPTree.generateProof(3);
|
||||
|
||||
// Fail to withdraw because using the same nullifier
|
||||
await circuit.expectFail({
|
||||
withdrawnValue: parseEther("1"),
|
||||
stateRoot: stateProof.root,
|
||||
stateTreeDepth: stateTree.depth,
|
||||
ASPRoot: ASPProof.root,
|
||||
ASPTreeDepth: ASPTree.depth,
|
||||
context: randomBigInt(),
|
||||
label: LABEL,
|
||||
existingValue: deposit.value,
|
||||
existingNullifier: deposit.nullifier,
|
||||
existingSecret: deposit.secret,
|
||||
newNullifier: withdrawal.nullifier,
|
||||
newSecret: withdrawal.secret,
|
||||
stateSiblings: padSiblings(stateProof.siblings, maxTreeDepth),
|
||||
stateIndex: stateProof.index,
|
||||
ASPSiblings: padSiblings(ASPProof.siblings, maxTreeDepth),
|
||||
ASPIndex: ASPProof.index,
|
||||
});
|
||||
});
|
||||
|
||||
it("Withdrawal should fail if passing an invalid tree depth", async () => {
|
||||
// Insert deposit commitment in state tree
|
||||
stateTree!.insert(randomBigInt());
|
||||
stateTree!.insert(randomBigInt());
|
||||
stateTree!.insert(randomBigInt());
|
||||
stateTree!.insert(depositHash);
|
||||
|
||||
// Insert deposit label in ASP tree (deposit is now validated)
|
||||
ASPTree!.insert(randomBigInt());
|
||||
ASPTree!.insert(randomBigInt());
|
||||
ASPTree!.insert(randomBigInt());
|
||||
ASPTree!.insert(LABEL);
|
||||
|
||||
// Withrdaw 1 ETH from deposit
|
||||
const withdrawal = {
|
||||
value: parseEther("4"), // New value after withdrawal
|
||||
label: LABEL,
|
||||
nullifier: randomBigInt(),
|
||||
secret: randomBigInt(),
|
||||
};
|
||||
|
||||
// Generate merkle proofs for commitment and label
|
||||
let stateProof = stateTree.generateProof(3);
|
||||
let ASPProof = ASPTree.generateProof(3);
|
||||
|
||||
// Fail to withdraw because using the same nullifier
|
||||
await circuit.expectFail({
|
||||
withdrawnValue: parseEther("1"),
|
||||
stateRoot: stateProof.root,
|
||||
stateTreeDepth: 33,
|
||||
ASPRoot: ASPProof.root,
|
||||
ASPTreeDepth: ASPTree.depth,
|
||||
context: randomBigInt(),
|
||||
label: LABEL,
|
||||
existingValue: deposit.value,
|
||||
existingNullifier: deposit.nullifier,
|
||||
existingSecret: deposit.secret,
|
||||
newNullifier: withdrawal.nullifier,
|
||||
newSecret: withdrawal.secret,
|
||||
stateSiblings: padSiblings(stateProof.siblings, maxTreeDepth),
|
||||
stateIndex: stateProof.index,
|
||||
ASPSiblings: padSiblings(ASPProof.siblings, maxTreeDepth),
|
||||
ASPIndex: ASPProof.index,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user