mirror of
https://github.com/arnaucube/circomlib.git
synced 2026-02-06 18:56:43 +01:00
working with some errors yet
This commit is contained in:
29
src/mimc7.js
29
src/mimc7.js
@@ -3,35 +3,34 @@ const bigInt = require("snarkjs").bigInt;
|
||||
const Web3 = require("web3");
|
||||
const F = bn128.Fr;
|
||||
|
||||
module.exports.hash = MiMC7Hash;
|
||||
module.exports.getConstants = getConstants;
|
||||
|
||||
const SEED = "iden3_mimc";
|
||||
const nRounds = 91;
|
||||
|
||||
function getConstants(seed, nRounds) {
|
||||
|
||||
exports.getConstants = (seed, nRounds) => {
|
||||
const cts = new Array(nRounds);
|
||||
let c = Web3.utils.keccak256(SEED);
|
||||
for (let i=1; i<nRounds; i++) {
|
||||
c = Web3.utils.keccak256(c);
|
||||
|
||||
const n1 = Web3.utils.toBN(c).mod(Web3.utils.toBN(F.q.toString()));
|
||||
cts[i] = Web3.utils.padLeft(Web3.utils.toHex(n1), 64);
|
||||
const c2 = Web3.utils.padLeft(Web3.utils.toHex(n1), 64);
|
||||
cts[i] = bigInt(Web3.utils.toBN(c2).toString());
|
||||
}
|
||||
cts[0] = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
||||
cts[0] = bigInt(0);
|
||||
return cts;
|
||||
}
|
||||
};
|
||||
|
||||
function MiMC7Hash(_x_in, _k, nRounds) {
|
||||
const cts = exports.getConstants(SEED, 91);
|
||||
|
||||
exports.hash = (_x_in, _k) =>{
|
||||
const x_in = bigInt(_x_in);
|
||||
const k = bigInt(_k);
|
||||
const cts = getConstants(SEED, nRounds);
|
||||
let r;
|
||||
for (let i=0; i<nRounds; i++) {
|
||||
const c = bigInt(Web3.utils.toBN(cts[i]).toString());
|
||||
let t = (i==0) ? F.add(x_in, k) : F.add(F.add(r, k), c);
|
||||
let t2 = F.square(t);
|
||||
let t4 = F.square(t2);
|
||||
r = F.mul(F.mul(t4, t2), t);
|
||||
const c = cts[i];
|
||||
const t = (i==0) ? F.add(x_in, k) : F.add(F.add(r, k), c);
|
||||
r = F.exp(t, 7);
|
||||
}
|
||||
return F.affine(F.add(r, k));
|
||||
}
|
||||
};
|
||||
|
||||
144
src/smt.js
144
src/smt.js
@@ -1,12 +1,12 @@
|
||||
const bigInt = require("snarkjs").bigInt;
|
||||
|
||||
const SMTMemDB = require("./smt_memdb");
|
||||
const mimc7 = require("./mimc7");
|
||||
const mimc7 = require("./mimc7").hash;
|
||||
|
||||
function smtHash(arr) {
|
||||
let r = bigInt(0);
|
||||
for (let i=0; i<arr.length; i++) {
|
||||
r = mimc7.hash(r, bigInt(arr[i]), 91 );
|
||||
r = mimc7(r, bigInt(arr[i]));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
@@ -37,6 +37,92 @@ class SMT {
|
||||
return res;
|
||||
}
|
||||
|
||||
async delete(_key) {
|
||||
const key = bigInt(_key);
|
||||
|
||||
const resFind = await this.find(key);
|
||||
if (!resFind.found) throw new Error("Key does not exists");
|
||||
|
||||
const res = {
|
||||
sibblings: [],
|
||||
delKey: key,
|
||||
delValue: resFind.foundValue
|
||||
};
|
||||
|
||||
const dels = [];
|
||||
const ins = [];
|
||||
let rtOld = smtHash([1, key, resFind.foundValue]);
|
||||
let rtNew;
|
||||
dels.push(rtOld);
|
||||
|
||||
|
||||
let mixed;
|
||||
if (resFind.sibblings.length > 0) {
|
||||
const record = await this.db.get(resFind.sibblings[resFind.sibblings.length - 1]);
|
||||
if ((record.length == 3)&&(record[0].equals(bigInt.one))) {
|
||||
mixed = false;
|
||||
res.oldKey = record[1];
|
||||
res.oldValue = record[2];
|
||||
res.isOld0 = false;
|
||||
rtNew = resFind.sibblings[resFind.sibblings.length - 1];
|
||||
} else if (record.length == 2) {
|
||||
mixed = true;
|
||||
res.oldKey = key;
|
||||
res.oldValue = bigInt(0);
|
||||
res.isOld0 = true;
|
||||
rtNew = bigInt.zero;
|
||||
} else {
|
||||
throw new Error("Invalid node. Database corrupted");
|
||||
}
|
||||
} else {
|
||||
rtNew = bigInt.zero;
|
||||
res.oldKey = key;
|
||||
res.oldValue = bigInt(0);
|
||||
res.isOld0 = true;
|
||||
}
|
||||
|
||||
const keyBits = this._splitBits(key);
|
||||
|
||||
for (let level = resFind.sibblings.length-1; level >=0; level--) {
|
||||
let newSibling = resFind.sibblings[level];
|
||||
if ((level == resFind.sibblings.length-1)&&(!res.isOld0)) {
|
||||
newSibling = bigInt.zero;
|
||||
}
|
||||
const oldSibling = resFind.sibblings[level];
|
||||
if (keyBits[level]) {
|
||||
rtOld = smtHash([oldSibling, rtOld]);
|
||||
} else {
|
||||
rtOld = smtHash([rtOld, oldSibling]);
|
||||
}
|
||||
dels.push(rtOld);
|
||||
if (!newSibling.isZero()) {
|
||||
mixed = true;
|
||||
}
|
||||
|
||||
if (mixed) {
|
||||
res.sibblings.unshift(resFind.sibblings[level]);
|
||||
let newNode;
|
||||
if (keyBits[level]) {
|
||||
newNode = [newSibling, rtNew];
|
||||
} else {
|
||||
newNode = [rtNew, newSibling];
|
||||
}
|
||||
rtNew = smtHash(newNode);
|
||||
ins.push([rtNew, newNode]);
|
||||
}
|
||||
}
|
||||
|
||||
await this.db.multiIns(ins);
|
||||
await this.db.setRoot(rtNew);
|
||||
this.root = rtNew;
|
||||
await this.db.multiDel(dels);
|
||||
|
||||
res.newRoot = rtNew;
|
||||
res.oldRoot = rtOld;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
async insert(_key, _value) {
|
||||
const key = bigInt(_key);
|
||||
const value = bigInt(_value);
|
||||
@@ -44,34 +130,60 @@ class SMT {
|
||||
const res = {};
|
||||
res.oldRoot = this.root;
|
||||
const newKeyBits = this._splitBits(key);
|
||||
|
||||
let rtOld;
|
||||
|
||||
const resFind = await this.find(key);
|
||||
|
||||
if (resFind.found) throw new Error("Key already exists");
|
||||
|
||||
res.sibblings = resFind.sibblings;
|
||||
let mixed;
|
||||
|
||||
if (!resFind.isOld0) {
|
||||
const oldKeyits = this._splitBits(resFind.notFoundKey);
|
||||
for (let i= res.sibblings.length; oldKeyits[i] == newKeyBits[i]; i++) {
|
||||
res.sibblings.push(bigInt.zero);
|
||||
}
|
||||
res.sibblings.push(smtHash([1, resFind.notFoundKey, resFind.notFoundValue]));
|
||||
rtOld = smtHash([1, resFind.notFoundKey, resFind.notFoundValue]);
|
||||
res.sibblings.push(rtOld);
|
||||
addedOne = true;
|
||||
mixed = false;
|
||||
} else if (res.sibblings.length >0) {
|
||||
mixed = true;
|
||||
rtOld = bigInt.zero;
|
||||
}
|
||||
|
||||
const inserts = [];
|
||||
const dels = [];
|
||||
|
||||
let rt = smtHash([1, key, value]);
|
||||
inserts.push([rt,[1, key, value]] );
|
||||
|
||||
for (let i=res.sibblings.length-1; i>=0; i--) {
|
||||
if (newKeyBits[i]) {
|
||||
rt = smtHash([res.sibblings[i], rt]);
|
||||
inserts.push([rt,[res.sibblings[i], rt]] );
|
||||
} else {
|
||||
rt = smtHash([rt, res.sibblings[i]]);
|
||||
inserts.push([rt,[rt, res.sibblings[i]]] );
|
||||
if ((i<res.sibblings.length-1)&&(!res.sibblings[i].isZero())) {
|
||||
mixed = true;
|
||||
}
|
||||
if (mixed) {
|
||||
const oldSibling = resFind.sibblings[i];
|
||||
if (newKeyBits[i]) {
|
||||
rtOld = smtHash([oldSibling, rtOld]);
|
||||
} else {
|
||||
rtOld = smtHash([rtOld, oldSibling]);
|
||||
}
|
||||
dels.push(rtOld);
|
||||
}
|
||||
|
||||
|
||||
let newRt;
|
||||
if (newKeyBits[i]) {
|
||||
newRt = smtHash([res.sibblings[i], rt]);
|
||||
inserts.push([newRt,[res.sibblings[i], rt]] );
|
||||
} else {
|
||||
newRt = smtHash([rt, res.sibblings[i]]);
|
||||
inserts.push([newRt,[rt, res.sibblings[i]]] );
|
||||
}
|
||||
rt = newRt;
|
||||
}
|
||||
|
||||
if (addedOne) res.sibblings.pop();
|
||||
@@ -83,9 +195,11 @@ class SMT {
|
||||
res.newRoot = rt;
|
||||
res.isOld0 = resFind.isOld0;
|
||||
|
||||
this.root = rt;
|
||||
|
||||
await this.db.save(rt, inserts);
|
||||
await this.db.multiIns(inserts);
|
||||
await this.db.setRoot(rt);
|
||||
this.root = rt;
|
||||
await this.db.multiDel(dels);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -131,11 +245,11 @@ class SMT {
|
||||
}
|
||||
} else {
|
||||
if (keyBits[level] == 0) {
|
||||
const res = await this.find(key, keyBits, record[1], level+1);
|
||||
res.sibblings.unshift(record[2]);
|
||||
} else {
|
||||
res = await this.find(key, keyBits, record[2], level+1);
|
||||
res = await this._find(key, keyBits, record[0], level+1);
|
||||
res.sibblings.unshift(record[1]);
|
||||
} else {
|
||||
res = await this._find(key, keyBits, record[1], level+1);
|
||||
res.sibblings.unshift(record[0]);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
||||
@@ -10,21 +10,40 @@ class SMTMemDb {
|
||||
return this.root;
|
||||
}
|
||||
|
||||
async get(key) {
|
||||
const res = [];
|
||||
const keyS = bigInt(key).leInt2Buff(32).toString("hex");
|
||||
for (let i=0; i<this.nodes[keyS].length; i++) {
|
||||
res.push(bigInt(this.nodes[keyS][i]));
|
||||
}
|
||||
return res;
|
||||
_key2str(k) {
|
||||
// const keyS = bigInt(key).leInt2Buff(32).toString("hex");
|
||||
const keyS = bigInt(k).toString();
|
||||
return keyS;
|
||||
}
|
||||
|
||||
async save(root, inserts) {
|
||||
_normalize(n) {
|
||||
for (let i=0; i<n.length; i++) {
|
||||
n[i] = bigInt(n[i]);
|
||||
}
|
||||
}
|
||||
|
||||
async get(key) {
|
||||
const keyS = this._key2str(key);
|
||||
return this.nodes[keyS];
|
||||
}
|
||||
|
||||
async setRoot(rt) {
|
||||
this.root = rt;
|
||||
}
|
||||
|
||||
async multiIns(inserts) {
|
||||
for (let i=0; i<inserts.length; i++) {
|
||||
const keyS = bigInt(inserts[i][0]).leInt2Buff(32).toString("hex");
|
||||
const keyS = this._key2str(inserts[i][0]);
|
||||
this._normalize(inserts[i][1]);
|
||||
this.nodes[keyS] = inserts[i][1];
|
||||
}
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
async multiDel(dels) {
|
||||
for (let i=0; i<dels.length; i++) {
|
||||
const keyS = this._key2str(dels[i]);
|
||||
delete this.nodes[keyS];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user