poseidon contract
This commit is contained in:
parent
528b292da5
commit
436cf45a04
@ -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]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user