Skip to content

Commit

Permalink
poseidonfix
Browse files Browse the repository at this point in the history
  • Loading branch information
jbaylina committed Mar 8, 2021
1 parent f4e2097 commit cf853c1
Showing 6 changed files with 42 additions and 35 deletions.
19 changes: 8 additions & 11 deletions circuits/poseidon.circom
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@ template Mix(t, M) {
for (var i=0; i<t; i++) {
lc = 0;
for (var j=0; j<t; j++) {
lc += M[j][i]*in[j];
lc += M[i][j]*in[j];
}
out[i] <== lc;
}
@@ -50,19 +50,19 @@ template Poseidon(nInputs) {
var C[t*(nRoundsF + nRoundsP)] = POSEIDON_C(t);
var M[t][t] = POSEIDON_M(t);

component ark[nRoundsF + nRoundsP - 1];
component sigmaF[nRoundsF - 1][t];
component ark[nRoundsF + nRoundsP];
component sigmaF[nRoundsF][t];
component sigmaP[nRoundsP];
component mix[nRoundsF + nRoundsP - 1];
component mix[nRoundsF + nRoundsP];

var k;

for (var i=0; i<nRoundsF + nRoundsP - 1; i++) {
for (var i=0; i<nRoundsF + nRoundsP; i++) {
ark[i] = Ark(t, C, t*i);
for (var j=0; j<t; j++) {
if (i==0) {
if (j<nInputs) {
ark[i].in[j] <== inputs[j];
if (j>0) {
ark[i].in[j] <== inputs[j-1];
} else {
ark[i].in[j] <== 0;
}
@@ -91,8 +91,5 @@ template Poseidon(nInputs) {
}
}

// last round is done only for the first word, so we do it manually to save constraints
component lastSigmaF = Sigma();
lastSigmaF.in <== mix[nRoundsF + nRoundsP - 2].out[0] + C[t*(nRoundsF + nRoundsP - 1)];
out <== lastSigmaF.out;
out <== mix[nRoundsF + nRoundsP -1].out[0];
}
11 changes: 4 additions & 7 deletions src/poseidon.js
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ function poseidon(inputs) {
const nRoundsF = N_ROUNDS_F;
const nRoundsP = N_ROUNDS_P[t - 2];

let state = [...inputs.map(a => F.e(a)), F.zero];
let state = [F.zero, ...inputs.map(a => F.e(a))];
for (let r = 0; r < nRoundsF + nRoundsP; r++) {
state = state.map((a, i) => F.add(a, C[t - 2][r * t + i]));

@@ -36,12 +36,9 @@ function poseidon(inputs) {
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)
);
}
state = state.map((_, i) =>
state.reduce((acc, a, j) => F.add(acc, F.mul(M[t - 2][i][j], a)), F.zero)
);
}
return F.normalize(state[0]);
}
17 changes: 6 additions & 11 deletions src/poseidon_gencontract.js
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@ function createCode(nInputs) {
function saveM() {
for (let i=0; i<t; i++) {
for (let j=0; j<t; j++) {
C.push(toHex256(M[t-2][j][i]));
C.push(toHex256(M[t-2][i][j]));
C.push((1+i*t+j)*32);
C.mstore();
}
@@ -120,12 +120,14 @@ function createCode(nInputs) {
// The function has a single array param param
// [Selector (4)] [item1 (32)] [item2 (32)] ....
// Stack positions 0-nInputs.
for (let i=0; i<t; i++) {
C.push(0x04+(0x20*(nInputs-i)));
for (let i=0; i<nInputs; i++) {
C.push(0x04+(0x20*(nInputs-i-1)));
C.calldataload();
}

for (let i=0; i<nRoundsF+nRoundsP-1; i++) {
C.push(0);

for (let i=0; i<nRoundsF+nRoundsP; i++) {
ark(i);
if ((i<nRoundsF/2) || (i>=nRoundsP+nRoundsF/2)) {
for (let j=0; j<t; j++) {
@@ -142,13 +144,6 @@ function createCode(nInputs) {
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.mstore(); // Save it to pos 0;
C.push("0x20");
4 changes: 2 additions & 2 deletions test/eddsa_js.js
Original file line number Diff line number Diff line change
@@ -67,12 +67,12 @@ describe("EdDSA js test", function () {
assert.equal(signature.R8[1].toString(),
"15383486972088797283337779941324724402501462225528836549661220478783371668959");
assert.equal(signature.S.toString(),
"1398758333392199195742243841591064350253744445503462896781493968760929513778");
"1672775540645840396591609181675628451599263765380031905495115170613215233181");

const pSignature = eddsa.packSignature(signature);
assert.equal(pSignature.toString("hex"), ""+
"dfedb4315d3f2eb4de2d3c510d7a987dcab67089c8ace06308827bf5bcbe02a2"+
"32f16b0f2f4c4e1169aa59685637e1429b6581a9531d058d65f4ab224eab1703");
"9d043ece562a8f82bfc0adb640c0107a7d3a27c1c7c1a6179a0da73de5c1b203");

const uSignature = eddsa.unpackSignature(pSignature);
assert(eddsa.verifyPoseidon(msg, uSignature, pubKey));
11 changes: 7 additions & 4 deletions test/poseidoncircuit.js
Original file line number Diff line number Diff line change
@@ -21,7 +21,8 @@ describe("Poseidon Circuit test", function () {
const w = await circuit6.calculateWitness({inputs: [1, 2, 0,0,0]}, true);

const res2 = poseidon([1,2,0,0,0]);
assert.equal("3975478831357328722254985704342968745327876719981393787143845259590563829094", res2.toString());

assert.equal("1018317224307729531995786483840663576608797660851238720571059489595066344487", res2.toString());
await circuit6.assertOut(w, {out : res2});
await circuit6.checkConstraints(w);
});
@@ -31,7 +32,7 @@ describe("Poseidon Circuit test", function () {

const res2 = poseidon([3, 4,5,10,23]);

assert.equal("18540626624821144952552691894137986276337186174352554475896834101336254024067", res2.toString());
assert.equal("13034429309846638789535561449942021891039729847501137143363028890275222221409", res2.toString());
await circuit6.assertOut(w, {out : res2});
await circuit6.checkConstraints(w);
});
@@ -41,7 +42,8 @@ describe("Poseidon Circuit test", function () {
const w = await circuit3.calculateWitness({inputs: [1, 2]});

const res2 = poseidon([1,2]);
assert.equal("17117985411748610629288516079940078114952304104811071254131751175361957805920", res2.toString());

assert.equal("7853200120776062878684798364095072458815029376092732009249414926327459813530", res2.toString());
await circuit3.assertOut(w, {out : res2});
await circuit3.checkConstraints(w);
});
@@ -50,7 +52,8 @@ describe("Poseidon Circuit test", function () {
const w = await circuit3.calculateWitness({inputs: [3, 4]});

const res2 = poseidon([3, 4]);
assert.equal("21867347236198497199818917118739170715216974132230970409806500217655788551452", res2.toString());

assert.equal("14763215145315200506921711489642608356394854266165572616578112107564877678998", res2.toString());
await circuit3.assertOut(w, {out : res2});
await circuit3.checkConstraints(w);
});
15 changes: 15 additions & 0 deletions test/poseidonjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const chai = require("chai");
const assert = chai.assert;

const poseidon = require("../src/poseidon.js");

describe("Poseidon Circuit test", function () {
it("Should check constrain reference implementation poseidonperm_x5_254_3", async () => {
const res2 = poseidon([1,2]);
assert.equal("115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a", res2.toString(16));
});
it("Should check constrain reference implementation poseidonperm_x5_254_5", async () => {
const res2 = poseidon([1,2,3,4]);
assert.equal("299c867db6c1fdd79dcefa40e4510b9837e60ebb1ce0663dbaa525df65250465", res2.toString(16));
});
});

0 comments on commit cf853c1

Please sign in to comment.