New Version of Poseidon
This commit is contained in:
parent
5269afee0a
commit
86c6a2a6f5
@ -780,7 +780,7 @@ Implementation of Poseidon hash function (LINK)
|
|||||||
- BENCHMARKS
|
- BENCHMARKS
|
||||||
- EXAMPLE
|
- EXAMPLE
|
||||||
|
|
||||||
- `Ark(t, C)`
|
- `Ark(t, C, r)`
|
||||||
|
|
||||||
- DESCRIPTION
|
- DESCRIPTION
|
||||||
- SCHEMA
|
- SCHEMA
|
||||||
@ -798,7 +798,7 @@ Implementation of Poseidon hash function (LINK)
|
|||||||
- BENCHMARKS
|
- BENCHMARKS
|
||||||
- EXAMPLE
|
- EXAMPLE
|
||||||
|
|
||||||
- `Poseidon(nInputs, t, nRoundsF, nRoundsP)`
|
- `Poseidon(nInputs)`
|
||||||
|
|
||||||
- DESCRIPTION
|
- DESCRIPTION
|
||||||
- SCHEMA
|
- SCHEMA
|
||||||
|
@ -51,7 +51,7 @@ template EdDSAPoseidonVerifier() {
|
|||||||
|
|
||||||
// Calculate the h = H(R,A, msg)
|
// Calculate the h = H(R,A, msg)
|
||||||
|
|
||||||
component hash = Poseidon(5, 6, 8, 57);
|
component hash = Poseidon(5);
|
||||||
|
|
||||||
hash.inputs[0] <== R8x;
|
hash.inputs[0] <== R8x;
|
||||||
hash.inputs[1] <== R8y;
|
hash.inputs[1] <== R8y;
|
||||||
|
File diff suppressed because one or more lines are too long
@ -29,7 +29,7 @@ template SMTHash1() {
|
|||||||
signal input value;
|
signal input value;
|
||||||
signal output out;
|
signal output out;
|
||||||
|
|
||||||
component h = Poseidon(3, 6, 8, 57); // Constant
|
component h = Poseidon(3); // Constant
|
||||||
h.inputs[0] <== key;
|
h.inputs[0] <== key;
|
||||||
h.inputs[1] <== value;
|
h.inputs[1] <== value;
|
||||||
h.inputs[2] <== 1;
|
h.inputs[2] <== 1;
|
||||||
@ -48,7 +48,7 @@ template SMTHash2() {
|
|||||||
signal input R;
|
signal input R;
|
||||||
signal output out;
|
signal output out;
|
||||||
|
|
||||||
component h = Poseidon(2, 6, 8, 57); // Constant
|
component h = Poseidon(2); // Constant
|
||||||
h.inputs[0] <== L;
|
h.inputs[0] <== L;
|
||||||
h.inputs[1] <== R;
|
h.inputs[1] <== R;
|
||||||
|
|
||||||
|
@ -112,8 +112,7 @@ function signPoseidon(prv, msg) {
|
|||||||
const Fr = new F1Field(babyJub.subOrder);
|
const Fr = new F1Field(babyJub.subOrder);
|
||||||
r = Fr.e(r);
|
r = Fr.e(r);
|
||||||
const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
|
const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
|
||||||
const hash = poseidon.createHash(6, 8, 57);
|
const hm = poseidon([R8[0], R8[1], A[0], A[1], msg]);
|
||||||
const hm = hash([R8[0], R8[1], A[0], A[1], msg]);
|
|
||||||
const S = Fr.add(r , Fr.mul(hm, s));
|
const S = Fr.add(r , Fr.mul(hm, s));
|
||||||
return {
|
return {
|
||||||
R8: R8,
|
R8: R8,
|
||||||
@ -180,8 +179,7 @@ function verifyPoseidon(msg, sig, A) {
|
|||||||
if (!babyJub.inCurve(A)) return false;
|
if (!babyJub.inCurve(A)) return false;
|
||||||
if (sig.S>= babyJub.subOrder) return false;
|
if (sig.S>= babyJub.subOrder) return false;
|
||||||
|
|
||||||
const hash = poseidon.createHash(6, 8, 57);
|
const hm = poseidon([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
|
||||||
const hm = hash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
|
|
||||||
|
|
||||||
const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
|
const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
|
||||||
let Pright = babyJub.mulPointEscalar(A, Scalar.mul(hm, 8));
|
let Pright = babyJub.mulPointEscalar(A, Scalar.mul(hm, 8));
|
||||||
|
@ -154,6 +154,17 @@ class Contract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
push(data) {
|
push(data) {
|
||||||
|
if (typeof data === "number") {
|
||||||
|
let isNeg;
|
||||||
|
if (data<0) {
|
||||||
|
isNeg = true;
|
||||||
|
data = -data;
|
||||||
|
}
|
||||||
|
data = data.toString(16);
|
||||||
|
if (data.length % 2 == 1) data = "0" + data;
|
||||||
|
data = "0x" + data;
|
||||||
|
if (isNeg) data = "-"+data;
|
||||||
|
}
|
||||||
const d = Web3Utils.hexToBytes(Web3Utils.toHex(data));
|
const d = Web3Utils.hexToBytes(Web3Utils.toHex(data));
|
||||||
if (d.length == 0 || d.length > 32) {
|
if (d.length == 0 || d.length > 32) {
|
||||||
throw new Error("Assertion failed");
|
throw new Error("Assertion failed");
|
||||||
|
140
src/poseidon.js
140
src/poseidon.js
@ -1,121 +1,49 @@
|
|||||||
const Scalar = require("ffjavascript").Scalar;
|
|
||||||
const blake2b = require("blake2b");
|
|
||||||
const assert = require("assert");
|
const assert = require("assert");
|
||||||
|
const Scalar = require("ffjavascript").Scalar;
|
||||||
const ZqField = require("ffjavascript").ZqField;
|
const ZqField = require("ffjavascript").ZqField;
|
||||||
const utils = require("ffjavascript").utils;
|
const { unstringifyBigInts } = require("ffjavascript").utils;
|
||||||
|
|
||||||
|
// Prime 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
|
||||||
const F = new ZqField(Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
|
const F = new ZqField(Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
|
||||||
exports.F = F;
|
|
||||||
|
|
||||||
const SEED = "poseidon";
|
// Parameters are generated by a reference script https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/generate_parameters_grain.sage
|
||||||
const NROUNDSF = 8;
|
// Used like so: sage generate_parameters_grain.sage 1 0 254 2 8 56 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
|
||||||
const NROUNDSP = 57;
|
const { C, M } = unstringifyBigInts(require("./poseidon_constants.json"));
|
||||||
const T = 6;
|
|
||||||
|
|
||||||
function getPseudoRandom(seed, n) {
|
// Using recommended parameters from whitepaper https://eprint.iacr.org/2019/458.pdf (table 2, table 8)
|
||||||
const res = [];
|
// Generated by https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/calc_round_numbers.py
|
||||||
let input = Buffer.from(seed);
|
// And rounded up to nearest integer that divides by t
|
||||||
let h = blake2b(32).update(input).digest();
|
const N_ROUNDS_F = 8;
|
||||||
while (res.length<n) {
|
const N_ROUNDS_P = [56, 57, 56, 60, 60, 63, 64, 63];
|
||||||
const n = F.normalize(utils.leBuff2int(Buffer.from(h)));
|
|
||||||
res.push(n);
|
|
||||||
h = blake2b(32).update(h).digest();
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
const pow5 = a => F.mul(a, F.square(F.square(a, a)));
|
||||||
}
|
|
||||||
|
|
||||||
function allDifferent(v) {
|
function poseidon(inputs) {
|
||||||
for (let i=0; i<v.length; i++) {
|
|
||||||
if (F.isZero(v[i])) return false;
|
|
||||||
for (let j=i+1; j<v.length; j++) {
|
|
||||||
if (F.eq(v[i],v[j])) return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.getMatrix = (t, seed, nRounds) => {
|
|
||||||
if (typeof seed === "undefined") seed = SEED;
|
|
||||||
if (typeof nRounds === "undefined") nRounds = NROUNDSF + NROUNDSP;
|
|
||||||
if (typeof t === "undefined") t = T;
|
|
||||||
assert(t<=6); // Force the same matrix for all.
|
|
||||||
t=6;
|
|
||||||
let nonce = "0000";
|
|
||||||
let cmatrix = getPseudoRandom(seed+"_matrix_"+nonce, t*2);
|
|
||||||
while (!allDifferent(cmatrix)) {
|
|
||||||
nonce = (Number(nonce)+1)+"";
|
|
||||||
while(nonce.length<4) nonce = "0"+nonce;
|
|
||||||
cmatrix = getPseudoRandom(seed+"_matrix_"+nonce, t*2);
|
|
||||||
}
|
|
||||||
|
|
||||||
const M = new Array(t);
|
|
||||||
for (let i=0; i<t; i++) {
|
|
||||||
M[i] = new Array(t);
|
|
||||||
for (let j=0; j<t; j++) {
|
|
||||||
M[i][j] = F.normalize(F.inv(F.sub(cmatrix[i], cmatrix[t+j])));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return M;
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.getConstants = (t, seed, nRounds) => {
|
|
||||||
if (typeof seed === "undefined") seed = SEED;
|
|
||||||
if (typeof nRounds === "undefined") nRounds = NROUNDSF + NROUNDSP;
|
|
||||||
if (typeof t === "undefined") t = T;
|
|
||||||
const cts = getPseudoRandom(seed+"_constants", nRounds);
|
|
||||||
return cts;
|
|
||||||
};
|
|
||||||
|
|
||||||
function ark(state, c) {
|
|
||||||
for (let j=0; j<state.length; j++ ) {
|
|
||||||
state[j] = F.add(state[j], c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function sigma(a) {
|
|
||||||
return F.mul(a, F.square(F.square(a,a)));
|
|
||||||
}
|
|
||||||
|
|
||||||
function mix(state, M) {
|
|
||||||
const newState = new Array(state.length);
|
|
||||||
for (let i=0; i<state.length; i++) {
|
|
||||||
newState[i] = F.zero;
|
|
||||||
for (let j=0; j<state.length; j++) {
|
|
||||||
newState[i] = F.add(newState[i], F.mul(M[i][j], state[j]) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (let i=0; i<state.length; i++) state[i] = newState[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.createHash = (t, nRoundsF, nRoundsP, seed) => {
|
|
||||||
|
|
||||||
if (typeof seed === "undefined") seed = SEED;
|
|
||||||
if (typeof nRoundsF === "undefined") nRoundsF = NROUNDSF;
|
|
||||||
if (typeof nRoundsP === "undefined") nRoundsP = NROUNDSP;
|
|
||||||
if (typeof t === "undefined") t = T;
|
|
||||||
|
|
||||||
assert(nRoundsF % 2 == 0);
|
|
||||||
const C = exports.getConstants(t, seed, nRoundsF + nRoundsP);
|
|
||||||
const M = exports.getMatrix(t, seed, nRoundsF + nRoundsP);
|
|
||||||
return function(inputs) {
|
|
||||||
let state = [];
|
|
||||||
assert(inputs.length <= t);
|
|
||||||
assert(inputs.length > 0);
|
assert(inputs.length > 0);
|
||||||
for (let i=0; i<inputs.length; i++) state[i] = F.e(inputs[i]);
|
assert(inputs.length < N_ROUNDS_P.length - 1);
|
||||||
for (let i=inputs.length; i<t; i++) state[i] = F.zero;
|
|
||||||
|
|
||||||
for (let i=0; i< nRoundsF + nRoundsP; i++) {
|
const t = inputs.length + 1;
|
||||||
ark(state, C[i]);
|
const nRoundsF = N_ROUNDS_F;
|
||||||
if ((i<nRoundsF/2) || (i >= nRoundsF/2 + nRoundsP)) {
|
const nRoundsP = N_ROUNDS_P[t - 2];
|
||||||
for (let j=0; j<t; j++) state[j] = sigma(state[j]);
|
|
||||||
|
let state = [...inputs.map(a => F.e(a)), F.zero];
|
||||||
|
for (let r = 0; r < nRoundsF + nRoundsP; r++) {
|
||||||
|
state = state.map((a, i) => F.add(a, C[t - 2][r * t + i]));
|
||||||
|
|
||||||
|
if (r < nRoundsF / 2 || r >= nRoundsF / 2 + nRoundsP) {
|
||||||
|
state = state.map(a => pow5(a));
|
||||||
} else {
|
} else {
|
||||||
state[0] = sigma(state[0]);
|
state[0] = pow5(state[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// no matrix multiplication in the last round
|
||||||
|
if (r < nRoundsF + nRoundsP - 1) {
|
||||||
|
state = state.map((_, i) =>
|
||||||
|
state.reduce((acc, a, j) => F.add(acc, F.mul(M[t - 2][j][i], a)), F.zero)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
mix(state, M);
|
|
||||||
}
|
}
|
||||||
return F.normalize(state[0]);
|
return F.normalize(state[0]);
|
||||||
};
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = poseidon;
|
||||||
|
3449
src/poseidon_constants.json
Normal file
3449
src/poseidon_constants.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,14 +2,13 @@
|
|||||||
// License: LGPL-3.0+
|
// License: LGPL-3.0+
|
||||||
//
|
//
|
||||||
|
|
||||||
const Poseidon = require("./poseidon.js");
|
|
||||||
|
|
||||||
const Contract = require("./evmasm");
|
const Contract = require("./evmasm");
|
||||||
|
const { unstringifyBigInts } = require("ffjavascript").utils;
|
||||||
|
|
||||||
const SEED = "poseidon";
|
const { C:K, M } = unstringifyBigInts(require("./poseidon_constants.json"));
|
||||||
const NROUNDSF = 8;
|
|
||||||
const NROUNDSP = 57;
|
const N_ROUNDS_F = 8;
|
||||||
const T = 6;
|
const N_ROUNDS_P = [56, 57, 56, 60, 60, 63, 64, 63];
|
||||||
|
|
||||||
function toHex256(a) {
|
function toHex256(a) {
|
||||||
let S = a.toString(16);
|
let S = a.toString(16);
|
||||||
@ -17,38 +16,38 @@ function toHex256(a) {
|
|||||||
return "0x" + S;
|
return "0x" + S;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createCode(t, nRoundsF, nRoundsP, seed) {
|
function createCode(nInputs) {
|
||||||
if (typeof seed === "undefined") seed = SEED;
|
|
||||||
if (typeof nRoundsF === "undefined") nRoundsF = NROUNDSF;
|
if (( nInputs<1) || (nInputs>8)) throw new Error("Invalid number of inputs. Must be 1<=nInputs<=8");
|
||||||
if (typeof nRoundsP === "undefined") nRoundsP = NROUNDSP;
|
const t = nInputs + 1;
|
||||||
if (typeof t === "undefined") t = T;
|
const nRoundsF = N_ROUNDS_F;
|
||||||
|
const nRoundsP = N_ROUNDS_P[t - 2];
|
||||||
|
|
||||||
|
// const nRoundsF = 2;
|
||||||
|
// const nRoundsP = 2;
|
||||||
|
|
||||||
const K = Poseidon.getConstants(t, seed, nRoundsP + nRoundsF);
|
|
||||||
const M = Poseidon.getMatrix(t, seed, nRoundsP + nRoundsF);
|
|
||||||
|
|
||||||
const C = new Contract();
|
const C = new Contract();
|
||||||
|
|
||||||
function saveM() {
|
function saveM() {
|
||||||
for (let i=0; i<t; i++) {
|
for (let i=0; i<t; i++) {
|
||||||
for (let j=0; j<t; j++) {
|
for (let j=0; j<t; j++) {
|
||||||
C.push(toHex256(M[i][j]));
|
C.push(toHex256(M[t-2][j][i]));
|
||||||
C.push((1+i*t+j)*32);
|
C.push((1+i*t+j)*32);
|
||||||
C.mstore();
|
C.mstore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function ark(r) {
|
function ark(r) { // st, q
|
||||||
C.push(toHex256(K[r])); // K, st, q
|
|
||||||
for (let i=0; i<t; i++) {
|
for (let i=0; i<t; i++) {
|
||||||
C.dup(1+t); // q, K, st, q
|
C.dup(t); // q, st, q
|
||||||
C.dup(1); // K, q, K, st, q
|
C.push(toHex256(K[t-2][r*t+i])); // K, q, st, q
|
||||||
C.dup(3+i); // st[i], K, q, K, st, q
|
C.dup(2+i); // st[i], K, q, st, q
|
||||||
C.addmod(); // newSt[i], K, st, q
|
C.addmod(); // newSt[i], st, q
|
||||||
C.swap(2 + i); // xx, K, st, q
|
C.swap(1 + i); // xx, st, q
|
||||||
C.pop();
|
C.pop();
|
||||||
}
|
}
|
||||||
C.pop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function sigma(p) {
|
function sigma(p) {
|
||||||
@ -115,17 +114,17 @@ function createCode(t, nRoundsF, nRoundsP, seed) {
|
|||||||
|
|
||||||
C.push("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"); // q
|
C.push("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"); // q
|
||||||
|
|
||||||
// Load 6 values from the call data.
|
// Load t values from the call data.
|
||||||
// The function has a single array param param
|
// The function has a single array param param
|
||||||
// [Selector (4)] [Pointer (32)][Length (32)] [data1 (32)] ....
|
// [Selector (4)] [Pointer (32)][Length (32)] [data1 (32)] ....
|
||||||
// We ignore the pointer and the length and just load 6 values to the state
|
// We ignore the pointer and the length and just load t values to the state
|
||||||
// (Stack positions 0-5) If the array is shorter, we just set zeros.
|
// (Stack positions 0-{t-1}) If the array is shorter, we just set zeros.
|
||||||
for (let i=0; i<t; i++) {
|
for (let i=0; i<t; i++) {
|
||||||
C.push(0x44+(0x20*(t-1-i)));
|
C.push(0x44+(0x20*(t-1-i)));
|
||||||
C.calldataload();
|
C.calldataload();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i=0; i<nRoundsF+nRoundsP; i++) {
|
for (let i=0; i<nRoundsF+nRoundsP-1; i++) {
|
||||||
ark(i);
|
ark(i);
|
||||||
if ((i<nRoundsF/2) || (i>=nRoundsP+nRoundsF/2)) {
|
if ((i<nRoundsF/2) || (i>=nRoundsP+nRoundsF/2)) {
|
||||||
for (let j=0; j<t; j++) {
|
for (let j=0; j<t; j++) {
|
||||||
@ -142,6 +141,13 @@ function createCode(t, nRoundsF, nRoundsP, seed) {
|
|||||||
C.label(strLabel);
|
C.label(strLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
C.push(toHex256(K[t-2][(nRoundsF+nRoundsP-1)*t])); // K, st, q
|
||||||
|
C.dup(t+1); // q, K, st, q
|
||||||
|
C.swap(2); // st[0], K, q, st\st[0]
|
||||||
|
C.addmod(); // st q
|
||||||
|
|
||||||
|
sigma(0);
|
||||||
|
|
||||||
C.push("0x00");
|
C.push("0x00");
|
||||||
C.mstore(); // Save it to pos 0;
|
C.mstore(); // Save it to pos 0;
|
||||||
C.push("0x20");
|
C.push("0x20");
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
const Poseidon = require("./poseidon.js");
|
|
||||||
|
|
||||||
const C = Poseidon.getConstants();
|
|
||||||
|
|
||||||
let S = "[\n";
|
|
||||||
|
|
||||||
for (let i=0; i<C.length; i++) {
|
|
||||||
S = S + " " + C[i].toString();
|
|
||||||
if (i<C.length-1) S = S + ",";
|
|
||||||
S = S + "\n";
|
|
||||||
}
|
|
||||||
S=S+ "]\n";
|
|
||||||
|
|
||||||
console.log(S);
|
|
@ -1,5 +1,5 @@
|
|||||||
const poseidonGenContract = require("./poseidon_gencontract");
|
const poseidonGenContract = require("./poseidon_gencontract");
|
||||||
|
|
||||||
|
|
||||||
console.log(poseidonGenContract.createCode(6, 8, 57));
|
console.log(poseidonGenContract.createCode(5));
|
||||||
|
|
||||||
|
@ -1,13 +1,18 @@
|
|||||||
const Poseidon = require("./poseidon");
|
|
||||||
|
|
||||||
const hash = Poseidon.createHash(6, 8, 57);
|
const ZqField = require("ffjavascript").ZqField;
|
||||||
|
const Scalar = require("ffjavascript").Scalar;
|
||||||
|
|
||||||
|
const poseidon = require("./poseidon");
|
||||||
|
|
||||||
|
const F = new ZqField(Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
|
||||||
|
|
||||||
|
|
||||||
exports.hash0 = function (left, right) {
|
exports.hash0 = function (left, right) {
|
||||||
return hash([left, right]);
|
return poseidon([left, right]);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.hash1 = function(key, value) {
|
exports.hash1 = function(key, value) {
|
||||||
return hash([key, value, Poseidon.F.one]);
|
return poseidon([key, value, F.one]);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.F = Poseidon.F;
|
exports.F = F;
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
|
|
||||||
const F = require("./poseidon.js").F;
|
|
||||||
const Scalar = require("ffjavascript").Scalar;
|
const Scalar = require("ffjavascript").Scalar;
|
||||||
const utils = require("ffjavascript").utils;
|
const ZqField = require("ffjavascript").ZqField;
|
||||||
|
|
||||||
|
// Prime 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
|
||||||
|
const F = new ZqField(Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
|
||||||
|
|
||||||
class SMTMemDb {
|
class SMTMemDb {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
include "../../circuits/poseidon.circom"
|
include "../../circuits/poseidon.circom"
|
||||||
|
|
||||||
component main = Poseidon(2, 3, 8, 57);
|
component main = Poseidon(2);
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
include "../../circuits/poseidon.circom"
|
include "../../circuits/poseidon.circom"
|
||||||
|
|
||||||
component main = Poseidon(2, 6, 8, 57);
|
component main = Poseidon(5);
|
||||||
|
@ -67,12 +67,12 @@ describe("EdDSA js test", function () {
|
|||||||
assert.equal(signature.R8[1].toString(),
|
assert.equal(signature.R8[1].toString(),
|
||||||
"15383486972088797283337779941324724402501462225528836549661220478783371668959");
|
"15383486972088797283337779941324724402501462225528836549661220478783371668959");
|
||||||
assert.equal(signature.S.toString(),
|
assert.equal(signature.S.toString(),
|
||||||
"248298168863866362217836334079793350221620631973732197668910946177382043688");
|
"1398758333392199195742243841591064350253744445503462896781493968760929513778");
|
||||||
|
|
||||||
const pSignature = eddsa.packSignature(signature);
|
const pSignature = eddsa.packSignature(signature);
|
||||||
assert.equal(pSignature.toString("hex"), ""+
|
assert.equal(pSignature.toString("hex"), ""+
|
||||||
"dfedb4315d3f2eb4de2d3c510d7a987dcab67089c8ace06308827bf5bcbe02a2"+
|
"dfedb4315d3f2eb4de2d3c510d7a987dcab67089c8ace06308827bf5bcbe02a2"+
|
||||||
"28506bce274aa1b3f7e7c2fd7e4fe09bff8f9aa37a42def7994e98f322888c00");
|
"32f16b0f2f4c4e1169aa59685637e1429b6581a9531d058d65f4ab224eab1703");
|
||||||
|
|
||||||
const uSignature = eddsa.unpackSignature(pSignature);
|
const uSignature = eddsa.unpackSignature(pSignature);
|
||||||
assert(eddsa.verifyPoseidon(msg, uSignature, pubKey));
|
assert(eddsa.verifyPoseidon(msg, uSignature, pubKey));
|
||||||
|
@ -1,21 +1,11 @@
|
|||||||
const chai = require("chai");
|
const chai = require("chai");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
var blake2b = require("blake2b");
|
|
||||||
const tester = require("circom").tester;
|
const tester = require("circom").tester;
|
||||||
|
|
||||||
const poseidon = require("../src/poseidon.js");
|
const poseidon = require("../src/poseidon.js");
|
||||||
|
|
||||||
const assert = chai.assert;
|
const assert = chai.assert;
|
||||||
|
|
||||||
describe("Blake2b version test", function() {
|
|
||||||
it("Should give the expected output for blake2b version", async () => {
|
|
||||||
var output = new Uint8Array(32);
|
|
||||||
var input = Buffer.from("poseidon_constants");
|
|
||||||
const h = blake2b(output.length).update(input).digest("hex");
|
|
||||||
assert.equal("e57ba154fb2c47811dc1a2369b27e25a44915b4e4ece4eb8ec74850cb78e01b1", h);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Poseidon Circuit test", function () {
|
describe("Poseidon Circuit test", function () {
|
||||||
let circuit6;
|
let circuit6;
|
||||||
let circuit3;
|
let circuit3;
|
||||||
@ -28,24 +18,20 @@ describe("Poseidon Circuit test", function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("Should check constrain of hash([1, 2]) t=6", async () => {
|
it("Should check constrain of hash([1, 2]) t=6", async () => {
|
||||||
const w = await circuit6.calculateWitness({inputs: [1, 2]}, true);
|
const w = await circuit6.calculateWitness({inputs: [1, 2, 0,0,0]}, true);
|
||||||
|
|
||||||
const hash = poseidon.createHash(6, 8, 57);
|
const res2 = poseidon([1,2,0,0,0]);
|
||||||
|
assert.equal("3975478831357328722254985704342968745327876719981393787143845259590563829094", res2.toString());
|
||||||
const res2 = hash([1,2]);
|
|
||||||
assert.equal("12242166908188651009877250812424843524687801523336557272219921456462821518061", res2.toString());
|
|
||||||
await circuit6.assertOut(w, {out : res2});
|
await circuit6.assertOut(w, {out : res2});
|
||||||
await circuit6.checkConstraints(w);
|
await circuit6.checkConstraints(w);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should check constrain of hash([3, 4]) t=6", async () => {
|
it("Should check constrain of hash([3, 4]) t=6", async () => {
|
||||||
const w = await circuit6.calculateWitness({inputs: [3, 4]});
|
const w = await circuit6.calculateWitness({inputs: [3, 4,5,10,23]});
|
||||||
|
|
||||||
const hash = poseidon.createHash(6, 8, 57);
|
const res2 = poseidon([3, 4,5,10,23]);
|
||||||
|
|
||||||
const res2 = hash([3, 4]);
|
assert.equal("18540626624821144952552691894137986276337186174352554475896834101336254024067", res2.toString());
|
||||||
|
|
||||||
assert.equal("17185195740979599334254027721507328033796809509313949281114643312710535000993", res2.toString());
|
|
||||||
await circuit6.assertOut(w, {out : res2});
|
await circuit6.assertOut(w, {out : res2});
|
||||||
await circuit6.checkConstraints(w);
|
await circuit6.checkConstraints(w);
|
||||||
});
|
});
|
||||||
@ -54,10 +40,8 @@ describe("Poseidon Circuit test", function () {
|
|||||||
it("Should check constrain of hash([1, 2]) t=3", async () => {
|
it("Should check constrain of hash([1, 2]) t=3", async () => {
|
||||||
const w = await circuit3.calculateWitness({inputs: [1, 2]});
|
const w = await circuit3.calculateWitness({inputs: [1, 2]});
|
||||||
|
|
||||||
const hash = poseidon.createHash(3, 8, 57);
|
const res2 = poseidon([1,2]);
|
||||||
|
assert.equal("17117985411748610629288516079940078114952304104811071254131751175361957805920", res2.toString());
|
||||||
const res2 = hash([1,2]);
|
|
||||||
assert.equal("2104035019328376391822106787753454168168617545136592089411833517434990977743", res2.toString());
|
|
||||||
await circuit3.assertOut(w, {out : res2});
|
await circuit3.assertOut(w, {out : res2});
|
||||||
await circuit3.checkConstraints(w);
|
await circuit3.checkConstraints(w);
|
||||||
});
|
});
|
||||||
@ -65,10 +49,8 @@ describe("Poseidon Circuit test", function () {
|
|||||||
it("Should check constrain of hash([3, 4]) t=3", async () => {
|
it("Should check constrain of hash([3, 4]) t=3", async () => {
|
||||||
const w = await circuit3.calculateWitness({inputs: [3, 4]});
|
const w = await circuit3.calculateWitness({inputs: [3, 4]});
|
||||||
|
|
||||||
const hash = poseidon.createHash(3, 8, 57);
|
const res2 = poseidon([3, 4]);
|
||||||
|
assert.equal("21867347236198497199818917118739170715216974132230970409806500217655788551452", res2.toString());
|
||||||
const res2 = hash([3, 4]);
|
|
||||||
assert.equal("12456141564250880945411182508630957604732712316993112736876413121277158512223", res2.toString());
|
|
||||||
await circuit3.assertOut(w, {out : res2});
|
await circuit3.assertOut(w, {out : res2});
|
||||||
await circuit3.checkConstraints(w);
|
await circuit3.checkConstraints(w);
|
||||||
});
|
});
|
||||||
|
@ -2,7 +2,7 @@ const ganache = require("ganache-cli");
|
|||||||
const Web3 = require("web3");
|
const Web3 = require("web3");
|
||||||
const chai = require("chai");
|
const chai = require("chai");
|
||||||
const poseidonGenContract = require("../src/poseidon_gencontract.js");
|
const poseidonGenContract = require("../src/poseidon_gencontract.js");
|
||||||
const Poseidon = require("../src/poseidon.js");
|
const poseidon = require("../src/poseidon.js");
|
||||||
|
|
||||||
const assert = chai.assert;
|
const assert = chai.assert;
|
||||||
const log = (msg) => { if (process.env.MOCHA_VERBOSE) console.log(msg); };
|
const log = (msg) => { if (process.env.MOCHA_VERBOSE) console.log(msg); };
|
||||||
@ -24,28 +24,26 @@ describe("Poseidon Smart contract test", function () {
|
|||||||
const C = new web3.eth.Contract(poseidonGenContract.abi);
|
const C = new web3.eth.Contract(poseidonGenContract.abi);
|
||||||
|
|
||||||
poseidon6 = await C.deploy({
|
poseidon6 = await C.deploy({
|
||||||
data: poseidonGenContract.createCode(6)
|
data: poseidonGenContract.createCode(5)
|
||||||
}).send({
|
}).send({
|
||||||
gas: 2500000,
|
gas: 5000000,
|
||||||
from: accounts[0]
|
from: accounts[0]
|
||||||
});
|
});
|
||||||
poseidon3 = await C.deploy({
|
poseidon3 = await C.deploy({
|
||||||
data: poseidonGenContract.createCode(3)
|
data: poseidonGenContract.createCode(2)
|
||||||
}).send({
|
}).send({
|
||||||
gas: 2500000,
|
gas: 5000000,
|
||||||
from: accounts[0]
|
from: accounts[0]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Shold calculate the poseidon correctly t=6", async () => {
|
it("Shold calculate the poseidon correctly t=6", async () => {
|
||||||
|
|
||||||
const res = await poseidon6.methods.poseidon([1,2]).call();
|
const res = await poseidon6.methods.poseidon([1,2, 0, 0, 0]).call();
|
||||||
|
|
||||||
// console.log("Cir: " + bigInt(res.toString(16)).toString(16));
|
// console.log("Cir: " + bigInt(res.toString(16)).toString(16));
|
||||||
|
|
||||||
const hash = Poseidon.createHash(6, 8, 57);
|
const res2 = poseidon([1,2, 0, 0, 0]);
|
||||||
|
|
||||||
const res2 = hash([1,2]);
|
|
||||||
// console.log("Ref: " + bigInt(res2).toString(16));
|
// console.log("Ref: " + bigInt(res2).toString(16));
|
||||||
|
|
||||||
assert.equal(res.toString(), res2.toString());
|
assert.equal(res.toString(), res2.toString());
|
||||||
@ -56,9 +54,7 @@ describe("Poseidon Smart contract test", function () {
|
|||||||
|
|
||||||
// console.log("Cir: " + bigInt(res.toString(16)).toString(16));
|
// console.log("Cir: " + bigInt(res.toString(16)).toString(16));
|
||||||
|
|
||||||
const hash = Poseidon.createHash(3, 8, 57);
|
const res2 = poseidon([1,2]);
|
||||||
|
|
||||||
const res2 = hash([1,2]);
|
|
||||||
// console.log("Ref: " + bigInt(res2).toString(16));
|
// console.log("Ref: " + bigInt(res2).toString(16));
|
||||||
|
|
||||||
assert.equal(res.toString(), res2.toString());
|
assert.equal(res.toString(), res2.toString());
|
||||||
|
Loading…
Reference in New Issue
Block a user