diff --git a/src/poseidon_opt.js b/src/poseidon_opt.js index f9d2692..ecf1b6c 100644 --- a/src/poseidon_opt.js +++ b/src/poseidon_opt.js @@ -48,6 +48,10 @@ export default async function buildPoseidon() { assert(inputs.length > 0); assert(inputs.length <= N_ROUNDS_P.length); + if (inputs.some((i) => i < 0 || i >= F.p)) { + throw new Error(`One or more inputs are not in the field: ${F.p}`); + } + if (initState) { initState = F.e(initState); } else { diff --git a/src/poseidon_reference.js b/src/poseidon_reference.js index a57f52f..91811c2 100644 --- a/src/poseidon_reference.js +++ b/src/poseidon_reference.js @@ -45,6 +45,10 @@ export default async function buildPoseidon() { assert(inputs.length > 0); assert(inputs.length <= N_ROUNDS_P.length); + if (inputs.some((i) => i < 0 || i >= F.p)) { + throw new Error(`One or more inputs are not in the field: ${F.p}`); + } + const t = inputs.length + 1; const nRoundsF = N_ROUNDS_F; const nRoundsP = N_ROUNDS_P[t - 2]; diff --git a/src/poseidon_wasm.js b/src/poseidon_wasm.js index c7048c0..cfebae2 100644 --- a/src/poseidon_wasm.js +++ b/src/poseidon_wasm.js @@ -16,14 +16,31 @@ export async function buildPoseidon() { let buff; let n; if (Array.isArray(arr)) { + if (arr.some((i) => i < 0 || i >= F.p)) { + throw new Error(`One or more inputs are not in the field: ${F.p}`); + } n = arr.length; buff = new Uint8Array(n*32); for (let i=0; i { + const bi = chunk.reduceRight((acc, n) => (acc << 8n) | BigInt(n), 0n); + if (bi < 0 || bi >= F.p) { + throw new Error(`One or more inputs are not in the field: ${F.p}`); + } + }); } + bn128.tm.setBuff(pIn, buff); if ((n<1)||(n>16)) throw new Error("Invalid poseidon size"); @@ -437,4 +454,4 @@ export function buildPoseidonWasm(module) { buildPoseidon(); module.exportFunction("poseidon"); -} \ No newline at end of file +} diff --git a/test/poseidon.js b/test/poseidon.js index 8ef544e..d5b6199 100644 --- a/test/poseidon.js +++ b/test/poseidon.js @@ -1,5 +1,6 @@ import chai from "chai"; const assert = chai.assert; +const expect = chai.expect; import buildPoseidonOpt from "../src/poseidon_opt.js"; import {buildPoseidon as buildPoseidonWasm } from "../src/poseidon_wasm.js"; @@ -209,4 +210,57 @@ describe("Poseidon test", function () { } } }); + + it("Should check if inputs are in field", async () => { + + function arrayToReversedUint8Array(arr) { + const byteArray = []; + arr.forEach((num) => { + assert(num < 2n ** 256n) + const hex = num.toString(16); + const paddedHex = hex.padStart(64, '0'); + + for (let i = 0; i < paddedHex.length; i += 2) { + byteArray.push(parseInt(paddedHex.substring(i, i + 2), 16)); + } + }); + return new Uint8Array(byteArray.reverse()); + } + + const funcFactory = (func, input) => { + return () => func(input); + } + + // TODO fix this assertion + assert( + poseidonWasm.F.eq(funcFactory(poseidonWasm, [1n])(), + funcFactory(poseidonWasm, arrayToReversedUint8Array([1n]))()), + ); + + expect(funcFactory(poseidonWasm, [21888242871839275222246405745257275088548364400416034343698204186575808495616n])) + .not.to.throw(); + expect(funcFactory(poseidonWasm, [21888242871839275222246405745257275088548364400416034343698204186575808495617n])) + .to.throw("One or more inputs are not in the field"); + expect(funcFactory(poseidonWasm, ([-1n]))) + .to.throw("One or more inputs are not in the field"); + + expect(funcFactory(poseidonWasm, arrayToReversedUint8Array([21888242871839275222246405745257275088548364400416034343698204186575808495616n]))) + .not.to.throw(); + expect(funcFactory(poseidonWasm, arrayToReversedUint8Array([21888242871839275222246405745257275088548364400416034343698204186575808495617n]))) + .to.throw("One or more inputs are not in the field"); + + expect(funcFactory(poseidonOpt, [21888242871839275222246405745257275088548364400416034343698204186575808495616n])) + .not.to.throw(); + expect(funcFactory(poseidonOpt, [21888242871839275222246405745257275088548364400416034343698204186575808495617n])) + .to.throw("One or more inputs are not in the field"); + expect(funcFactory(poseidonOpt, ([-1n]), false)) + .to.throw("One or more inputs are not in the field"); + + expect(funcFactory(poseidonReference, [21888242871839275222246405745257275088548364400416034343698204186575808495616n])) + .not.to.throw(); + expect(funcFactory(poseidonReference, [21888242871839275222246405745257275088548364400416034343698204186575808495617n])) + .to.throw("One or more inputs are not in the field"); + expect(funcFactory(poseidonReference, ([-1n]), false)) + .to.throw("One or more inputs are not in the field"); + }); });