Files
self/circuits/tests/other_circuits/custom_hasher.test.ts
2025-06-04 11:37:32 +02:00

102 lines
4.1 KiB
TypeScript

import { expect } from 'chai';
import path from 'path';
import { wasm as wasm_tester } from 'circom_tester';
import { formatInput } from '@selfxyz/common/utils/circuits/generateInputs';
import { customHasher, packBytesAndPoseidon } from '@selfxyz/common/utils/hash';
describe('CustomHasher', function () {
this.timeout(0);
let circuitCustomHasher;
let circuitPackBytesAndPoseidon;
this.beforeAll(async () => {
const circuitPathCustomHasher = path.resolve(
__dirname,
'../../circuits/tests/utils/customHasher_tester.circom'
);
const circuitPathPackBytesAndPoseidon = path.resolve(
__dirname,
'../../circuits/tests/utils/packBytesAndPoseidon_tester.circom'
);
circuitCustomHasher = await wasm_tester(circuitPathCustomHasher, {
include: [
'node_modules',
'./node_modules/@zk-kit/binary-merkle-root.circom/src',
'./node_modules/circomlib/circuits',
],
});
circuitPackBytesAndPoseidon = await wasm_tester(circuitPathPackBytesAndPoseidon, {
include: [
'node_modules',
'./node_modules/@zk-kit/binary-merkle-root.circom/src',
'./node_modules/circomlib/circuits',
],
});
});
describe('custom hasher', async () => {
const randomNumbers = Array(16)
.fill(0)
.map(() => {
const maxVal = BigInt(2) ** BigInt(250);
const randomVal =
BigInt(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)) *
BigInt(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER));
return (randomVal % maxVal).toString();
});
const inputs = { in: formatInput(randomNumbers) };
it('customHasher output should be the same between circom and js implementation', async () => {
const witness = await circuitCustomHasher.calculateWitness(inputs, true);
const hashValueCircom = (await circuitCustomHasher.getOutput(witness, ['out'])).out;
console.log('\x1b[34m', 'hashValueCircom: ', hashValueCircom, '\x1b[0m');
const hashValueJs = customHasher(randomNumbers);
console.log('\x1b[34m', 'hashValueJs: ', hashValueJs, '\x1b[0m');
expect(BigInt(hashValueCircom).toString()).to.equal(BigInt(hashValueJs).toString());
});
});
describe('packBytesAndPoseidon', async () => {
let randomNumbers = Array(16)
.fill(0)
.map(() => {
return Math.floor(Math.random() * 256); // Random number between 0 and 255
});
const inputs = { in: formatInput(randomNumbers) };
console.log('\x1b[34m', 'inputs: ', inputs, '\x1b[0m');
it('packBytesAndPoseidon output should be the same between circom and js implementation', async () => {
const witness = await circuitPackBytesAndPoseidon.calculateWitness(inputs, true);
const hashValueCircom = (await circuitPackBytesAndPoseidon.getOutput(witness, ['out'])).out;
console.log('\x1b[34m', 'hashValueCircom: ', hashValueCircom, '\x1b[0m');
const hashValueJs = packBytesAndPoseidon(randomNumbers);
console.log('\x1b[34m', 'hashValueJs: ', hashValueJs, '\x1b[0m');
expect(BigInt(hashValueCircom).toString()).to.equal(BigInt(hashValueJs).toString());
});
it('packBytesAndPoseidon should fail, inputs[0] = 256', async () => {
try {
const wrongRandomNumbers = [...randomNumbers];
wrongRandomNumbers[0] = 256;
const wrongInputs = { in: formatInput(wrongRandomNumbers) };
const witness = await circuitPackBytesAndPoseidon.calculateWitness(wrongInputs, true);
expect.fail('Expected an error but none was thrown.');
} catch (error) {
expect(error.message).to.include('Assert Failed');
}
});
it('packBytesAndPoseidon should fail, inputs[15] = 256', async () => {
try {
const wrongRandomNumbers = [...randomNumbers];
wrongRandomNumbers[15] = 256;
const wrongInputs = { in: formatInput(wrongRandomNumbers) };
const witness = await circuitPackBytesAndPoseidon.calculateWitness(wrongInputs, true);
expect.fail('Expected an error but none was thrown.');
} catch (error) {
expect(error.message).to.include('Assert Failed');
}
});
});
});