Add poseidon252 snark-friendly hash

This commit is contained in:
Paul Miller 2023-01-23 18:41:19 +00:00
parent 6f99f6042e
commit 055147f1be
No known key found for this signature in database
GPG Key ID: 697079DA6878B89B
6 changed files with 1673 additions and 6 deletions

@ -219,6 +219,15 @@ export const CURVES = {
);
},
},
poseidon: {
samples: 2000,
noble: () => {
return stark.poseidonHash(
0x3d937c035c878245caf64531a5756109c53068da139362728feb561405371cbn,
0x208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31an
);
},
},
verify: {
samples: 500,
old: ({ publicKeyStark, msgHash, keyPair }) => {

@ -83,6 +83,11 @@
"import": "./lib/esm/abstract/utils.js",
"default": "./lib/abstract/utils.js"
},
"./abstract/poseidon": {
"types": "./lib/abstract/poseidon.d.ts",
"import": "./lib/esm/abstract/poseidon.js",
"default": "./lib/abstract/poseidon.js"
},
"./_shortw_utils": {
"types": "./lib/_shortw_utils.d.ts",
"import": "./lib/esm/_shortw_utils.js",

117
src/abstract/poseidon.ts Normal file

@ -0,0 +1,117 @@
// Poseidon Hash (https://eprint.iacr.org/2019/458.pdf)
// Website: https://www.poseidon-hash.info
import * as mod from './modular.js';
// NOTE: we currently don't provide any constants, since different implementations use diffferent constants
// For reference constants see './test/poseidon.test.js'
export type PoseidonOpts = {
Fp: mod.Field<bigint>;
t: number;
roundsFull: number;
roundsPartial: number;
sboxPower?: number;
reversePartialPowIdx?: boolean; // Hack for stark
mds: bigint[][];
roundConstants: bigint[][];
};
export function validateOpts(opts: PoseidonOpts) {
const { Fp } = opts;
mod.validateField(Fp);
for (const i of ['t', 'roundsFull', 'roundsPartial'] as const) {
if (typeof opts[i] !== 'number' || !Number.isSafeInteger(opts[i]))
throw new Error(`Poseidon: invalid param ${i}=${opts[i]} (${typeof opts[i]})`);
}
if (opts.reversePartialPowIdx !== undefined && typeof opts.reversePartialPowIdx !== 'boolean')
throw new Error(`Poseidon: invalid param reversePartialPowIdx=${opts.reversePartialPowIdx}`);
// Default is 5, but by some reasons stark uses 3
let sboxPower = opts.sboxPower;
if (sboxPower === undefined) sboxPower = 5;
if (typeof sboxPower !== 'number' || !Number.isSafeInteger(sboxPower))
throw new Error(`Poseidon wrong sboxPower=${sboxPower}`);
const _sboxPower = BigInt(sboxPower);
let sboxFn = (n: bigint) => mod.FpPow(Fp, n, _sboxPower);
// Unwrapped sbox power for common cases (195->142μs)
if (sboxPower === 3) sboxFn = (n: bigint) => Fp.mul(Fp.squareN(n), n);
else if (sboxPower === 5) sboxFn = (n: bigint) => Fp.mul(Fp.squareN(Fp.squareN(n)), n);
if (opts.roundsFull % 2 !== 0)
throw new Error(`Poseidon roundsFull is not even: ${opts.roundsFull}`);
const rounds = opts.roundsFull + opts.roundsPartial;
if (!Array.isArray(opts.roundConstants) || opts.roundConstants.length !== rounds)
throw new Error('Poseidon: wrong round constants');
const roundConstants = opts.roundConstants.map((rc) => {
if (!Array.isArray(rc) || rc.length !== opts.t)
throw new Error(`Poseidon wrong round constants: ${rc}`);
return rc.map((i) => {
if (typeof i !== 'bigint' || !Fp.isValid(i))
throw new Error(`Poseidon wrong round constant=${i}`);
return Fp.create(i);
});
});
// MDS is TxT matrix
if (!Array.isArray(opts.mds) || opts.mds.length !== opts.t)
throw new Error('Poseidon: wrong MDS matrix');
const mds = opts.mds.map((mdsRow) => {
if (!Array.isArray(mdsRow) || mdsRow.length !== opts.t)
throw new Error(`Poseidon MDS matrix row: ${mdsRow}`);
return mdsRow.map((i) => {
if (typeof i !== 'bigint') throw new Error(`Poseidon MDS matrix value=${i}`);
return Fp.create(i);
});
});
return Object.freeze({ ...opts, rounds, sboxFn, roundConstants, mds });
}
export function splitConstants(rc: bigint[], t: number) {
if (typeof t !== 'number') throw new Error('poseidonSplitConstants: wrong t');
if (!Array.isArray(rc) || rc.length % t) throw new Error('poseidonSplitConstants: wrong rc');
const res = [];
let tmp = [];
for (let i = 0; i < rc.length; i++) {
tmp.push(rc[i]);
if (tmp.length === t) {
res.push(tmp);
tmp = [];
}
}
return res;
}
export function poseidon(opts: PoseidonOpts) {
const { t, Fp, rounds, sboxFn, reversePartialPowIdx } = validateOpts(opts);
const halfRoundsFull = Math.floor(opts.roundsFull / 2);
const partialIdx = reversePartialPowIdx ? t - 1 : 0;
const poseidonRound = (values: bigint[], isFull: boolean, idx: number) => {
values = values.map((i, j) => Fp.add(i, opts.roundConstants[idx][j]));
if (isFull) values = values.map((i) => sboxFn(i));
else values[partialIdx] = sboxFn(values[partialIdx]);
// Matrix multiplication
values = opts.mds.map((i) =>
i.reduce((acc, i, j) => Fp.add(acc, Fp.mulN(i, values[j])), Fp.ZERO)
);
return values;
};
return function poseidonHash(values: bigint[]) {
if (!Array.isArray(values) || values.length !== t)
throw new Error(`Poseidon: wrong values (expected array of bigints with length ${t})`);
values = values.map((i) => {
if (typeof i !== 'bigint') throw new Error(`Poseidon: wrong value=${i} (${typeof i})`);
return Fp.create(i);
});
let round = 0;
// Apply r_f/2 full rounds.
for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, round++);
// Apply r_p partial rounds.
for (let i = 0; i < opts.roundsPartial; i++) values = poseidonRound(values, false, round++);
// Apply r_f/2 full rounds.
for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, round++);
if (round !== rounds)
throw new Error(`Poseidon: wrong number of rounds: last round=${round}, total=${rounds}`);
return values;
};
}

@ -3,8 +3,10 @@ import { keccak_256 } from '@noble/hashes/sha3';
import { sha256 } from '@noble/hashes/sha256';
import { weierstrass, ProjectivePointType } from './abstract/weierstrass.js';
import * as cutils from './abstract/utils.js';
import { Fp, mod } from './abstract/modular.js';
import { Fp, mod, Field, validateField } from './abstract/modular.js';
import { getHash } from './_shortw_utils.js';
import * as poseidon from './abstract/poseidon.js';
import { utf8ToBytes } from '@noble/hashes/utils';
type ProjectivePoint = ProjectivePointType<bigint>;
// Stark-friendly elliptic curve
@ -138,12 +140,12 @@ function hashKeyWithIndex(key: Uint8Array, index: number) {
export function grindKey(seed: Hex) {
const _seed = ensureBytes0x(seed);
const sha256mask = 2n ** 256n;
const Fn = Fp(CURVE.n);
const limit = sha256mask - Fn.create(sha256mask);
const limit = sha256mask - mod(sha256mask, CURVE_N);
for (let i = 0; ; i++) {
const key = hashKeyWithIndex(_seed, i);
// key should be in [0, limit)
if (key < limit) return Fn.create(key).toString(16);
if (key < limit) return mod(key, CURVE_N).toString(16);
}
}
@ -261,5 +263,84 @@ export function hashChain(data: PedersenArg[], fn = pedersen) {
export const computeHashOnElements = (data: PedersenArg[], fn = pedersen) =>
[0, ...data, data.length].reduce((x, y) => fn(x, y));
const MASK_250 = 2n ** 250n - 1n;
const MASK_250 = cutils.bitMask(250);
export const keccak = (data: Uint8Array) => bytesToNumber0x(keccak_256(data)) & MASK_250;
// Poseidon hash
export const Fp253 = Fp(
BigInt('14474011154664525231415395255581126252639794253786371766033694892385558855681')
); // 2^253 + 2^199 + 1
export const Fp251 = Fp(
BigInt('3618502788666131213697322783095070105623107215331596699973092056135872020481')
); // 2^251 + 17 * 2^192 + 1
function poseidonRoundConstant(Fp: Field<bigint>, name: string, idx: number) {
const val = Fp.fromBytes(sha256(utf8ToBytes(`${name}${idx}`)));
return Fp.create(val);
}
// NOTE: doesn't check eiginvalues and possible can create unsafe matrix. But any filtration here will break compatibility with starknet
// Please use only if you really know what you doing.
// https://eprint.iacr.org/2019/458.pdf Section 2.3 (Avoiding Insecure Matrices)
export function _poseidonMDS(Fp: Field<bigint>, name: string, m: number, attempt = 0) {
const x_values: bigint[] = [];
const y_values: bigint[] = [];
for (let i = 0; i < m; i++) {
x_values.push(poseidonRoundConstant(Fp, `${name}x`, attempt * m + i));
y_values.push(poseidonRoundConstant(Fp, `${name}y`, attempt * m + i));
}
if (new Set([...x_values, ...y_values]).size !== 2 * m)
throw new Error('X and Y values are not distinct');
return x_values.map((x) => y_values.map((y) => Fp.invert(Fp.sub(x, y))));
}
const MDS_SMALL = [
[3, 1, 1],
[1, -1, 1],
[1, 1, -2],
].map((i) => i.map(BigInt));
export type PoseidonOpts = {
Fp: Field<bigint>;
rate: number;
capacity: number;
roundsFull: number;
roundsPartial: number;
};
function poseidonBasic(opts: PoseidonOpts, mds: bigint[][]) {
validateField(opts.Fp);
if (!Number.isSafeInteger(opts.rate) || !Number.isSafeInteger(opts.capacity))
throw new Error(`Wrong poseidon opts: ${opts}`);
const m = opts.rate + opts.capacity;
const rounds = opts.roundsFull + opts.roundsPartial;
const roundConstants = [];
for (let i = 0; i < rounds; i++) {
const row = [];
for (let j = 0; j < m; j++) row.push(poseidonRoundConstant(opts.Fp, 'Hades', m * i + j));
roundConstants.push(row);
}
return poseidon.poseidon({
...opts,
t: m,
sboxPower: 3,
reversePartialPowIdx: true, // Why?!
mds,
roundConstants,
});
}
export function poseidonCreate(opts: PoseidonOpts, mdsAttempt = 0) {
const m = opts.rate + opts.capacity;
if (!Number.isSafeInteger(mdsAttempt)) throw new Error(`Wrong mdsAttempt=${mdsAttempt}`);
return poseidonBasic(opts, _poseidonMDS(opts.Fp, 'HadesMDS', m, mdsAttempt));
}
export const poseidonSmall = poseidonBasic(
{ Fp: Fp251, rate: 2, capacity: 1, roundsFull: 8, roundsPartial: 83 },
MDS_SMALL
);
export function poseidonHash(x: bigint, y: bigint, fn = poseidonSmall) {
return fn([x, y, 2n])[0];
}

375
test/poseidon.test.js Normal file

@ -0,0 +1,375 @@
import { deepStrictEqual, throws } from 'assert';
import { should, describe } from 'micro-should';
import * as poseidon from '../lib/esm/abstract/poseidon.js';
import * as stark from '../lib/esm/stark.js';
import * as mod from '../lib/esm/abstract/modular.js';
import { default as pvectors } from './vectors/poseidon.json' assert { type: 'json' };
const { st1, st2, st3, st4 } = pvectors;
describe('Stark', () => {
should('poseidonMdsMatrixUnsafe', () => {
const matrix = [
[
2778560475384578201077246683568670693743746494974613838537993780462451025202n,
1175299404131241652930097281601393692628174430208909163156444576599667748918n,
459930634481240293374476654621049426021644833445120509139335338093973616187n,
],
[
2699370377471722242958186781613316939129713429759631049128040020458992590651n,
1488831960940040807419416081499284128899207850625157044437836107358246188803n,
3405112981980800875534081635548548562399171531483475155039499736396630179833n,
],
[
1860070716810022053527433635909648527418980081585070357136946388030401399342n,
2606527819893847364468965441606872534271438365089422719512470850627617054272n,
2715867691630559973784374069384091521307896505826088878858115800121387149186n,
],
];
deepStrictEqual(stark._poseidonMDS(stark.Fp251, 'HadesMDS', 3, 0), matrix);
});
should('HadesPermutation', () => {
deepStrictEqual(
stark.poseidonSmall([
4379311784651118086770398084575492314150568148003994287303975907890254409956n,
5329163686893598957822497554130545759427567507701132391649270915797304266381n,
1081797873147645298856697595691862435558345225505029083672323747888463248125n,
]),
[
1342232677189718451682683203787286758407058155581807117466384919996430343159n,
380853961496438693334706417244065195303131974442781224856980145160981376662n,
1919212703304954644851339421413808305076993030243665926017858381407659820613n,
]
);
});
should('HadesPermutation (custom)', () => {
const h = stark.poseidonCreate({
Fp: stark.Fp251,
rate: 2,
capacity: 1,
roundsFull: 8,
roundsPartial: 83,
});
deepStrictEqual(
h([
4379311784651118086770398084575492314150568148003994287303975907890254409956n,
5329163686893598957822497554130545759427567507701132391649270915797304266381n,
1081797873147645298856697595691862435558345225505029083672323747888463248125n,
]),
[
2864461397224564530993577865807718592436235694918699912757414692654057505365n,
1576206983934669422583425346343473837630736957734769961428118554039862202613n,
1607006208879950753054674913136990521997740361932184292107790666308092455675n,
]
);
});
should('HadesPermutation (custom, Fp253)', () => {
const h = stark.poseidonCreate({
Fp: stark.Fp253,
rate: 2,
capacity: 1,
roundsFull: 8,
roundsPartial: 83,
});
deepStrictEqual(
h([
4379311784651118086770398084575492314150568148003994287303975907890254409956n,
5329163686893598957822497554130545759427567507701132391649270915797304266381n,
1081797873147645298856697595691862435558345225505029083672323747888463248125n,
]),
[
11142411210283675631592374649001218595612035205233832049083369488791454026844n,
98304838055259883374145304326851527594402230455144399354815642835291000581n,
8643534790068701259242695637167859384191499281344739826454631748110172472997n,
]
);
});
should('PoseidonHash', () => {
deepStrictEqual(
stark.poseidonHash(
4379311784651118086770398084575492314150568148003994287303975907890254409956n,
5329163686893598957822497554130545759427567507701132391649270915797304266381n
),
2457757238178986673695038558497063891521456354791980183317105434323761563347n
);
});
should('PoseidonHash (custom)', () => {
const h = stark.poseidonCreate({
Fp: stark.Fp251,
rate: 2,
capacity: 1,
roundsFull: 8,
roundsPartial: 83,
});
deepStrictEqual(
stark.poseidonHash(
4379311784651118086770398084575492314150568148003994287303975907890254409956n,
5329163686893598957822497554130545759427567507701132391649270915797304266381n,
h
),
654164301216498483748450956182386165976155551413834652546305861430119544536n
);
});
should('PoseidonHash (custom, Fp253)', () => {
const h = stark.poseidonCreate({
Fp: stark.Fp253,
rate: 2,
capacity: 1,
roundsFull: 8,
roundsPartial: 83,
});
deepStrictEqual(
stark.poseidonHash(
4379311784651118086770398084575492314150568148003994287303975907890254409956n,
5329163686893598957822497554130545759427567507701132391649270915797304266381n,
h
),
9557424461253897982213839283192966960594440725760392861778010931094267239786n
);
});
});
// Official vectors: https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/test_vectors.txt
should('poseidonperm_x5_255_3', () => {
const Fp = mod.Fp(BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001'));
const mds = [
[
0x3d955d6c02fe4d7cb500e12f2b55eff668a7b4386bd27413766713c93f2acfcdn,
0x3798866f4e6058035dcf8addb2cf1771fac234bcc8fc05d6676e77e797f224bfn,
0x2c51456a7bf2467eac813649f3f25ea896eac27c5da020dae54a6e640278fda2n,
],
[
0x20088ca07bbcd7490a0218ebc0ecb31d0ea34840e2dc2d33a1a5adfecff83b43n,
0x1d04ba0915e7807c968ea4b1cb2d610c7f9a16b4033f02ebacbb948c86a988c3n,
0x5387ccd5729d7acbd09d96714d1d18bbd0eeaefb2ddee3d2ef573c9c7f953307n,
],
[
0x1e208f585a72558534281562cad89659b428ec61433293a8d7f0f0e38a6726acn,
0x0455ebf862f0b60f69698e97d36e8aafd4d107cae2b61be1858b23a3363642e0n,
0x569e2c206119e89455852059f707370e2c1fc9721f6c50991cedbbf782daef54n,
],
];
const t = 3;
const roundConstants = poseidon.splitConstants(st1.map(BigInt), t);
const poseidon_x5_255_3 = poseidon.poseidon({
Fp,
t,
roundsFull: 8,
roundsPartial: 57,
mds,
roundConstants,
});
deepStrictEqual(
poseidon_x5_255_3([
0x0000000000000000000000000000000000000000000000000000000000000000n,
0x0000000000000000000000000000000000000000000000000000000000000001n,
0x0000000000000000000000000000000000000000000000000000000000000002n,
]),
[
0x28ce19420fc246a05553ad1e8c98f5c9d67166be2c18e9e4cb4b4e317dd2a78an,
0x51f3e312c95343a896cfd8945ea82ba956c1118ce9b9859b6ea56637b4b1ddc4n,
0x3b2b69139b235626a0bfb56c9527ae66a7bf486ad8c11c14d1da0c69bbe0f79an,
]
);
});
should('poseidonperm_x5_255_5', () => {
const Fp = mod.Fp(0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001n);
const t = 5;
const mds = [
[
0x354423b163d1078b0dd645be56316e34a9b98e52dcf9f469be44b108be46c107n,
0x44778737e8bc1154aca1cd92054a1e5b83808403705f7d54da88bbd1920e1053n,
0x5872eefb5ab6b2946556524168a2aebb69afd513a2fff91e50167b1f6e4055e0n,
0x43dff85b25129835819bc8c95819f1a34136f6114e900cd3656e1b9e0e13f86an,
0x07803d2ffe72940596803f244ac090a9cf2d3616546520bc360c7eed0b81cbf8n,
],
[
0x45d6bc4b818e2b9a53e0e2c0a08f70c34167fd8128e05ac800651ddfee0932d1n,
0x08317abbb9e5046b22dfb79e64c8184855107c1d95dddd2b63ca10dddea9ff1an,
0x1bb80eba77c5dcffafb55ccba4ae39ac8f94a054f2a0ee3006b362f709d5e470n,
0x038e75bdcf8be7fd3a1e844c4de7333531bbd5a8d2c3779627df88e7480e7c5cn,
0x2dd797a699e620ea6b31b91ba3fad4a82f40cffb3e8a30c0b7a546ff69a9002bn,
],
[
0x4b906f9ee339b196e958e3541b555b4b53e540a113b2f1cabba627be16eb5608n,
0x605f0c707b82ef287f46431f9241fe4acf0b7ddb151803cbcf1e7bbd27c3e974n,
0x100c514bf38f6ff10df1c83bb428397789cfff7bb0b1280f52343861e8c8737en,
0x2d40ce8af8a252f5611701c3d6b1e517161d0549ef27f443570c81fcdfe3706bn,
0x3e6418bdf0313f59afc5f40b4450e56881110ea9a0532e8092efb06a12a8b0f1n,
],
[
0x71788bf7f6c0cebae5627c5629d012d5fba52428d1f25cdaa0a7434e70e014d0n,
0x55cc73296f7e7d26d10b9339721d7983ca06145675255025ab00b34342557db7n,
0x0f043b29be2def73a6c6ec92168ea4b47bc9f434a5e6b5d48677670a7ca4d285n,
0x62ccc9cdfed859a610f103d74ea04dec0f6874a9b36f3b4e9b47fd73368d45b4n,
0x55fb349dd6200b34eaba53a67e74f47d08e473da139dc47e44df50a26423d2d1n,
],
[
0x45bfbe5ed2f4a01c13b15f20bba00ff577b1154a81b3f318a6aff86369a66735n,
0x6a008906685587af05dce9ad2c65ea1d42b1ec32609597bd00c01f58443329efn,
0x004feebd0dbdb9b71176a1d43c9eb495e16419382cdf7864e4bce7b37440cd58n,
0x09f080180ce23a5aef3a07e60b28ffeb2cf1771aefbc565c2a3059b39ed82f43n,
0x2f7126ddc54648ab6d02493dbe9907f29f4ef3967ad8cd609f0d9467e1694607n,
],
];
const roundConstants = poseidon.splitConstants(st2.map(BigInt), t);
const poseidon_x5_255_5 = poseidon.poseidon({
Fp,
t,
roundsFull: 8,
roundsPartial: 60,
mds,
roundConstants,
});
deepStrictEqual(
poseidon_x5_255_5([
0x0000000000000000000000000000000000000000000000000000000000000000n,
0x0000000000000000000000000000000000000000000000000000000000000001n,
0x0000000000000000000000000000000000000000000000000000000000000002n,
0x0000000000000000000000000000000000000000000000000000000000000003n,
0x0000000000000000000000000000000000000000000000000000000000000004n,
]),
[
0x2a918b9c9f9bd7bb509331c81e297b5707f6fc7393dcee1b13901a0b22202e18n,
0x65ebf8671739eeb11fb217f2d5c5bf4a0c3f210e3f3cd3b08b5db75675d797f7n,
0x2cc176fc26bc70737a696a9dfd1b636ce360ee76926d182390cdb7459cf585cen,
0x4dc4e29d283afd2a491fe6aef122b9a968e74eff05341f3cc23fda1781dcb566n,
0x03ff622da276830b9451b88b85e6184fd6ae15c8ab3ee25a5667be8592cce3b1n,
]
);
});
should('poseidonperm_x5_254_3', () => {
const Fp = mod.Fp(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001n);
const t = 3;
const mds = [
[
0x109b7f411ba0e4c9b2b70caf5c36a7b194be7c11ad24378bfedb68592ba8118bn,
0x16ed41e13bb9c0c66ae119424fddbcbc9314dc9fdbdeea55d6c64543dc4903e0n,
0x2b90bba00fca0589f617e7dcbfe82e0df706ab640ceb247b791a93b74e36736dn,
],
[
0x2969f27eed31a480b9c36c764379dbca2cc8fdd1415c3dded62940bcde0bd771n,
0x2e2419f9ec02ec394c9871c832963dc1b89d743c8c7b964029b2311687b1fe23n,
0x101071f0032379b697315876690f053d148d4e109f5fb065c8aacc55a0f89bfan,
],
[
0x143021ec686a3f330d5f9e654638065ce6cd79e28c5b3753326244ee65a1b1a7n,
0x176cc029695ad02582a70eff08a6fd99d057e12e58e7d7b6b16cdfabc8ee2911n,
0x19a3fc0a56702bf417ba7fee3802593fa644470307043f7773279cd71d25d5e0n,
],
];
const roundConstants = poseidon.splitConstants(st3.map(BigInt), t);
const poseidon_x5_254_3 = poseidon.poseidon({
Fp,
t,
roundsFull: 8,
roundsPartial: 57,
mds,
roundConstants,
});
deepStrictEqual(
poseidon_x5_254_3([
0x0000000000000000000000000000000000000000000000000000000000000000n,
0x0000000000000000000000000000000000000000000000000000000000000001n,
0x0000000000000000000000000000000000000000000000000000000000000002n,
]),
[
0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189an,
0x0fca49b798923ab0239de1c9e7a4a9a2210312b6a2f616d18b5a87f9b628ae29n,
0x0e7ae82e40091e63cbd4f16a6d16310b3729d4b6e138fcf54110e2867045a30cn,
]
);
});
should('poseidonperm_x5_254_5', () => {
const Fp = mod.Fp(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001n);
const t = 5;
const mds = [
[
0x251e7fdf99591080080b0af133b9e4369f22e57ace3cd7f64fc6fdbcf38d7da1n,
0x25fb50b65acf4fb047cbd3b1c17d97c7fe26ea9ca238d6e348550486e91c7765n,
0x293d617d7da72102355f39ebf62f91b06deb5325f367a4556ea1e31ed5767833n,
0x104d0295ab00c85e960111ac25da474366599e575a9b7edf6145f14ba6d3c1c4n,
0x0aaa35e2c84baf117dea3e336cd96a39792b3813954fe9bf3ed5b90f2f69c977n,
],
[
0x2a70b9f1d4bbccdbc03e17c1d1dcdb02052903dc6609ea6969f661b2eb74c839n,
0x281154651c921e746315a9934f1b8a1bba9f92ad8ef4b979115b8e2e991ccd7an,
0x28c2be2f8264f95f0b53c732134efa338ccd8fdb9ee2b45fb86a894f7db36c37n,
0x21888041e6febd546d427c890b1883bb9b626d8cb4dc18dcc4ec8fa75e530a13n,
0x14ddb5fada0171db80195b9592d8cf2be810930e3ea4574a350d65e2cbff4941n,
],
[
0x2f69a7198e1fbcc7dea43265306a37ed55b91bff652ad69aa4fa8478970d401dn,
0x001c1edd62645b73ad931ab80e37bbb267ba312b34140e716d6a3747594d3052n,
0x15b98ce93e47bc64ce2f2c96c69663c439c40c603049466fa7f9a4b228bfc32bn,
0x12c7e2adfa524e5958f65be2fbac809fcba8458b28e44d9265051de33163cf9cn,
0x2efc2b90d688134849018222e7b8922eaf67ce79816ef468531ec2de53bbd167n,
],
[
0x0c3f050a6bf5af151981e55e3e1a29a13c3ffa4550bd2514f1afd6c5f721f830n,
0x0dec54e6dbf75205fa75ba7992bd34f08b2efe2ecd424a73eda7784320a1a36en,
0x1c482a25a729f5df20225815034b196098364a11f4d988fb7cc75cf32d8136fan,
0x2625ce48a7b39a4252732624e4ab94360812ac2fc9a14a5fb8b607ae9fd8514an,
0x07f017a7ebd56dd086f7cd4fd710c509ed7ef8e300b9a8bb9fb9f28af710251fn,
],
[
0x2a20e3a4a0e57d92f97c9d6186c6c3ea7c5e55c20146259be2f78c2ccc2e3595n,
0x1049f8210566b51faafb1e9a5d63c0ee701673aed820d9c4403b01feb727a549n,
0x02ecac687ef5b4b568002bd9d1b96b4bef357a69e3e86b5561b9299b82d69c8en,
0x2d3a1aea2e6d44466808f88c9ba903d3bdcb6b58ba40441ed4ebcf11bbe1e37bn,
0x14074bb14c982c81c9ad171e4f35fe49b39c4a7a72dbb6d9c98d803bfed65e64n,
],
];
const roundConstants = poseidon.splitConstants(st4.map(BigInt), t);
const poseidon_x5_254_5 = poseidon.poseidon({
Fp,
t,
roundsFull: 8,
roundsPartial: 60,
mds,
roundConstants,
});
deepStrictEqual(
poseidon_x5_254_5([
0x0000000000000000000000000000000000000000000000000000000000000000n,
0x0000000000000000000000000000000000000000000000000000000000000001n,
0x0000000000000000000000000000000000000000000000000000000000000002n,
0x0000000000000000000000000000000000000000000000000000000000000003n,
0x0000000000000000000000000000000000000000000000000000000000000004n,
]),
[
0x299c867db6c1fdd79dcefa40e4510b9837e60ebb1ce0663dbaa525df65250465n,
0x1148aaef609aa338b27dafd89bb98862d8bb2b429aceac47d86206154ffe053dn,
0x24febb87fed7462e23f6665ff9a0111f4044c38ee1672c1ac6b0637d34f24907n,
0x0eb08f6d809668a981c186beaf6110060707059576406b248e5d9cf6e78b3d3en,
0x07748bc6877c9b82c8b98666ee9d0626ec7f5be4205f79ee8528ef1c4a376fc7n,
]
);
});
// Startadperm is unsupported, since it is non prime field
// ESM is broken.
import url from 'url';
if (import.meta.url === url.pathToFileURL(process.argv[1]).href) {
should.run();
}

1080
test/vectors/poseidon.json Normal file

File diff suppressed because it is too large Load Diff