23 Commits

Author SHA1 Message Date
Jordi Baylina
d689f737d8 0.0.8 2019-06-04 17:55:28 +02:00
Jordi Baylina
154a9bcbae Merge branch 'master' of github.com:iden3/circomlib 2019-06-04 17:36:54 +02:00
Jordi Baylina
c4490b2ce9 Poseidon in SMT 2019-06-04 17:32:28 +02:00
Jordi Baylina
590d62a07c Poseidon 2019-06-04 13:40:15 +02:00
Jordi Baylina
d91afa804a Merge pull request #5 from udibr/multiplexer
fixed Multiplexer name and usage of old syntax
2019-05-11 21:04:17 +02:00
Jordi Baylina
1da1f5886f Merge pull request #6 from udibr/circuits-readme
readme for circuits:
2019-05-11 21:00:43 +02:00
Jordi Baylina
fdce2a96e3 Merge pull request #7 from iden3/feature/babypbk
Add babyjub pvk->pbk circuit
2019-05-11 21:00:09 +02:00
Jordi Baylina
e7c4a979a0 Merge pull request #10 from kobigurk/fix_babyjubjub
fixes babyjubjub addition to use generic bigint interfaces
2019-05-11 20:45:27 +02:00
Jordi Baylina
efc77065e7 0.0.7 2019-05-08 19:09:28 +02:00
Jordi Baylina
58f758d5ad Adapt the way to connect mimcs 2019-04-28 12:03:15 +01:00
Kobi Gurkan
0503ec9de9 fixes babyjubjub addition to use generic bigint interfaces 2019-04-22 17:19:39 +03:00
adriamb
d9d6e43143 added pvk->pbk circuit 2019-03-17 10:38:36 +01:00
adriamb
8cb7b46603 fix missing deps 2019-03-17 10:36:14 +01:00
Ehud Ben-Reuven
39bb716785 fixed Multiplexer name and usage of old syntax 2019-02-23 20:16:06 -05:00
Ehud Ben-Reuven
b14eef4d90 readme for circuits: 2019-02-23 14:25:43 -05:00
Jordi Baylina
7792887216 0.0.6 2019-02-15 09:41:11 +01:00
Jordi Baylina
7971f0150e snarkjs version dep 2019-02-15 09:40:56 +01:00
Jordi Baylina
b3ff8b246d Merge branch 'master' of github.com:iden3/circomlib 2019-02-15 09:39:43 +01:00
Jordi Baylina
951e51423d rollupdoc 2019-02-15 09:39:38 +01:00
Jordi Baylina
9a5294dea1 Merge pull request #4 from ledfusion/master
Combined small fixes
2019-02-15 00:04:42 +01:00
Jordi
2635e8d3c9 Make code independent of NodeJS core modules 2019-02-12 12:21:44 +01:00
Jordi
138945bfdc Overcome undefined "Web3.utils" on web3@1.0.0-beta41 2019-02-12 12:19:17 +01:00
Jordi
2f9ad59c3a Exposing babyjub and pruneBuffer 2019-02-12 12:11:25 +01:00
40 changed files with 13020 additions and 1026 deletions

View File

@@ -1,14 +1,15 @@
const bn128 = require("snarkjs").bn128;
const bigInt = require("snarkjs").bigInt;
const createBlakeHash = require("blake-hash");
const assert = require("assert");
const babyJub = require("../src/babyjub");
function getPoint(S) {
const F = bn128.Fr;
const h = createBlakeHash("blake256").update(S).digest();
assert(h.length == 32);
if (h.length != 32) {
throw new Error("Invalid length")
}
let sign = false;
if (h[31] & 0x80) {
@@ -52,7 +53,9 @@ function generatePoint(S) {
p = getPoint(S+"_"+sidx);
idx++;
}
assert(babyJub.inCurve(p), "Point not in curve");
if (!babyJub.inCurve(p)){
throw new Error("Point not in curve");
}
return p;
}

14
circuits/README.md Normal file
View File

@@ -0,0 +1,14 @@
* compconstant - Returns 1 if `in` (expanded to binary array) > `ct`
* aliascheck - check if `in` (expanded to binary array) oveflowed its 254 bits (<= -1)
* babyjub - twisted Edwards curve 168700.x^2 + y^2 = 1 + 168696.x^2.y^2
* BabyAdd - (`xout`,`yout`) = (`x1`,`y1`) + (`x2`,`y2`)
* BabyDbl - (`xout`,`yout`) = 2*(`x`,`y`)
* BabyCheck - check that (`x`,`y`) is on the curve
* binsub - binary subtraction
* gates - logical gates
* mimc - SNARK-friendly hash Minimal Multiplicative Complexity.
* https://eprint.iacr.org/2016/492.pdf
* zcash/zcash#2233
* smt - Sparse Merkle Tree
* https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751
* montgomery https://en.wikipedia.org/wiki/Montgomery_curve

View File

@@ -17,6 +17,9 @@
along with circom. If not, see <https://www.gnu.org/licenses/>.
*/
include "bitify.circom";
include "escalarmulfix.circom";
template BabyAdd() {
signal input x1;
signal input y1;
@@ -77,3 +80,27 @@ template BabyCheck() {
a*x2 + y2 === 1 + d*x2*y2;
}
// Extracts the public key from private key
template BabyPbk() {
signal private input in;
signal output Ax;
signal output Ay;
var BASE8 = [
17777552123799933955779906779655732241715742912184938656739573121738514868268,
2626589144620713026669568689430873010625803728049924121243784502389097019475
];
component pvkBits = Num2Bits(253);
pvkBits.in <== in;
component mulFix = EscalarMulFix(253, BASE8);
var i;
for (i=0; i<253; i++) {
mulFix.e[i] <== pvkBits.out[i];
}
Ax <== mulFix.out[0];
Ay <== mulFix.out[1];
}

View File

@@ -58,6 +58,7 @@ template EdDSAMiMCVerifier() {
hash.in[2] <== Ax;
hash.in[3] <== Ay;
hash.in[4] <== M;
hash.k <== 0;
component h2bits = Num2Bits_strict();
h2bits.in <== hash.out;

View File

@@ -137,18 +137,19 @@ template MiMC7(nrounds) {
template MultiMiMC7(nInputs, nRounds) {
signal input in[nInputs];
signal input k;
signal output out;
signal r[nInputs +1];
component mims[nInputs];
r[0] <== k;
for (var i=0; i<nInputs; i++) {
mims[i] = MiMC7(nRounds);
if (i==0) {
mims[i].x_in <== 15021630795539610737508582392395901278341266317943626182700664337106830745361;
} else {
mims[i].x_in <== mims[i-1].out;
}
mims[i].k <== in[i];
mims[i].x_in <== in[i];
mims[i].k <== r[i];
r[i+1] <== r[i] + in[i] + mims[i].out;
}
out <== mims[nInputs-1].out;
out <== r[nInputs];
}

View File

@@ -90,12 +90,17 @@ template Decoder(w) {
}
template Multiplexor(wIn, nIn) {
template Multiplexer(wIn, nIn) {
signal input inp[nIn][wIn];
signal input sel;
signal output out[wIn];
component Decoder(nIn) dec;
component EscalarProduct(nIn) ep[wIn];
component dec = Decoder(nIn);
component ep[wIn];
for (var k=0; k<wIn; k++) {
ep[k] = EscalarProduct(nIn);
}
sel ==> dec.inp;
for (var j=0; j<wIn; j++) {
for (var k=0; k<nIn; k++) {
@@ -106,7 +111,3 @@ template Multiplexor(wIn, nIn) {
}
dec.success === 1;
}
component Multiplexor(8,3) main;

202
circuits/poseidon.circom Normal file
View File

@@ -0,0 +1,202 @@
template Sigma() {
signal input in;
signal output out;
signal in2;
signal in4;
in2 <== in*in;
in4 <== in2*in2;
out <== in4*in;
}
template Ark(t, C) {
signal input in[t];
signal output out[t];
for (var i=0; i<t; i++) {
out[i] <== in[i] + C;
}
}
template Mix(t, M) {
signal input in[t];
signal output out[t];
var lc;
for (var i=0; i<t; i++) {
lc = 0;
for (var j=0; j<t; j++) {
lc = lc + M[i][j]*in[j];
}
out[i] <== lc;
}
}
// var nRoundsF = 8;
// var nRoundsP = 57;
// var t = 6;
template Poseidon(nInputs, t, nRoundsF, nRoundsP) {
var C = [
1354025385229961744769229343273868518314335569873439558835166239576773343708,
14378844218625331047742339561309620904043097700980163591187076404481144585564,
19370813333785034372560258124535206525278124675105547990205946542330734467847,
19339919977375282793227987561727366424934767905100680591050582380667086628202,
8422275364316831706903446151602338206948363474119622730702497535467809432414,
7433947928146794739292515659214608949964639549664630885486968546133071892830,
20753350951496713264979200428833003140825588922450200809553577914404143341040,
21437018888080559864996889038552602698883513894753499324572098534369350747880,
6815447461573214810645016226370803316854141900901895816072622961504507953749,
11746901014017411226283657362310634990885933032228701131899561585228216986615,
13428722985713722660261823704226749286675766756093697029778643398137361221114,
10894749142018158588533110743373157663019829222177356873395009880383491602356,
13720066349319517776784660327982201297420012713976744204318378121767771862484,
4665971664531891307640113589671067488692829783046247264698659233443166028412,
5364541878673041196937884015923978656299860601766012213141306792903990539664,
1747411112078838632103476037026417344408680910500491241306123941341644055714,
1835035066071759522152578007305026433897204459772540871869487151042238374039,
21055637025200882290106914253232617255445210101773537879323245961051751183138,
19215142378199333594641095299020637309879189505235993967243075316794127016728,
5264915734761449905856538116909638235466879053604660991987579054616980096262,
10045917614023673044141331581538797960977704806582630277050701175565262856382,
7789533631025313780520004400945166898631872921910178131342071973345076732672,
19972498130123740615813398456152565371201412297339860820234719562997192378694,
14216077977931104808041453382683965630500368477063603536695472115075869912121,
2555981910568472028679439033700033287358333564454149464965229699417319912931,
11735111941739477522347883122573591136355121750109794306409399099068977659499,
16957890207070910233505303498878270130436461648242792271152604513138986611609,
358520143235124107055243451716507147499373646513864848163778795927281509793,
6389190271835493841487214043252929516390267871881261173336690351147926750010,
12939611907106878137030264379019786496625916664142697309441198804098015086205,
456696638239570875759108333278090964360604015255503302016190396687826618227,
20569764931577491771523222445135914903999292206008007769649255123342890660989,
3341317247281280728261320226215152668194921091152837358683334635401182164637,
11821224368797169892747612081573458772211068320533296007836648033607696236615,
2185176387193659864764608304330502180888068591409305411859725028056771843945,
17161758741114551704796078639849789476380746803787101178795737276111464575519,
11889888355183092530573415929875444766831739308191993115663429638848547668798,
19503084309842095729857399025417533485089330284851492085544757107759925099089,
20280152151768521735424910115623976684589382048161526796204268413029416266256,
17607351334578006856860845064970248988416315904757246948622629528628773644114,
20769468546336672951384440602623018830493119282829911435465737079851020547355,
1546429204704408801701093430086546742691081844046642451323347737810191940866,
11200569249561318620053458114013886527484999499632128671282997438827107108229,
20198213289062010915914579158889968647687156198219713083074315178786791524034,
12911209060630719799682705729835581341676468319742562559036843993017369855977,
18925188847138989248835676768641716482476141553833902070405850166412140133887,
20376466983584239909415025821007315251422803039634139484663713769887712746966,
5250536177612235431141386983455571232984126980327432803966957255414592397060,
344847263093423485167610155050688875010578621416939967999896518937961396680,
19870333728541576497318505013425518731999037041271340888970559590767369935385,
20604512495859902382577228682521142736989261702707317046150335692410020156250,
18293964088694556689667514948280720605277532123251572448395882397578643211622,
21211253784206079547762943120791531326787601501123474236198383850531142559075,
17247914781304154940895909185506123510423535554247372833321968000513811053190,
16432189025237084563810000088202867449333673799705533820685782829379758927490,
7204783063529242442830743239980168374343946353418800547956909848044774363774,
2108268032972510691814120801033692084861951866306906253604497017452204030001,
13483247063999686990721729188827693318708500027762095503921527692630827328070,
18194665574704709729868916970580318177272365766028499528691737819467051567534,
9275639092314761435364537152118796424056864859607619908791935597976913759411,
12700165678727983685032332532042155014245610964583614362270316386368455898604,
19127554193875137546212792134421555344854604853165878912238751527694270097310,
16817455471920423226570476063669349525676437756352144502692679769377074040335,
17331185397945904160678487303485263376032543419657328137924881433628614769955,
11605569208043267134285833752214422326246425655661043119023566733685555142420
];
var M = [
[
12037235000515189726428793905458162231976011685774991261061889278958802340039,
15885254491685089152627111704751054604879027605518712546805347341940526552948,
12220682901774309471330657931458552366575439534877271150866614914170639536810,
11195096069395318710866553226959674457987772316145705151894647995087349332576,
598000700605575401177173118514166571064818339748567530524299773749024042768,
1430722853270801285936618367966028727146977818314178365893636191280860605092
],[
2478807512283787086755520696277192042388812450777005645736937700857950416751,
2233078558675693495109307103888903813217767160310116996267068037131890781382,
18876120310576321787684235034151243856925703159922712959767164734820803570163,
16850806847813838898693870637445284830832219430572133120914449039176718036761,
1333036876405396107763619427367607232034082504897380383847654332653606615427,
8024813862822108072341428765418554797098705487914663416123759888639403831315
],[
6500095533434910955474026763873910167129305339747639394388586826716085593160,
8370208895752773828195461153114215021863221486187756770286440396339432061839,
9303960191058819387902927958335344077259478983903385066838134730814638010892,
12233235273183315334651707749232602313616943260130930740801007863528547113209,
9140649423847813564210562288927015604065254723368331178903734405333716165919,
1715897011776785698388835993891828784112980527691698420841641796168725014542
],[
19092640119254952117901733765506685707486610088248205883870061221436629780176,
3099417239661426161523333446616746096617346084970490427773391639810420659748,
4498351799178816410443394768364090919370619407529999860500200773846156676605,
17766546613911504681964882079687098358108049762069064124348111606619240189874,
19735199036142202254810745273503942799136628866093225336283966579447096889407,
18618071352177331467649099054615438672487187348128402045695624605978242597928
],[
13282641901514824677915134398195165361567825236648422290753355584311135817423,
842963276112770184096507757019973399127531993386626262873928307889423235104,
5724939764407712239242783736588389538981693110806985476155198757555171230777,
3015568820237516884743892014063659856564948150197038824747891972506031149123,
8926202997251578932273751544826990276848999132609774201265891812369804099098,
13523975980414815337318802343464374889255493007711857898760066111901192774093
],[
13163705634211158833717167498904899472888572514300041636511944020589976373689,
6705743158328622712684686369234272301477431173971663001146157949982901448493,
5341285785102635724684809992160578025785996331334612975598752577556138916495,
2365134732811643517126128253974711531515283135672252986518431351700239265326,
11812366860142870031000585328436207067560705932658624313008187741187899702321,
11192751017231920972897699839932659451476356148115786649719660565307185769796
]
];
signal input inputs[nInputs];
signal output out;
component ark[nRoundsF + nRoundsP];
component sigmaF[nRoundsF][t];
component sigmaP[nRoundsP];
component mix[nRoundsF + nRoundsP];
var k;
for (var i=0; i<(nRoundsF + nRoundsP); i++) {
ark[i] = Ark(t, C[i]);
mix[i] = Mix(t, M);
for (var j=0; j<t; j++) {
if (i==0) {
if (j<nInputs) {
ark[i].in[j] <== inputs[j];
} else {
ark[i].in[j] <== 0;
}
} else {
ark[i].in[j] <== mix[i-1].out[j];
}
}
if ((i<(nRoundsF/2)) || (i>= (nRoundsP + nRoundsF/2))) {
k= i<nRoundsF/2 ? i : (i-nRoundsP);
for (var j=0; j<t; j++) {
sigmaF[k][j] = Sigma();
sigmaF[k][j].in <== ark[i].out[j];
mix[i].in[j] <== sigmaF[k][j].out;
}
} else {
k= i-nRoundsF/2;
sigmaP[k] = Sigma();
sigmaP[k].in <== ark[i].out[0];
mix[i].in[0] <== sigmaP[k].out;
for (var j=1; j<t; j++) {
mix[i].in[j] <== ark[i].out[j];
}
}
}
out <== mix[nRoundsF + nRoundsP -1].out[0];
}

View File

@@ -29,19 +29,12 @@ template SMTHash1() {
signal input value;
signal output out;
component h1 = MiMC7(91); // Constant
h1.x_in <== 15021630795539610737508582392395901278341266317943626182700664337106830745361;
h1.k <== 1;
component h = MultiMiMC7(2, 91); // Constant
h.in[0] <== key;
h.in[1] <== value;
h.k <== 1;
component h2 = MiMC7(91);
h2.x_in <== h1.out;
h2.k <== key;
component h3 = MiMC7(91);
h3.x_in <== h2.out;
h3.k <== value;
out <== h3.out;
out <== h.out;
}
/*
@@ -55,13 +48,10 @@ template SMTHash2() {
signal input R;
signal output out;
component h1 = MiMC7(91);
h1.x_in <== 15021630795539610737508582392395901278341266317943626182700664337106830745361;
h1.k <== L;
component h = MultiMiMC7(2, 91); // Constant
h.in[0] <== L;
h.in[1] <== R;
h.k <== 0;
component h2 = MiMC7(91);
h2.x_in <== h1.out;
h2.k <== R;
out <== h2.out;
out <== h.out;
}

View File

@@ -0,0 +1,56 @@
/*
Copyright 2018 0KIMS association.
This file is part of circom (Zero Knowledge Circuit Compiler).
circom is a free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
circom is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with circom. If not, see <https://www.gnu.org/licenses/>.
*/
include "../poseidon.circom";
/*
Hash1 = H(1 | key | value)
*/
template SMTHash1() {
signal input key;
signal input value;
signal output out;
component h = Poseidon(3, 6, 8, 57); // Constant
h.inputs[0] <== key;
h.inputs[1] <== value;
h.inputs[2] <== 1;
out <== h.out;
}
/*
This component is used to create the 2 nodes.
Hash2 = H(Hl | Hr)
*/
template SMTHash2() {
signal input L;
signal input R;
signal output out;
component h = Poseidon(2, 6, 8, 57); // Constant
h.inputs[0] <== L;
h.inputs[1] <== R;
out <== h.out;
}

View File

@@ -135,7 +135,7 @@ include "../switcher.circom";
include "smtlevins.circom";
include "smtprocessorlevel.circom";
include "smtprocessorsm.circom";
include "smthash.circom";
include "smthash_poseidon.circom";
template SMTProcessor(nLevels) {
signal input oldRoot;

View File

@@ -35,7 +35,7 @@ include "../switcher.circom";
include "smtlevins.circom";
include "smtverifierlevel.circom";
include "smtverifiersm.circom";
include "smthash.circom";
include "smthash_poseidon.circom";
template SMTVerifier(nLevels) {
signal input enabled;

BIN
doc/rollup_tree.monopic Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -1,3 +1,4 @@
exports.smt = require("./src/smt");
exports.eddsa = require("./src/eddsa");
exports.mimc7 = require("./src/mimc7");
exports.babyJub = require("./src/babyjub");

11471
log.txt Normal file

File diff suppressed because it is too large Load Diff

1332
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "circomlib",
"version": "0.0.5",
"version": "0.0.8",
"description": "Basic circuits library for Circom",
"main": "index.js",
"directories": {
@@ -25,11 +25,12 @@
"license": "GPL-3.0",
"dependencies": {
"blake-hash": "^1.1.0",
"snarkjs": "0.1.9",
"snarkjs": "0.1.11",
"typedarray-to-buffer": "^3.1.5",
"web3": "^1.0.0-beta.36"
},
"devDependencies": {
"circom": "0.0.24",
"circom": "0.0.28",
"eslint-plugin-mocha": "^5.2.0",
"ganache-cli": "^6.2.3",
"mocha": "^5.2.0"

View File

@@ -22,8 +22,14 @@ function addPoint(a,b) {
const d = bigInt("168696");
const res = [];
/* does the equivalent of:
res[0] = bigInt((a[0]*b[1] + b[0]*a[1]) * bigInt(bigInt("1") + d*a[0]*b[0]*a[1]*b[1]).inverse(q)).affine(q);
res[1] = bigInt((a[1]*b[1] - cta*a[0]*b[0]) * bigInt(bigInt("1") - d*a[0]*b[0]*a[1]*b[1]).inverse(q)).affine(q);
*/
res[0] = bigInt((bigInt(a[0]).mul(b[1]).add(bigInt(b[0]).mul(a[1]))).mul(bigInt(bigInt("1").add(d.mul(a[0]).mul(b[0]).mul(a[1]).mul(b[1]))).inverse(q))).affine(q);
res[1] = bigInt((bigInt(a[1]).mul(b[1]).sub(cta.mul(a[0]).mul(b[0]))).mul(bigInt(bigInt("1").sub(d.mul(a[0]).mul(b[0]).mul(a[1]).mul(b[1]))).inverse(q))).affine(q);
return res;
}

View File

@@ -3,9 +3,7 @@ const bigInt = require("snarkjs").bigInt;
const babyJub = require("./babyjub");
const pedersenHash = require("./pedersenHash").hash;
const mimc7 = require("./mimc7");
const crypto = require("crypto");
exports.cratePrvKey = cratePrvKey;
exports.prv2pub= prv2pub;
exports.sign = sign;
exports.signMiMC = signMiMC;
@@ -13,12 +11,9 @@ exports.verify = verify;
exports.verifyMiMC = verifyMiMC;
exports.packSignature = packSignature;
exports.unpackSignature = unpackSignature;
exports.pruneBuffer = pruneBuffer;
function cratePrvKey() {
return crypto.randomBytes(32);
}
function pruneBuffer(_buff) {
const buff = Buffer.from(_buff);
buff[0] = buff[0] & 0xF8;

View File

@@ -3,8 +3,7 @@
//
const Web3 = require("web3");
const assert = require("assert");
const Web3Utils = require("web3-utils");
class Contract {
constructor() {
@@ -39,7 +38,7 @@ class Contract {
genLoadedLength = C.code.length;
}
return Web3.utils.bytesToHex(C.code.concat(this.code));
return Web3Utils.bytesToHex(C.code.concat(this.code));
}
stop() { this.code.push(0x00); }
@@ -128,12 +127,16 @@ class Contract {
jmp(label) {
if (typeof label !== "undefined") {
this._pushLabel(label);
}
this.code.push(0x56);
}
jmpi(label) {
if (typeof label !== "undefined") {
this._pushLabel(label);
}
this.code.push(0x57);
}
@@ -141,7 +144,9 @@ class Contract {
msize() { this.code.push(0x59); }
gas() { this.code.push(0x5a); }
label(name) {
assert(typeof this.labels[name] == "undefined", "Label already defined");
if (typeof this.labels[name] != "undefined") {
throw new Error("Label already defined");
}
this.labels[name] = this.code.length;
this.code.push(0x5b);
@@ -149,21 +154,24 @@ class Contract {
}
push(data) {
const d = Web3.utils.hexToBytes(Web3.utils.toHex(data));
assert(d.length>0);
assert(d.length<=32);
const d = Web3Utils.hexToBytes(Web3Utils.toHex(data));
if (d.length == 0 || d.length > 32) {
throw new Error("Assertion failed");
}
this.code = this.code.concat([0x5F + d.length], d);
}
dup(n) {
assert(n>=0);
assert(n<16);
if (n < 0 || n >= 16) {
throw new Error("Assertion failed");
}
this.code.push(0x80 + n);
}
swap(n) {
assert(n>=1);
assert(n<=16);
if (n < 1 || n > 16) {
throw new Error("Assertion failed");
}
this.code.push(0x8f + n);
}

View File

@@ -1,6 +1,6 @@
const bn128 = require("snarkjs").bn128;
const bigInt = require("snarkjs").bigInt;
const Web3 = require("web3");
const Web3Utils = require("web3-utils");
const F = bn128.Fr;
const SEED = "mimc";
@@ -8,8 +8,8 @@ const NROUNDS = 91;
exports.getIV = (seed) => {
if (typeof seed === "undefined") seed = SEED;
const c = Web3.utils.keccak256(seed+"_iv");
const cn = bigInt(Web3.utils.toBN(c).toString());
const c = Web3Utils.keccak256(seed+"_iv");
const cn = bigInt(Web3Utils.toBN(c).toString());
const iv = cn.mod(F.q);
return iv;
};
@@ -18,13 +18,13 @@ exports.getConstants = (seed, nRounds) => {
if (typeof seed === "undefined") seed = SEED;
if (typeof nRounds === "undefined") nRounds = NROUNDS;
const cts = new Array(nRounds);
let c = Web3.utils.keccak256(SEED);
let c = Web3Utils.keccak256(SEED);
for (let i=1; i<nRounds; i++) {
c = Web3.utils.keccak256(c);
c = Web3Utils.keccak256(c);
const n1 = Web3.utils.toBN(c).mod(Web3.utils.toBN(F.q.toString()));
const c2 = Web3.utils.padLeft(Web3.utils.toHex(n1), 64);
cts[i] = bigInt(Web3.utils.toBN(c2).toString());
const n1 = Web3Utils.toBN(c).mod(Web3Utils.toBN(F.q.toString()));
const c2 = Web3Utils.padLeft(Web3Utils.toHex(n1), 64);
cts[i] = bigInt(Web3Utils.toBN(c2).toString());
}
cts[0] = bigInt(0);
return cts;
@@ -44,10 +44,21 @@ exports.hash = (_x_in, _k) =>{
return F.affine(F.add(r, k));
};
exports.multiHash = (arr) => {
let r = exports.getIV();
for (let i=0; i<arr.length; i++) {
r = exports.hash(r, bigInt(arr[i]));
exports.multiHash = (arr, key) => {
let r;
if (typeof(key) === "undefined") {
r = F.zero;
} else {
r = key;
}
return r;
for (let i=0; i<arr.length; i++) {
r = F.add(
F.add(
r,
arr[i]
),
exports.hash(bigInt(arr[i]), r)
);
}
return F.affine(r);
};

View File

@@ -2,13 +2,13 @@
// License: LGPL-3.0+
//
const Web3 = require("web3");
const Web3Utils = require("web3-utils");
const Contract = require("./evmasm");
function createCode(seed, n) {
let ci = Web3.utils.keccak256(seed);
let ci = Web3Utils.keccak256(seed);
const C = new Contract();
@@ -51,7 +51,7 @@ function createCode(seed, n) {
C.mulmod(); // r=t^7 k q
for (let i=0; i<n-1; i++) {
ci = Web3.utils.keccak256(ci);
ci = Web3Utils.keccak256(ci);
C.dup(2); // q r k q
C.dup(0); // q q r k q
C.dup(0); // q q q r k q

View File

@@ -1,7 +1,6 @@
const bn128 = require("snarkjs").bn128;
const bigInt = require("snarkjs").bigInt;
const babyJub = require("./babyjub");
const assert = require("assert");
const createBlakeHash = require("blake-hash");
const GENPOINT_PREFIX = "PedersenGenerator";
@@ -73,7 +72,9 @@ function getBasePoint(pointIdx) {
const p8 = babyJub.mulPointEscalar(p, 8);
assert(babyJub.inSubgroup(p8), "Point not in curve");
if (!babyJub.inSubgroup(p8)) {
throw new Error("Point not in curve");
}
bases[pointIdx] = p8;
return p8;

115
src/poseidon.js Normal file
View File

@@ -0,0 +1,115 @@
const bn128 = require("snarkjs").bn128;
const bigInt = require("snarkjs").bigInt;
const createBlakeHash = require("blake-hash");
const assert = require("assert");
const F = bn128.Fr;
const SEED = "poseidon";
const NROUNDSF = 8;
const NROUNDSP = 57;
const T = 6;
function getPseudoRandom(seed, n) {
const res = [];
let h = createBlakeHash("blake256").update(seed).digest();
while (res.length<n) {
const n = F.affine(bigInt.leBuff2int(h));
res.push(n);
h = createBlakeHash("blake256").update(h).digest();
}
return res;
}
function allDifferent(v) {
for (let i=0; i<v.length; i++) {
if (v[i].isZero()) return false;
for (let j=i+1; j<v.length; j++) {
if (v[i].equals(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;
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.affine(F.inverse(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] = bigInt(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.affine(state[0]);
};
};

180
src/poseidon_gencontract.js Normal file
View File

@@ -0,0 +1,180 @@
// Copyright (c) 2018 Jordi Baylina
// License: LGPL-3.0+
//
const Poseidon = require("./poseidon.js");
const Contract = require("./evmasm");
const SEED = "poseidon";
const NROUNDSF = 8;
const NROUNDSP = 57;
const T = 6;
function toHex256(a) {
let S = a.toString(16);
while (S.length < 64) S="0"+S;
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;
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((1+i*t+j)*32);
C.mstore();
}
}
}
function ark(r) {
C.push(toHex256(K[r])); // K, 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.pop();
}
C.pop();
}
function sigma(p) {
// sq, q
C.dup(t); // q, st, q
C.dup(1+p); // st[p] , q , st, q
C.dup(1); // q, st[p] , q , st, q
C.dup(0); // q, q, st[p] , q , st, q
C.dup(2); // st[p] , q, q, st[p] , q , st, q
C.dup(0); // st[p] , st[p] , q, q, st[p] , q , st, q
C.mulmod(); // st2[p], q, st[p] , q , st, q
C.dup(0); // st2[p], st2[p], q, st[p] , q , st, q
C.mulmod(); // st4[p], st[p] , q , st, q
C.mulmod(); // st5[p], st, q
C.swap(1+p);
C.pop(); // newst, q
}
function mix() {
C.label("mix");
for (let i=0; i<t; i++) {
for (let j=0; j<t; j++) {
if (j==0) {
C.dup(i+t); // q, newSt, oldSt, q
C.push((1+i*t+j)*32);
C.mload(); // M, q, newSt, oldSt, q
C.dup(2+i+j); // oldSt[j], M, q, newSt, oldSt, q
C.mulmod(); // acc, newSt, oldSt, q
} else {
C.dup(1+i+t); // q, acc, newSt, oldSt, q
C.push((1+i*t+j)*32);
C.mload(); // M, q, acc, newSt, oldSt, q
C.dup(3+i+j); // oldSt[j], M, q, acc, newSt, oldSt, q
C.mulmod(); // aux, acc, newSt, oldSt, q
C.dup(2+i+t); // q, aux, acc, newSt, oldSt, q
C.swap(2); // acc, aux, q, newSt, oldSt, q
C.addmod(); // acc, newSt, oldSt, q
}
}
}
for (let i=0; i<t; i++) {
C.swap((t -i) + (t -i-1));
C.pop();
}
C.push(0);
C.mload();
C.jmp();
}
// Check selector
C.push("0x0100000000000000000000000000000000000000000000000000000000");
C.push(0);
C.calldataload();
C.div();
C.push("0xc4420fb4"); // poseidon(uint256[])
C.eq();
C.jmpi("start");
C.invalid();
C.label("start");
saveM();
C.push("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"); // q
// Load 6 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.
for (let i=0; i<t; i++) {
C.push(0x44+(0x20*(5-i)));
C.calldataload();
}
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++) {
sigma(j);
}
} else {
sigma(0);
}
const strLabel = "aferMix"+i;
C._pushLabel(strLabel);
C.push(0);
C.mstore();
C.jmp("mix");
C.label(strLabel);
}
C.push("0x00");
C.mstore(); // Save it to pos 0;
C.push("0x20");
C.push("0x00");
C.return();
mix();
return C.createTxData();
}
module.exports.abi = [
{
"constant": true,
"inputs": [
{
"name": "input",
"type": "uint256[]"
}
],
"name": "poseidon",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "pure",
"type": "function"
}
];
module.exports.createCode = createCode;

View File

@@ -0,0 +1,16 @@
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);

View File

@@ -0,0 +1,5 @@
const poseidonGenContract = require("./poseidon_gencontract");
console.log(poseidonGenContract.createCode(6, 8, 57));

View File

@@ -0,0 +1,22 @@
const Poseidon = require("./poseidon.js");
const M = Poseidon.getMatrix();
let S = "[\n ";
for (let i=0; i<M.length; i++) {
const LC = M[i];
S = S + "[\n";
for (let j=0; j<LC.length; j++) {
S = S + " " + M[i][j].toString();
if (j<LC.length-1) S = S + ",";
S = S + "\n";
}
S = S + " ]";
if (i<M.length-1) S = S + ",";
}
S=S+ "\n]\n";
console.log(S);

View File

@@ -1,7 +1,7 @@
const bigInt = require("snarkjs").bigInt;
const SMTMemDB = require("./smt_memdb");
const mimc7 = require("./mimc7");
const {hash0, hash1} = require("./smt_hashes_poseidon");
class SMT {
@@ -46,8 +46,8 @@ class SMT {
const ins = [];
const dels = [];
let rtOld = mimc7.multiHash([1, key, resFind.foundValue]);
let rtNew = mimc7.multiHash([1, key, newValue]);
let rtOld = hash1(key, resFind.foundValue);
let rtNew = hash1(key, newValue);
ins.push([rtNew, [1, key, newValue ]]);
dels.push(rtOld);
@@ -59,11 +59,11 @@ class SMT {
oldNode = [sibling, rtOld];
newNode = [sibling, rtNew];
} else {
oldNode = [rtOld, sibling, ];
newNode = [rtNew, sibling, ];
oldNode = [rtOld, sibling];
newNode = [rtNew, sibling];
}
rtOld = mimc7.multiHash(oldNode);
rtNew = mimc7.multiHash(newNode);
rtOld = hash0(oldNode[0], oldNode[1]);
rtNew = hash0(newNode[0], newNode[1]);
dels.push(rtOld);
ins.push([rtNew, newNode]);
}
@@ -92,7 +92,7 @@ class SMT {
const dels = [];
const ins = [];
let rtOld = mimc7.multiHash([1, key, resFind.foundValue]);
let rtOld = hash1(key, resFind.foundValue);
let rtNew;
dels.push(rtOld);
@@ -130,9 +130,9 @@ class SMT {
}
const oldSibling = resFind.siblings[level];
if (keyBits[level]) {
rtOld = mimc7.multiHash([oldSibling, rtOld]);
rtOld = hash0(oldSibling, rtOld);
} else {
rtOld = mimc7.multiHash([rtOld, oldSibling]);
rtOld = hash0(rtOld, oldSibling);
}
dels.push(rtOld);
if (!newSibling.isZero()) {
@@ -147,7 +147,7 @@ class SMT {
} else {
newNode = [rtNew, newSibling];
}
rtNew = mimc7.multiHash(newNode);
rtNew = hash0(newNode[0], newNode[1]);
ins.push([rtNew, newNode]);
}
}
@@ -185,7 +185,7 @@ class SMT {
for (let i= res.siblings.length; oldKeyits[i] == newKeyBits[i]; i++) {
res.siblings.push(bigInt.zero);
}
rtOld = mimc7.multiHash([1, resFind.notFoundKey, resFind.notFoundValue]);
rtOld = hash1(resFind.notFoundKey, resFind.notFoundValue);
res.siblings.push(rtOld);
addedOne = true;
mixed = false;
@@ -197,7 +197,7 @@ class SMT {
const inserts = [];
const dels = [];
let rt = mimc7.multiHash([1, key, value]);
let rt = hash1(key, value);
inserts.push([rt,[1, key, value]] );
for (let i=res.siblings.length-1; i>=0; i--) {
@@ -207,9 +207,9 @@ class SMT {
if (mixed) {
const oldSibling = resFind.siblings[i];
if (newKeyBits[i]) {
rtOld = mimc7.multiHash([oldSibling, rtOld]);
rtOld = hash0(oldSibling, rtOld);
} else {
rtOld = mimc7.multiHash([rtOld, oldSibling]);
rtOld = hash0(rtOld, oldSibling);
}
dels.push(rtOld);
}
@@ -217,10 +217,10 @@ class SMT {
let newRt;
if (newKeyBits[i]) {
newRt = mimc7.multiHash([res.siblings[i], rt]);
newRt = hash0(res.siblings[i], rt);
inserts.push([newRt,[res.siblings[i], rt]] );
} else {
newRt = mimc7.multiHash([rt, res.siblings[i]]);
newRt = hash0(rt, res.siblings[i]);
inserts.push([newRt,[rt, res.siblings[i]]] );
}
rt = newRt;

10
src/smt_hashes_mimc.js Normal file
View File

@@ -0,0 +1,10 @@
const mimc7 = require("./mimc7");
const bigInt = require("snarkjs").bigInt;
exports.hash0 = function (left, right) {
return mimc7.multiHash(left, right);
};
exports.hash1 = function(key, value) {
return mimc7.multiHash([key, value], bigInt.one);
};

View File

@@ -0,0 +1,12 @@
const Poseidon = require("./poseidon");
const bigInt = require("snarkjs").bigInt;
const hash = Poseidon.createHash(6, 8, 57);
exports.hash0 = function (left, right) {
return hash([left, right]);
};
exports.hash1 = function(key, value) {
return hash([key, value, bigInt.one]);
};

View File

@@ -3,10 +3,12 @@ const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const createBlakeHash = require("blake-hash");
const eddsa = require("../src/eddsa.js");
const assert = chai.assert;
const bigInt = require("big-integer");
const bigInt = require("snarkjs").bigInt;
describe("Baby Jub test", function () {
let circuitAdd;
@@ -22,6 +24,11 @@ describe("Baby Jub test", function () {
const cirDefTest = await compiler(path.join(__dirname, "circuits", "babycheck_test.circom"));
circuitTest = new snarkjs.Circuit(cirDefTest);
console.log("NConstrains BabyTest: " + circuitTest.nConstraints);
const cirDefPbk = await compiler(path.join(__dirname, "circuits", "babypbk_test.circom"));
circuitPbk = new snarkjs.Circuit(cirDefPbk);
console.log("NConstrains BabyPbk: " + circuitPbk.nConstraints);
});
it("Should add point (0,1) and (0,1)", async () => {
@@ -97,4 +104,22 @@ describe("Baby Jub test", function () {
}
});
it("Should extract the public key from the private one", async () => {
const rawpvk = Buffer.from("0001020304050607080900010203040506070809000102030405060708090021", "hex");
const pvk = eddsa.pruneBuffer(createBlakeHash("blake512").update(rawpvk).digest().slice(0,32));
const S = bigInt.leBuff2int(pvk).shr(3);
const A = eddsa.prv2pub(rawpvk);
const input = {
in : S,
Ax : A[0],
Ay : A[1]
}
const w = circuitPbk.calculateWitness(input);
assert(circuitPbk.checkWitness(w));
});
});

View File

@@ -0,0 +1,3 @@
include "../../circuits/babyjub.circom";
component main = BabyPbk();

View File

@@ -0,0 +1,3 @@
include "../../circuits/poseidon.circom"
component main = Poseidon(2, 6, 8, 57);

View File

@@ -2,6 +2,7 @@ const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
// const crypto = require("crypto");
const eddsa = require("../src/eddsa.js");
const babyJub = require("../src/babyjub.js");
@@ -45,7 +46,7 @@ describe("EdDSA test", function () {
it("Sign a single 10 bytes from 0 to 9", async () => {
const msg = Buffer.from("00010203040506070809", "hex");
// const prvKey = eddsa.cratePrvKey();
// const prvKey = crypto.randomBytes(32);
const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex");

View File

@@ -9,7 +9,7 @@ const assert = chai.assert;
const bigInt = snarkjs.bigInt;
describe("EdDSA test", function () {
describe("EdDSA MiMC test", function () {
let circuit;
this.timeout(100000);

39
test/poseidoncircuit.js Normal file
View File

@@ -0,0 +1,39 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const poseidon = require("../src/poseidon.js");
const assert = chai.assert;
describe("Poseidon Circuit test", function () {
let circuit;
this.timeout(100000);
before( async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "poseidon_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("Poseidon constraints: " + circuit.nConstraints);
});
it("Should check constrain", async () => {
const w = circuit.calculateWitness({inputs: [1, 2]});
const res = w[circuit.getSignalIdx("main.out")];
const hash = poseidon.createHash(6, 8, 57);
const res2 = hash([1,2]);
console.log(res.toString());
assert.equal(res.toString(), res2.toString());
assert(circuit.checkWitness(w));
});
});

59
test/poseidoncontract.js Normal file
View File

@@ -0,0 +1,59 @@
const TestRPC = 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 bigInt = require("snarkjs").bigInt;
const assert = chai.assert;
const log = (msg) => { if (process.env.MOCHA_VERBOSE) console.log(msg); };
const SEED = "mimc";
describe("Poseidon Smart contract test", () => {
let testrpc;
let web3;
let mimc;
let accounts;
before(async () => {
testrpc = TestRPC.server({
ws: true,
gasLimit: 5800000,
total_accounts: 10,
});
testrpc.listen(8546, "127.0.0.1");
web3 = new Web3("ws://127.0.0.1:8546");
accounts = await web3.eth.getAccounts();
});
after(async () => testrpc.close());
it("Should deploy the contract", async () => {
const C = new web3.eth.Contract(poseidonGenContract.abi);
mimc = await C.deploy({
data: poseidonGenContract.createCode()
}).send({
gas: 2500000,
from: accounts[0]
});
});
it("Shold calculate the mimic correctly", async () => {
const res = await mimc.methods.poseidon([1,2]).call();
// console.log("Cir: " + bigInt(res.toString(16)).toString(16));
const hash = Poseidon.createHash(6, 8, 57);
const res2 = hash([1,2]);
// console.log("Ref: " + bigInt(res2).toString(16));
assert.equal(res.toString(), res2.toString());
});
});

View File

@@ -84,7 +84,7 @@ describe("SMT test", function () {
let circuit;
let tree;
this.timeout(100000);
this.timeout(10000000);
before( async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "smtprocessor10_test.circom"));

View File

@@ -1,231 +0,0 @@
const chai = require("chai");
const snarkjs = require("snarkjs");
const smt = require("../src/smt.js");
const mimcjs = require("../src/mimc7.js");
const assert = chai.assert;
const expect = chai.expect;
const bigInt = snarkjs.bigInt;
function stringifyBigInts(o) {
if ((typeof(o) == "bigint") || (o instanceof bigInt)) {
return o.toString(10);
} else if (Array.isArray(o)) {
return o.map(stringifyBigInts);
} else if (typeof o == "object") {
const res = {};
for (let k in o) {
res[k] = stringifyBigInts(o[k]);
}
return res;
} else {
return o;
}
}
function newEntryFromInts(a, b, c, d) {
return {
hi: mimcjs.hash(c, d),
hv: mimcjs.hash(a, b),
};
}
function smtHash(arr) {
let r = bigInt(0);
for (let i=0; i<arr.length; i++) {
r = mimcjs.hash(r, bigInt(arr[i]), 91 );
}
return r;
}
describe("SMT Javascript test", function () {
this.timeout(100000);
before( async () => {
});
it("test MIMC7", async() => {
//const h = mimcjs.multiHash(1,2,3);
//const h = smtHash([1,2,3]);
//console.log(h.toString(10));
const mimcjs = require("../src/mimc7.js");
const snarkjs = require("snarkjs");
const bigInt = snarkjs.bigInt;
const smt = require("../src/smt.js");
h = mimcjs.hash(1,2,91);
console.log(h);
function smtHash(arr) {
let r = bigInt(0);
for (let i=0; i<arr.length; i++) {
r = mimcjs.hash(r, bigInt(arr[i]), 91 );
}
return r;
}
console.log(smtHash([1, 2, 3]));
// Test from old ver
});
//it("Should calculate hindex", async() => {
// const entry = newEntryFromInts(12, 45, 78, 41);
// //console.log(entry.hi.toString(16));
// expect(entry.hi.toString(16)).to.be.
// equal("114438e8321f62c4a1708f443a5a66f9c8fcb0958e7b7008332b71442610b7a0");
//});
//it("Should insert 2 elements and empty them", async () => {
// const tree = await smt.newMemEmptyTrie();
// const key1 = bigInt(111);
// const value1 = bigInt(222);
// const key2 = bigInt(333);
// const value2 = bigInt(444);
// await tree.insert(key1,value1);
// await tree.insert(key2,value2);
// await tree.delete(key2);
// await tree.delete(key1);
// assert(tree.root.isZero());
//});
//it("Should insert 3 elements in dferent order and should be the same", async () => {
// const keys = [bigInt(8), bigInt(9), bigInt(32)];
// const values = [bigInt(88), bigInt(99), bigInt(3232)];
// const tree1 = await smt.newMemEmptyTrie();
// const tree2 = await smt.newMemEmptyTrie();
// const tree3 = await smt.newMemEmptyTrie();
// const tree4 = await smt.newMemEmptyTrie();
// const tree5 = await smt.newMemEmptyTrie();
// const tree6 = await smt.newMemEmptyTrie();
// await tree1.insert(keys[0],values[0]);
// await tree1.insert(keys[1],values[1]);
// await tree1.insert(keys[2],values[2]);
// await tree2.insert(keys[0],values[0]);
// await tree2.insert(keys[2],values[2]);
// await tree2.insert(keys[1],values[1]);
// await tree3.insert(keys[1],values[1]);
// await tree3.insert(keys[0],values[0]);
// await tree3.insert(keys[2],values[2]);
// await tree4.insert(keys[1],values[1]);
// await tree4.insert(keys[2],values[2]);
// await tree4.insert(keys[0],values[0]);
// await tree5.insert(keys[2],values[2]);
// await tree5.insert(keys[0],values[0]);
// await tree5.insert(keys[1],values[1]);
// await tree6.insert(keys[2],values[2]);
// await tree6.insert(keys[1],values[1]);
// await tree6.insert(keys[0],values[0]);
// assert(tree1.root.equals(tree2.root));
// assert(tree2.root.equals(tree3.root));
// assert(tree3.root.equals(tree4.root));
// assert(tree4.root.equals(tree5.root));
// assert(tree5.root.equals(tree6.root));
// assert.equal(Object.keys(tree1.db.nodes).length, Object.keys(tree2.db.nodes).length);
// assert.equal(Object.keys(tree2.db.nodes).length, Object.keys(tree3.db.nodes).length);
// assert.equal(Object.keys(tree3.db.nodes).length, Object.keys(tree4.db.nodes).length);
// assert.equal(Object.keys(tree4.db.nodes).length, Object.keys(tree5.db.nodes).length);
// assert.equal(Object.keys(tree5.db.nodes).length, Object.keys(tree6.db.nodes).length);
// await tree1.delete(keys[0]);
// await tree1.delete(keys[1]);
// await tree2.delete(keys[1]);
// await tree2.delete(keys[0]);
// assert(tree1.root.equals(tree2.root));
// await tree3.delete(keys[0]);
// await tree3.delete(keys[2]);
// await tree4.delete(keys[2]);
// await tree4.delete(keys[0]);
// assert(tree3.root.equals(tree4.root));
// await tree5.delete(keys[1]);
// await tree5.delete(keys[2]);
// await tree6.delete(keys[2]);
// await tree6.delete(keys[1]);
// assert(tree5.root.equals(tree6.root));
// await tree1.delete(keys[2]);
// await tree2.delete(keys[2]);
// await tree3.delete(keys[1]);
// await tree4.delete(keys[1]);
// await tree5.delete(keys[0]);
// await tree6.delete(keys[0]);
// assert(tree1.root.isZero());
// assert(tree2.root.isZero());
// assert(tree3.root.isZero());
// assert(tree4.root.isZero());
// assert(tree5.root.isZero());
// assert(tree6.root.isZero());
// assert.equal(Object.keys(tree1.db.nodes).length, 0);
// assert.equal(Object.keys(tree2.db.nodes).length, 0);
// assert.equal(Object.keys(tree3.db.nodes).length, 0);
// assert.equal(Object.keys(tree4.db.nodes).length, 0);
// assert.equal(Object.keys(tree5.db.nodes).length, 0);
// assert.equal(Object.keys(tree6.db.nodes).length, 0);
//});
//it("Insert and remove 100 numbers randomly", async () => {
// function perm(a) {
// const arr = a.slice();
// const rArr = [];
// for (let i=0; i<arr.length; i++) {
// let rIdx = Math.floor(Math.random() * (arr.length - i));
// rArr.push(arr[rIdx]);
// arr[rIdx] = arr[arr.length - i - 1];
// }
// return rArr;
// }
// const tree = await smt.newMemEmptyTrie();
// const arr = [];
// const N = 100;
// for (let i=0; i<N; i++) {
// arr.push(bigInt(i));
// }
// const insArr = perm(arr);
// for (let i=0; i<N; i++) {
// await tree.insert(insArr[i], i);
// }
// const delArr = perm(insArr);
// for (let i=0; i<N; i++) {
// await tree.delete(delArr[i]);
// }
// assert(tree.root.isZero());
// assert.equal(Object.keys(tree.db.nodes).length, 0);
//});
//it("Should test update", async () => {
// const tree1 = await smt.newMemEmptyTrie();
// const tree2 = await smt.newMemEmptyTrie();
// await tree1.insert(8,88);
// await tree1.insert(9,99,);
// await tree1.insert(32,3232);
// await tree2.insert(8,888);
// await tree2.insert(9,999);
// await tree2.insert(32,323232);
// await tree1.update(8, 888);
// await tree1.update(9, 999);
// await tree1.update(32, 323232);
// assert(tree1.root.equals(tree2.root));
//});
});