UNPKG

o1js

Version:

TypeScript framework for zk-SNARKs and zkApps

66 lines (52 loc) 2.25 kB
import { Poseidon, PoseidonLegacy } from './poseidon.js'; import { testPoseidonKimchiFp } from './test-vectors/poseidon-kimchi.js'; import { testPoseidonLegacyFp } from './test-vectors/poseidon-legacy.js'; import { expect } from 'expect'; import { bigIntToBytes, parseHexString32 } from './bigint-helpers.js'; import { test, Random } from '../../lib/testing/property.js'; import { Test } from '../../snarky.js'; import { FieldConst } from '../../lib/provable/core/fieldvar.js'; import { MlArray } from '../../lib/ml/base.js'; import { Fp } from './finite-field.js'; let mlTest = await Test(); function checkTestVectors( testVectors: { input: string[]; output: string }[], hash: (input: bigint[]) => bigint ) { for (let i = 0; i < testVectors.length; i++) { let { input, output } = testVectors[i]; let inputBigint = input.map(parseHexString32); let hashOutput = hash(inputBigint); let hex = fieldToHex(hashOutput); expect(hex).toEqual(output); } } checkTestVectors(testPoseidonKimchiFp.test_vectors, Poseidon.hash); checkTestVectors(testPoseidonLegacyFp.test_vectors, PoseidonLegacy.hash); // calling update() subsequently on size-2 chunks is the same as calling hash() on the full input test(Random.array(Random.field, 5), (xs) => { let h1 = Poseidon.hash(xs); let state = Poseidon.initialState(); state = Poseidon.update(state, [xs[0], xs[1]]); state = Poseidon.update(state, [xs[2], xs[3]]); state = Poseidon.update(state, [xs[4]]); let h2 = state[0]; expect(h1).toEqual(h2); }); console.log('poseidon implementation matches the test vectors! 🎉'); test(Random.array(Random.field, Random.nat(20)), (xs) => { let g1 = Poseidon.hashToGroup(xs)!; let [, g2x, g2y] = mlTest.poseidon.hashToGroup( MlArray.to(xs.map(FieldConst.fromBigint)) ); expect(g1).toBeDefined(); expect(g1.x).toEqual(FieldConst.toBigint(g2x)); let g2y_ = FieldConst.toBigint(g2y); expect(g1.y === g2y_ || Fp.negate(g1.y) === g2y_).toEqual(true); expect(Fp.isEven(g1.y)).toEqual(true); }); console.log('poseidon hashToGroup implementations match! 🎉'); function fieldToHex(x: bigint) { let bytes = bigIntToBytes(x, 32); return bytes.map((byte) => byte.toString(16).padStart(2, '0')).join(''); }