poseidon contract

This commit is contained in:
poma 2020-08-10 13:07:22 +03:00
parent 528b292da5
commit 436cf45a04
No known key found for this signature in database
GPG Key ID: BA20CB01FE165657
8 changed files with 55 additions and 49 deletions

@ -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");

@ -47,4 +47,3 @@ function poseidon(inputs) {
} }
module.exports = poseidon; module.exports = poseidon;
module.exports.F = F;

@ -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,34 @@ 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 (typeof nRoundsP === "undefined") nRoundsP = NROUNDSP;
if (typeof t === "undefined") t = T;
const K = Poseidon.getConstants(t, seed, nRoundsP + nRoundsF); if (( nInputs<1) || (nInputs>8)) throw new Error("Invalid number of inputs. Must be 1<=nInputs<=8");
const M = Poseidon.getMatrix(t, seed, nRoundsP + nRoundsF); const t = nInputs + 1;
const nRoundsF = N_ROUNDS_F;
const nRoundsP = N_ROUNDS_P[t - 2];
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 +110,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*(5-i))); C.push(0x44+(0x20*(5-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 +137,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,13 @@
const poseidonGenContract = require("./poseidon_gencontract"); const poseidonGenContract = require("./poseidon_gencontract");
if (process.argv.length != 3) {
console.log("Usage: node poseidon_gencontract.js [numberOfInputs]");
process.exit(1);
}
console.log(poseidonGenContract.createCode(6, 8, 57)); const nInputs = Number(process.argv[2]);
console.log(nInputs);
console.log(poseidonGenContract.createCode(nInputs));

@ -1,6 +1,8 @@
const poseidon = require("./poseidon"); const poseidon = require("./poseidon");
const bigInt = require("snarkjs").bigInt; const bigInt = require("snarkjs").bigInt;
//const F = new ZqField(Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
exports.hash0 = function (left, right) { exports.hash0 = function (left, right) {
return poseidon([left, right]); return poseidon([left, right]);
}; };
@ -9,4 +11,4 @@ exports.hash1 = function(key, value) {
return poseidon([key, value, bigInt.one]); return poseidon([key, value, bigInt.one]);
}; };
exports.F = poseidon.F; //exports.F = poseidon.F;

@ -68,12 +68,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));

@ -26,13 +26,13 @@ describe("Poseidon Smart contract test", function () {
poseidon2 = await C.deploy({ poseidon2 = await C.deploy({
data: poseidonGenContract.createCode(2) data: poseidonGenContract.createCode(2)
}).send({ }).send({
gas: 2500000, gas: 5000000,
from: accounts[0] from: accounts[0]
}); });
poseidon4 = await C.deploy({ poseidon4 = await C.deploy({
data: poseidonGenContract.createCode(4) data: poseidonGenContract.createCode(4)
}).send({ }).send({
gas: 2500000, gas: 5000000,
from: accounts[0] from: accounts[0]
}); });
}); });