New Version of Poseidon
This commit is contained in:
parent
5269afee0a
commit
86c6a2a6f5
@ -49,7 +49,7 @@ Folder containing the circuit implementation of Sparse Merkle Trees.
|
||||
- OUTPUT
|
||||
- BENCHMARKS
|
||||
- EXAMPLE
|
||||
|
||||
|
||||
### babyjub
|
||||
|
||||
Arithmetic on [Baby Jubjub elliptic curve](https://github.com/barryWhiteHat/baby_jubjub) in twisted Edwards form. (TODO: Expose here the characteristics of the curve?)
|
||||
@ -58,22 +58,22 @@ Arithmetic on [Baby Jubjub elliptic curve](https://github.com/barryWhiteHat/baby
|
||||
- `BabyAdd()`
|
||||
|
||||
- DESCRIPTION
|
||||
|
||||
|
||||
It adds two points on the Baby Jubjub curve. More specifically, given two points P1 = (`x1`, `y1`) and P2 = (`x2`, `y2`) it returns a point P3 = (`xout`, `yout`) such that
|
||||
|
||||
(`xout`, `yout`) = (`x1`,`y1`) + (`x2`,`y2`)
|
||||
(`xout`, `yout`) = (`x1`,`y1`) + (`x2`,`y2`)
|
||||
= ((`x1y2`+`y1x2`)/(1+`dx1x2y1y2`)),(`y1y2`-`ax1x2`)/(1-`dx1x2y1y2`))
|
||||
|
||||
|
||||
- SCHEMA
|
||||
```
|
||||
var a var d
|
||||
| |
|
||||
| |
|
||||
______v_________v_______
|
||||
______v_________v_______
|
||||
input x1 ----> | |
|
||||
input y1 ----> | BabyAdd() | ----> output xout
|
||||
input x2 ----> | | ----> output yout
|
||||
input y2 ----> |________________________|
|
||||
input y2 ----> |________________________|
|
||||
```
|
||||
|
||||
- INPUTS
|
||||
@ -84,16 +84,16 @@ Arithmetic on [Baby Jubjub elliptic curve](https://github.com/barryWhiteHat/baby
|
||||
| `y1` | Bigint | Field element of Fp | Second coordinate of a point (x1, y1) on E. |
|
||||
| `x2` | Bigint | Field element of Fp | First coordinate of a point (x2, y2) on E. |
|
||||
| `y2` | Bigint | Field element of Fp | Second coordinate of a point (x2, y2) on E. |
|
||||
|
||||
|
||||
Requirement: at least `x1`!=`x2` or `y1`!=`y2`.
|
||||
|
||||
- OUTPUT
|
||||
|
||||
|
||||
| Input | Representation | Description | |
|
||||
| ------------- | ------------- | ------------- | ------------- |
|
||||
| `xout` | Bigint | Field element of Fp | First coordinate of the addition point (xout, yout) = (x1, y1) + (x2, y2). |
|
||||
| `yout` | Bigint | Field element of Fp | Second coordinate of the addition point (xout, yout) = (x1, y1) + (x2, y2). |
|
||||
|
||||
|
||||
- BENCHMARKS (constraints)
|
||||
|
||||
- EXAMPLE
|
||||
@ -108,7 +108,7 @@ Arithmetic on [Baby Jubjub elliptic curve](https://github.com/barryWhiteHat/baby
|
||||
|
||||
- `BabyCheck()`
|
||||
|
||||
- DESCRIPTION : checks if a given point is in the curve.
|
||||
- DESCRIPTION : checks if a given point is in the curve.
|
||||
- SCHEMA
|
||||
- INPUT
|
||||
- OUTPUT
|
||||
@ -127,7 +127,7 @@ Arithmetic on [Baby Jubjub elliptic curve](https://github.com/barryWhiteHat/baby
|
||||
|
||||
### binsub
|
||||
|
||||
- `BinSub(n)`
|
||||
- `BinSub(n)`
|
||||
|
||||
- DESCRIPTION: binary substraction.
|
||||
- SCHEMA
|
||||
@ -140,7 +140,7 @@ Arithmetic on [Baby Jubjub elliptic curve](https://github.com/barryWhiteHat/baby
|
||||
|
||||
- `nbits(a)`
|
||||
|
||||
- DESCRIPTION : binary sum.
|
||||
- DESCRIPTION : binary sum.
|
||||
- SCHEMA
|
||||
- INPUT
|
||||
- OUTPUT
|
||||
@ -149,7 +149,7 @@ Arithmetic on [Baby Jubjub elliptic curve](https://github.com/barryWhiteHat/baby
|
||||
|
||||
- `BinSum(n, ops)`
|
||||
|
||||
- DESCRIPTION
|
||||
- DESCRIPTION
|
||||
- SCHEMA
|
||||
- INPUT
|
||||
- OUTPUT
|
||||
@ -169,7 +169,7 @@ Arithmetic on [Baby Jubjub elliptic curve](https://github.com/barryWhiteHat/baby
|
||||
|
||||
- `Num2Bits_strict()`
|
||||
|
||||
- DESCRIPTION
|
||||
- DESCRIPTION
|
||||
- SCHEMA
|
||||
- INPUT
|
||||
- OUTPUT
|
||||
@ -259,7 +259,7 @@ Arithmetic on [Baby Jubjub elliptic curve](https://github.com/barryWhiteHat/baby
|
||||
- BENCHMARKS
|
||||
- EXAMPLE
|
||||
|
||||
### compconstant
|
||||
### compconstant
|
||||
|
||||
- `CompConstant(ct)`
|
||||
|
||||
@ -688,7 +688,7 @@ Implementation of MiMC-7 hash in Fp being... (link to description of the hash)
|
||||
|
||||
### pedersen_old
|
||||
|
||||
Old version of the Pedersen hash (do not use any
|
||||
Old version of the Pedersen hash (do not use any
|
||||
more?).
|
||||
|
||||
### pedersen
|
||||
@ -720,7 +720,7 @@ more?).
|
||||
- BENCHMARKS
|
||||
- EXAMPLE
|
||||
|
||||
### pointbits
|
||||
### pointbits
|
||||
|
||||
- `sqrt(n)`
|
||||
|
||||
@ -780,7 +780,7 @@ Implementation of Poseidon hash function (LINK)
|
||||
- BENCHMARKS
|
||||
- EXAMPLE
|
||||
|
||||
- `Ark(t, C)`
|
||||
- `Ark(t, C, r)`
|
||||
|
||||
- DESCRIPTION
|
||||
- SCHEMA
|
||||
@ -798,7 +798,7 @@ Implementation of Poseidon hash function (LINK)
|
||||
- BENCHMARKS
|
||||
- EXAMPLE
|
||||
|
||||
- `Poseidon(nInputs, t, nRoundsF, nRoundsP)`
|
||||
- `Poseidon(nInputs)`
|
||||
|
||||
- DESCRIPTION
|
||||
- SCHEMA
|
||||
|
@ -51,7 +51,7 @@ template EdDSAPoseidonVerifier() {
|
||||
|
||||
// Calculate the h = H(R,A, msg)
|
||||
|
||||
component hash = Poseidon(5, 6, 8, 57);
|
||||
component hash = Poseidon(5);
|
||||
|
||||
hash.inputs[0] <== R8x;
|
||||
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 output out;
|
||||
|
||||
component h = Poseidon(3, 6, 8, 57); // Constant
|
||||
component h = Poseidon(3); // Constant
|
||||
h.inputs[0] <== key;
|
||||
h.inputs[1] <== value;
|
||||
h.inputs[2] <== 1;
|
||||
@ -48,7 +48,7 @@ template SMTHash2() {
|
||||
signal input R;
|
||||
signal output out;
|
||||
|
||||
component h = Poseidon(2, 6, 8, 57); // Constant
|
||||
component h = Poseidon(2); // Constant
|
||||
h.inputs[0] <== L;
|
||||
h.inputs[1] <== R;
|
||||
|
||||
|
@ -112,8 +112,7 @@ function signPoseidon(prv, msg) {
|
||||
const Fr = new F1Field(babyJub.subOrder);
|
||||
r = Fr.e(r);
|
||||
const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
|
||||
const hash = poseidon.createHash(6, 8, 57);
|
||||
const hm = hash([R8[0], R8[1], A[0], A[1], msg]);
|
||||
const hm = poseidon([R8[0], R8[1], A[0], A[1], msg]);
|
||||
const S = Fr.add(r , Fr.mul(hm, s));
|
||||
return {
|
||||
R8: R8,
|
||||
@ -180,8 +179,7 @@ function verifyPoseidon(msg, sig, A) {
|
||||
if (!babyJub.inCurve(A)) return false;
|
||||
if (sig.S>= babyJub.subOrder) return false;
|
||||
|
||||
const hash = poseidon.createHash(6, 8, 57);
|
||||
const hm = hash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
|
||||
const hm = poseidon([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
|
||||
|
||||
const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
|
||||
let Pright = babyJub.mulPointEscalar(A, Scalar.mul(hm, 8));
|
||||
|
@ -154,6 +154,17 @@ class Contract {
|
||||
}
|
||||
|
||||
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));
|
||||
if (d.length == 0 || d.length > 32) {
|
||||
throw new Error("Assertion failed");
|
||||
|
146
src/poseidon.js
146
src/poseidon.js
@ -1,121 +1,49 @@
|
||||
const Scalar = require("ffjavascript").Scalar;
|
||||
const blake2b = require("blake2b");
|
||||
const assert = require("assert");
|
||||
const Scalar = require("ffjavascript").Scalar;
|
||||
const ZqField = require("ffjavascript").ZqField;
|
||||
const utils = require("ffjavascript").utils;
|
||||
const { unstringifyBigInts } = require("ffjavascript").utils;
|
||||
|
||||
// Prime 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
|
||||
const F = new ZqField(Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
|
||||
exports.F = F;
|
||||
|
||||
const SEED = "poseidon";
|
||||
const NROUNDSF = 8;
|
||||
const NROUNDSP = 57;
|
||||
const T = 6;
|
||||
// Parameters are generated by a reference script https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/generate_parameters_grain.sage
|
||||
// Used like so: sage generate_parameters_grain.sage 1 0 254 2 8 56 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
|
||||
const { C, M } = unstringifyBigInts(require("./poseidon_constants.json"));
|
||||
|
||||
function getPseudoRandom(seed, n) {
|
||||
const res = [];
|
||||
let input = Buffer.from(seed);
|
||||
let h = blake2b(32).update(input).digest();
|
||||
while (res.length<n) {
|
||||
const n = F.normalize(utils.leBuff2int(Buffer.from(h)));
|
||||
res.push(n);
|
||||
h = blake2b(32).update(h).digest();
|
||||
}
|
||||
// Using recommended parameters from whitepaper https://eprint.iacr.org/2019/458.pdf (table 2, table 8)
|
||||
// Generated by https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/calc_round_numbers.py
|
||||
// And rounded up to nearest integer that divides by t
|
||||
const N_ROUNDS_F = 8;
|
||||
const N_ROUNDS_P = [56, 57, 56, 60, 60, 63, 64, 63];
|
||||
|
||||
return res;
|
||||
}
|
||||
const pow5 = a => F.mul(a, F.square(F.square(a, a)));
|
||||
|
||||
function allDifferent(v) {
|
||||
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;
|
||||
function poseidon(inputs) {
|
||||
assert(inputs.length > 0);
|
||||
assert(inputs.length < N_ROUNDS_P.length - 1);
|
||||
|
||||
const t = inputs.length + 1;
|
||||
const nRoundsF = N_ROUNDS_F;
|
||||
const nRoundsP = N_ROUNDS_P[t - 2];
|
||||
|
||||
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 {
|
||||
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)
|
||||
);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return F.normalize(state[0]);
|
||||
}
|
||||
|
||||
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);
|
||||
for (let i=0; i<inputs.length; i++) state[i] = F.e(inputs[i]);
|
||||
for (let i=inputs.length; i<t; i++) state[i] = F.zero;
|
||||
|
||||
for (let i=0; i< nRoundsF + nRoundsP; i++) {
|
||||
ark(state, C[i]);
|
||||
if ((i<nRoundsF/2) || (i >= nRoundsF/2 + nRoundsP)) {
|
||||
for (let j=0; j<t; j++) state[j] = sigma(state[j]);
|
||||
} else {
|
||||
state[0] = sigma(state[0]);
|
||||
}
|
||||
mix(state, M);
|
||||
}
|
||||
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+
|
||||
//
|
||||
|
||||
const Poseidon = require("./poseidon.js");
|
||||
|
||||
const Contract = require("./evmasm");
|
||||
const { unstringifyBigInts } = require("ffjavascript").utils;
|
||||
|
||||
const SEED = "poseidon";
|
||||
const NROUNDSF = 8;
|
||||
const NROUNDSP = 57;
|
||||
const T = 6;
|
||||
const { C:K, M } = unstringifyBigInts(require("./poseidon_constants.json"));
|
||||
|
||||
const N_ROUNDS_F = 8;
|
||||
const N_ROUNDS_P = [56, 57, 56, 60, 60, 63, 64, 63];
|
||||
|
||||
function toHex256(a) {
|
||||
let S = a.toString(16);
|
||||
@ -17,38 +16,38 @@ function toHex256(a) {
|
||||
return "0x" + S;
|
||||
}
|
||||
|
||||
function createCode(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;
|
||||
function createCode(nInputs) {
|
||||
|
||||
if (( nInputs<1) || (nInputs>8)) throw new Error("Invalid number of inputs. Must be 1<=nInputs<=8");
|
||||
const t = nInputs + 1;
|
||||
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();
|
||||
|
||||
function saveM() {
|
||||
for (let i=0; i<t; i++) {
|
||||
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.mstore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ark(r) {
|
||||
C.push(toHex256(K[r])); // K, st, q
|
||||
function ark(r) { // st, q
|
||||
for (let i=0; i<t; i++) {
|
||||
C.dup(1+t); // q, K, st, q
|
||||
C.dup(1); // K, q, K, st, q
|
||||
C.dup(3+i); // st[i], K, q, K, st, q
|
||||
C.addmod(); // newSt[i], K, st, q
|
||||
C.swap(2 + i); // xx, K, st, q
|
||||
C.dup(t); // q, st, q
|
||||
C.push(toHex256(K[t-2][r*t+i])); // K, q, st, q
|
||||
C.dup(2+i); // st[i], K, q, st, q
|
||||
C.addmod(); // newSt[i], st, q
|
||||
C.swap(1 + i); // xx, st, q
|
||||
C.pop();
|
||||
}
|
||||
C.pop();
|
||||
}
|
||||
|
||||
function sigma(p) {
|
||||
@ -115,17 +114,17 @@ function createCode(t, nRoundsF, nRoundsP, seed) {
|
||||
|
||||
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
|
||||
// [Selector (4)] [Pointer (32)][Length (32)] [data1 (32)] ....
|
||||
// We ignore the pointer and the length and just load 6 values to the state
|
||||
// (Stack positions 0-5) If the array is shorter, we just set zeros.
|
||||
// We ignore the pointer and the length and just load t values to the state
|
||||
// (Stack positions 0-{t-1}) If the array is shorter, we just set zeros.
|
||||
for (let i=0; i<t; i++) {
|
||||
C.push(0x44+(0x20*(t-1-i)));
|
||||
C.calldataload();
|
||||
}
|
||||
|
||||
for (let i=0; i<nRoundsF+nRoundsP; i++) {
|
||||
for (let i=0; i<nRoundsF+nRoundsP-1; i++) {
|
||||
ark(i);
|
||||
if ((i<nRoundsF/2) || (i>=nRoundsP+nRoundsF/2)) {
|
||||
for (let j=0; j<t; j++) {
|
||||
@ -142,6 +141,13 @@ function createCode(t, nRoundsF, nRoundsP, seed) {
|
||||
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");
|
||||
|
@ -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");
|
||||
|
||||
|
||||
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) {
|
||||
return hash([left, right]);
|
||||
return poseidon([left, right]);
|
||||
};
|
||||
|
||||
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 utils = require("ffjavascript").utils;
|
||||
const ZqField = require("ffjavascript").ZqField;
|
||||
|
||||
// Prime 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
|
||||
const F = new ZqField(Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
|
||||
|
||||
class SMTMemDb {
|
||||
constructor() {
|
||||
|
@ -1,3 +1,3 @@
|
||||
include "../../circuits/poseidon.circom"
|
||||
|
||||
component main = Poseidon(2, 3, 8, 57);
|
||||
component main = Poseidon(2);
|
||||
|
@ -1,3 +1,3 @@
|
||||
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(),
|
||||
"15383486972088797283337779941324724402501462225528836549661220478783371668959");
|
||||
assert.equal(signature.S.toString(),
|
||||
"248298168863866362217836334079793350221620631973732197668910946177382043688");
|
||||
"1398758333392199195742243841591064350253744445503462896781493968760929513778");
|
||||
|
||||
const pSignature = eddsa.packSignature(signature);
|
||||
assert.equal(pSignature.toString("hex"), ""+
|
||||
"dfedb4315d3f2eb4de2d3c510d7a987dcab67089c8ace06308827bf5bcbe02a2"+
|
||||
"28506bce274aa1b3f7e7c2fd7e4fe09bff8f9aa37a42def7994e98f322888c00");
|
||||
"32f16b0f2f4c4e1169aa59685637e1429b6581a9531d058d65f4ab224eab1703");
|
||||
|
||||
const uSignature = eddsa.unpackSignature(pSignature);
|
||||
assert(eddsa.verifyPoseidon(msg, uSignature, pubKey));
|
||||
|
@ -1,21 +1,11 @@
|
||||
const chai = require("chai");
|
||||
const path = require("path");
|
||||
var blake2b = require("blake2b");
|
||||
const tester = require("circom").tester;
|
||||
|
||||
const poseidon = require("../src/poseidon.js");
|
||||
|
||||
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 () {
|
||||
let circuit6;
|
||||
let circuit3;
|
||||
@ -28,24 +18,20 @@ describe("Poseidon Circuit test", function () {
|
||||
});
|
||||
|
||||
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 = hash([1,2]);
|
||||
assert.equal("12242166908188651009877250812424843524687801523336557272219921456462821518061", res2.toString());
|
||||
const res2 = poseidon([1,2,0,0,0]);
|
||||
assert.equal("3975478831357328722254985704342968745327876719981393787143845259590563829094", res2.toString());
|
||||
await circuit6.assertOut(w, {out : res2});
|
||||
await circuit6.checkConstraints(w);
|
||||
});
|
||||
|
||||
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("17185195740979599334254027721507328033796809509313949281114643312710535000993", res2.toString());
|
||||
assert.equal("18540626624821144952552691894137986276337186174352554475896834101336254024067", res2.toString());
|
||||
await circuit6.assertOut(w, {out : res2});
|
||||
await circuit6.checkConstraints(w);
|
||||
});
|
||||
@ -54,10 +40,8 @@ describe("Poseidon Circuit test", function () {
|
||||
it("Should check constrain of hash([1, 2]) t=3", async () => {
|
||||
const w = await circuit3.calculateWitness({inputs: [1, 2]});
|
||||
|
||||
const hash = poseidon.createHash(3, 8, 57);
|
||||
|
||||
const res2 = hash([1,2]);
|
||||
assert.equal("2104035019328376391822106787753454168168617545136592089411833517434990977743", res2.toString());
|
||||
const res2 = poseidon([1,2]);
|
||||
assert.equal("17117985411748610629288516079940078114952304104811071254131751175361957805920", res2.toString());
|
||||
await circuit3.assertOut(w, {out : res2});
|
||||
await circuit3.checkConstraints(w);
|
||||
});
|
||||
@ -65,10 +49,8 @@ describe("Poseidon Circuit test", function () {
|
||||
it("Should check constrain of hash([3, 4]) t=3", async () => {
|
||||
const w = await circuit3.calculateWitness({inputs: [3, 4]});
|
||||
|
||||
const hash = poseidon.createHash(3, 8, 57);
|
||||
|
||||
const res2 = hash([3, 4]);
|
||||
assert.equal("12456141564250880945411182508630957604732712316993112736876413121277158512223", res2.toString());
|
||||
const res2 = poseidon([3, 4]);
|
||||
assert.equal("21867347236198497199818917118739170715216974132230970409806500217655788551452", res2.toString());
|
||||
await circuit3.assertOut(w, {out : res2});
|
||||
await circuit3.checkConstraints(w);
|
||||
});
|
||||
|
@ -2,7 +2,7 @@ const ganache = require("ganache-cli");
|
||||
const Web3 = require("web3");
|
||||
const chai = require("chai");
|
||||
const poseidonGenContract = require("../src/poseidon_gencontract.js");
|
||||
const Poseidon = require("../src/poseidon.js");
|
||||
const poseidon = require("../src/poseidon.js");
|
||||
|
||||
const assert = chai.assert;
|
||||
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);
|
||||
|
||||
poseidon6 = await C.deploy({
|
||||
data: poseidonGenContract.createCode(6)
|
||||
data: poseidonGenContract.createCode(5)
|
||||
}).send({
|
||||
gas: 2500000,
|
||||
gas: 5000000,
|
||||
from: accounts[0]
|
||||
});
|
||||
poseidon3 = await C.deploy({
|
||||
data: poseidonGenContract.createCode(3)
|
||||
data: poseidonGenContract.createCode(2)
|
||||
}).send({
|
||||
gas: 2500000,
|
||||
gas: 5000000,
|
||||
from: accounts[0]
|
||||
});
|
||||
});
|
||||
|
||||
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));
|
||||
|
||||
const hash = Poseidon.createHash(6, 8, 57);
|
||||
|
||||
const res2 = hash([1,2]);
|
||||
const res2 = poseidon([1,2, 0, 0, 0]);
|
||||
// console.log("Ref: " + bigInt(res2).toString(16));
|
||||
|
||||
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));
|
||||
|
||||
const hash = Poseidon.createHash(3, 8, 57);
|
||||
|
||||
const res2 = hash([1,2]);
|
||||
const res2 = poseidon([1,2]);
|
||||
// console.log("Ref: " + bigInt(res2).toString(16));
|
||||
|
||||
assert.equal(res.toString(), res2.toString());
|
||||
|
Loading…
Reference in New Issue
Block a user