mirror of
https://github.com/arnaucube/circomlib.git
synced 2026-02-06 18:56:43 +01:00
Blake to Blake2b and use of native big num
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
const bigInt = require("big-integer");
|
||||
const ZqField = require("ffjavascript").ZqField;
|
||||
const utils = require("./utils.js");
|
||||
const F1Field = require("ffjavascript").F1Field;
|
||||
const Scalar = require("ffjavascript").Scalar;
|
||||
const utils = require("ffjavascript").utils;
|
||||
|
||||
exports.addPoint = addPoint;
|
||||
exports.mulPointEscalar = mulPointEscalar;
|
||||
@@ -8,23 +8,27 @@ exports.inCurve = inCurve;
|
||||
exports.inSubgroup = inSubgroup;
|
||||
exports.packPoint = packPoint;
|
||||
exports.unpackPoint = unpackPoint;
|
||||
|
||||
|
||||
exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||
const F = new F1Field(exports.p);
|
||||
exports.F = F;
|
||||
|
||||
exports.Generator = [
|
||||
bigInt("995203441582195749578291179787384436505546430278305826713579947235728471134"),
|
||||
bigInt("5472060717959818805561601436314318772137091100104008585924551046643952123905")
|
||||
F.e("995203441582195749578291179787384436505546430278305826713579947235728471134"),
|
||||
F.e("5472060717959818805561601436314318772137091100104008585924551046643952123905")
|
||||
];
|
||||
exports.Base8 = [
|
||||
bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
|
||||
bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")
|
||||
F.e("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
|
||||
F.e("16950150798460657717958625567821834550301663161624707787222815936182638968203")
|
||||
];
|
||||
exports.order = bigInt("21888242871839275222246405745257275088614511777268538073601725287587578984328");
|
||||
exports.subOrder = exports.order.shiftRight(3);
|
||||
exports.p = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||
exports.A = bigInt("168700");
|
||||
exports.D = bigInt("168696");
|
||||
exports.order = Scalar.fromString("21888242871839275222246405745257275088614511777268538073601725287587578984328");
|
||||
exports.subOrder = Scalar.shiftRight(exports.order, 3);
|
||||
exports.A = F.e("168700");
|
||||
exports.D = F.e("168696");
|
||||
|
||||
|
||||
function addPoint(a,b) {
|
||||
const F = new ZqField(exports.p);
|
||||
|
||||
const res = [];
|
||||
|
||||
@@ -44,28 +48,28 @@ function addPoint(a,b) {
|
||||
|
||||
res[0] = F.div(
|
||||
F.add(beta, gamma),
|
||||
F.add(bigInt.one, dtau)
|
||||
F.add(F.one, dtau)
|
||||
);
|
||||
|
||||
res[1] = F.div(
|
||||
F.add(delta, F.sub(F.mul(exports.A,beta), gamma)),
|
||||
F.sub(bigInt.one, dtau)
|
||||
F.sub(F.one, dtau)
|
||||
);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
function mulPointEscalar(base, e) {
|
||||
let res = [bigInt("0"),bigInt("1")];
|
||||
let rem = bigInt(e);
|
||||
let res = [F.e("0"),F.e("1")];
|
||||
let rem = e;
|
||||
let exp = base;
|
||||
|
||||
while (! rem.isZero()) {
|
||||
if (rem.isOdd()) {
|
||||
while (! Scalar.isZero(rem)) {
|
||||
if (Scalar.isOdd(rem)) {
|
||||
res = addPoint(res, exp);
|
||||
}
|
||||
exp = addPoint(exp, exp);
|
||||
rem = rem.shiftRight(1);
|
||||
rem = Scalar.shiftRight(rem, 1);
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -74,11 +78,10 @@ function mulPointEscalar(base, e) {
|
||||
function inSubgroup(P) {
|
||||
if (!inCurve(P)) return false;
|
||||
const res= mulPointEscalar(P, exports.subOrder);
|
||||
return (res[0].equals(bigInt(0))) && (res[1].equals(bigInt(1)));
|
||||
return (F.isZero(res[0]) && F.eq(res[1], F.one));
|
||||
}
|
||||
|
||||
function inCurve(P) {
|
||||
const F = new ZqField(exports.p);
|
||||
|
||||
const x2 = F.square(P[0]);
|
||||
const y2 = F.square(P[1]);
|
||||
@@ -92,15 +95,13 @@ function inCurve(P) {
|
||||
|
||||
function packPoint(P) {
|
||||
const buff = utils.leInt2Buff(P[1], 32);
|
||||
if (P[0].greater(exports.p.shiftRight(1))) {
|
||||
if (F.lt(P[0], F.zero)) {
|
||||
buff[31] = buff[31] | 0x80;
|
||||
}
|
||||
return buff;
|
||||
}
|
||||
|
||||
function unpackPoint(_buff) {
|
||||
const F = new ZqField(exports.p);
|
||||
|
||||
const buff = Buffer.from(_buff);
|
||||
let sign = false;
|
||||
const P = new Array(2);
|
||||
@@ -109,7 +110,7 @@ function unpackPoint(_buff) {
|
||||
buff[31] = buff[31] & 0x7F;
|
||||
}
|
||||
P[1] = utils.leBuff2int(buff);
|
||||
if (P[1].greaterOrEquals(exports.p)) return null;
|
||||
if (Scalar.gt(P[1], exports.p)) return null;
|
||||
|
||||
const y2 = F.square(P[1]);
|
||||
|
||||
|
||||
77
src/eddsa.js
77
src/eddsa.js
@@ -1,7 +1,8 @@
|
||||
const createBlakeHash = require("blake-hash");
|
||||
const bigInt = require("big-integer");
|
||||
const blake2b = require("blake2b");
|
||||
const Scalar = require("ffjavascript").Scalar;
|
||||
const F1Field = require("ffjavascript").F1Field;
|
||||
const babyJub = require("./babyjub");
|
||||
const utils = require("./utils");
|
||||
const utils = require("ffjavascript").utils;
|
||||
const pedersenHash = require("./pedersenHash").hash;
|
||||
const mimc7 = require("./mimc7");
|
||||
const poseidon = require("./poseidon.js");
|
||||
@@ -31,27 +32,28 @@ function pruneBuffer(_buff) {
|
||||
}
|
||||
|
||||
function prv2pub(prv) {
|
||||
const sBuff = pruneBuffer(createBlakeHash("blake512").update(prv).digest().slice(0,32));
|
||||
const sBuff = pruneBuffer(blake2b(64).update(prv).digest().slice(0,32));
|
||||
let s = utils.leBuff2int(sBuff);
|
||||
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shiftRight(3));
|
||||
const A = babyJub.mulPointEscalar(babyJub.Base8, Scalar.shr(s,3));
|
||||
return A;
|
||||
}
|
||||
|
||||
function sign(prv, msg) {
|
||||
const h1 = createBlakeHash("blake512").update(prv).digest();
|
||||
const h1 = Buffer.from(blake2b(64).update(prv).digest());
|
||||
const sBuff = pruneBuffer(h1.slice(0,32));
|
||||
const s = utils.leBuff2int(sBuff);
|
||||
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shiftRight(3));
|
||||
const A = babyJub.mulPointEscalar(babyJub.Base8, Scalar.shr(s, 3));
|
||||
|
||||
const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msg])).digest();
|
||||
const rBuff = Buffer.from(blake2b(64).update(Buffer.concat([h1.slice(32,64), msg])).digest());
|
||||
let r = utils.leBuff2int(rBuff);
|
||||
r = r.mod(babyJub.subOrder);
|
||||
const Fr = new F1Field(babyJub.subOrder);
|
||||
r = Fr.e(r);
|
||||
const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
|
||||
const R8p = babyJub.packPoint(R8);
|
||||
const Ap = babyJub.packPoint(A);
|
||||
const hmBuff = pedersenHash(Buffer.concat([R8p, Ap, msg]));
|
||||
const hm = utils.leBuff2int(hmBuff);
|
||||
const S = r.add(hm.times(s)).mod(babyJub.subOrder);
|
||||
const S = Fr.add(r , Fr.mul(hm, s));
|
||||
return {
|
||||
R8: R8,
|
||||
S: S
|
||||
@@ -59,18 +61,19 @@ function sign(prv, msg) {
|
||||
}
|
||||
|
||||
function signMiMC(prv, msg) {
|
||||
const h1 = createBlakeHash("blake512").update(prv).digest();
|
||||
const h1 = Buffer.from(blake2b(64).update(prv).digest());
|
||||
const sBuff = pruneBuffer(h1.slice(0,32));
|
||||
const s = utils.leBuff2int(sBuff);
|
||||
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shiftRight(3));
|
||||
const A = babyJub.mulPointEscalar(babyJub.Base8, Scalar.shr(s, 3));
|
||||
|
||||
const msgBuff = utils.leInt2Buff(msg, 32);
|
||||
const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
|
||||
const rBuff = Buffer.from(blake2b(64).update(Buffer.concat([h1.slice(32,64), msgBuff])).digest());
|
||||
let r = utils.leBuff2int(rBuff);
|
||||
r = r.mod(babyJub.subOrder);
|
||||
const Fr = new F1Field(babyJub.subOrder);
|
||||
r = Fr.e(r);
|
||||
const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
|
||||
const hm = mimc7.multiHash([R8[0], R8[1], A[0], A[1], msg]);
|
||||
const S = r.add(hm.times(s)).mod(babyJub.subOrder);
|
||||
const S = Fr.add(r , Fr.mul(hm, s));
|
||||
return {
|
||||
R8: R8,
|
||||
S: S
|
||||
@@ -78,18 +81,19 @@ function signMiMC(prv, msg) {
|
||||
}
|
||||
|
||||
function signMiMCSponge(prv, msg) {
|
||||
const h1 = createBlakeHash("blake512").update(prv).digest();
|
||||
const h1 = Buffer.from(blake2b(64).update(prv).digest());
|
||||
const sBuff = pruneBuffer(h1.slice(0,32));
|
||||
const s = utils.leBuff2int(sBuff);
|
||||
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shiftRight(3));
|
||||
const A = babyJub.mulPointEscalar(babyJub.Base8, Scalar.shr(s, 3));
|
||||
|
||||
const msgBuff = utils.leInt2Buff(msg, 32);
|
||||
const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
|
||||
const rBuff = Buffer.from(blake2b(64).update(Buffer.concat([h1.slice(32,64), msgBuff])).digest());
|
||||
let r = utils.leBuff2int(rBuff);
|
||||
r = r.mod(babyJub.subOrder);
|
||||
const Fr = new F1Field(babyJub.subOrder);
|
||||
r = Fr.e(r);
|
||||
const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
|
||||
const hm = mimcsponge.multiHash([R8[0], R8[1], A[0], A[1], msg]);
|
||||
const S = r.add(hm.times(s)).mod(babyJub.subOrder);
|
||||
const S = Fr.add(r , Fr.mul(hm, s));
|
||||
return {
|
||||
R8: R8,
|
||||
S: S
|
||||
@@ -97,19 +101,20 @@ function signMiMCSponge(prv, msg) {
|
||||
}
|
||||
|
||||
function signPoseidon(prv, msg) {
|
||||
const h1 = createBlakeHash("blake512").update(prv).digest();
|
||||
const h1 = Buffer.from(blake2b(64).update(prv).digest());
|
||||
const sBuff = pruneBuffer(h1.slice(0,32));
|
||||
const s = utils.leBuff2int(sBuff);
|
||||
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shiftRight(3));
|
||||
const A = babyJub.mulPointEscalar(babyJub.Base8, Scalar.shr(s, 3));
|
||||
|
||||
const msgBuff = utils.leInt2Buff(msg, 32);
|
||||
const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
|
||||
const rBuff = Buffer.from(blake2b(64).update(Buffer.concat([h1.slice(32,64), msgBuff])).digest());
|
||||
let r = utils.leBuff2int(rBuff);
|
||||
r = r.mod(babyJub.subOrder);
|
||||
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 S = r.add(hm.times(s)).mod(babyJub.subOrder);
|
||||
const S = Fr.add(r , Fr.mul(hm, s));
|
||||
return {
|
||||
R8: R8,
|
||||
S: S
|
||||
@@ -133,11 +138,11 @@ function verify(msg, sig, A) {
|
||||
const hm = utils.leBuff2int(hmBuff);
|
||||
|
||||
const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
|
||||
let Pright = babyJub.mulPointEscalar(A, hm.times(bigInt("8")));
|
||||
let Pright = babyJub.mulPointEscalar(A, Scalar.mul(hm,8));
|
||||
Pright = babyJub.addPoint(sig.R8, Pright);
|
||||
|
||||
if (!Pleft[0].equals(Pright[0])) return false;
|
||||
if (!Pleft[1].equals(Pright[1])) return false;
|
||||
if (!babyJub.F.eq(Pleft[0],Pright[0])) return false;
|
||||
if (!babyJub.F.eq(Pleft[1],Pright[1])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -155,11 +160,11 @@ function verifyMiMC(msg, sig, A) {
|
||||
const hm = mimc7.multiHash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
|
||||
|
||||
const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
|
||||
let Pright = babyJub.mulPointEscalar(A, hm.times(bigInt("8")));
|
||||
let Pright = babyJub.mulPointEscalar(A, Scalar.mul(hm, 8));
|
||||
Pright = babyJub.addPoint(sig.R8, Pright);
|
||||
|
||||
if (!Pleft[0].equals(Pright[0])) return false;
|
||||
if (!Pleft[1].equals(Pright[1])) return false;
|
||||
if (!babyJub.F.eq(Pleft[0],Pright[0])) return false;
|
||||
if (!babyJub.F.eq(Pleft[1],Pright[1])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -179,11 +184,11 @@ function verifyPoseidon(msg, sig, A) {
|
||||
const hm = hash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
|
||||
|
||||
const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
|
||||
let Pright = babyJub.mulPointEscalar(A, hm.times(bigInt("8")));
|
||||
let Pright = babyJub.mulPointEscalar(A, Scalar.mul(hm, 8));
|
||||
Pright = babyJub.addPoint(sig.R8, Pright);
|
||||
|
||||
if (!Pleft[0].equals(Pright[0])) return false;
|
||||
if (!Pleft[1].equals(Pright[1])) return false;
|
||||
if (!babyJub.F.eq(Pleft[0],Pright[0])) return false;
|
||||
if (!babyJub.F.eq(Pleft[1],Pright[1])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -204,8 +209,8 @@ function verifyMiMCSponge(msg, sig, A) {
|
||||
let Pright = babyJub.mulPointEscalar(A, hm.times(bigInt("8")));
|
||||
Pright = babyJub.addPoint(sig.R8, Pright);
|
||||
|
||||
if (!Pleft[0].equals(Pright[0])) return false;
|
||||
if (!Pleft[1].equals(Pright[1])) return false;
|
||||
if (!babyJub.F.eq(Pleft[0],Pright[0])) return false;
|
||||
if (!babyJub.F.eq(Pleft[1],Pright[1])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
const Contract = require("./evmasm");
|
||||
const G2 = require("snarkjs").bn128.G2;
|
||||
const bigInt = require("snarkjs").bigInt;
|
||||
|
||||
|
||||
function toHex256(a) {
|
||||
@@ -539,7 +538,7 @@ function createCode(P, w) {
|
||||
function storeVals() {
|
||||
C.push(VAR_POINTS); // p
|
||||
for (let i=0; i<NPOINTS; i++) {
|
||||
const MP = G2.affine(G2.mulScalar(P, bigInt(i)));
|
||||
const MP = G2.affine(G2.mulScalar(P, i));
|
||||
for (let j=0; j<2; j++) {
|
||||
for (let k=0; k<2; k++) {
|
||||
C.push(toHex256(MP[j][k])); // MP[0][0] p
|
||||
|
||||
17
src/mimc7.js
17
src/mimc7.js
@@ -1,8 +1,9 @@
|
||||
const bigInt = require("big-integer");
|
||||
const Scalar = require("ffjavascript").Scalar;
|
||||
const ZqField = require("ffjavascript").ZqField;
|
||||
|
||||
const Web3Utils = require("web3-utils");
|
||||
const F = new ZqField(bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
|
||||
const F = new ZqField(Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
|
||||
exports.F = F;
|
||||
|
||||
const SEED = "mimc";
|
||||
const NROUNDS = 91;
|
||||
@@ -10,7 +11,7 @@ const NROUNDS = 91;
|
||||
exports.getIV = (seed) => {
|
||||
if (typeof seed === "undefined") seed = SEED;
|
||||
const c = Web3Utils.keccak256(seed+"_iv");
|
||||
const cn = bigInt(Web3Utils.toBN(c).toString());
|
||||
const cn = Scalar.FromString(Web3Utils.toBN(c).toString());
|
||||
const iv = cn.mod(F.p);
|
||||
return iv;
|
||||
};
|
||||
@@ -25,17 +26,17 @@ exports.getConstants = (seed, nRounds) => {
|
||||
|
||||
const n1 = Web3Utils.toBN(c).mod(Web3Utils.toBN(F.p.toString()));
|
||||
const c2 = Web3Utils.padLeft(Web3Utils.toHex(n1), 64);
|
||||
cts[i] = bigInt(Web3Utils.toBN(c2).toString());
|
||||
cts[i] = Scalar.fromString(Web3Utils.toBN(c2).toString());
|
||||
}
|
||||
cts[0] = bigInt(0);
|
||||
cts[0] = F.e(0);
|
||||
return cts;
|
||||
};
|
||||
|
||||
const cts = exports.getConstants(SEED, 91);
|
||||
|
||||
exports.hash = (_x_in, _k) =>{
|
||||
const x_in = bigInt(_x_in);
|
||||
const k = bigInt(_k);
|
||||
const x_in = F.e(_x_in);
|
||||
const k = F.e(_k);
|
||||
let r;
|
||||
for (let i=0; i<NROUNDS; i++) {
|
||||
const c = cts[i];
|
||||
@@ -58,7 +59,7 @@ exports.multiHash = (arr, key) => {
|
||||
r,
|
||||
arr[i]
|
||||
),
|
||||
exports.hash(bigInt(arr[i]), r)
|
||||
exports.hash(F.e(arr[i]), r)
|
||||
);
|
||||
}
|
||||
return r;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const bigInt = require("big-integer");
|
||||
const Scalar = require("ffjavascript").Scalar
|
||||
const Web3Utils = require("web3-utils");
|
||||
const ZqField = require("ffjavascript").ZqField;
|
||||
const F = new ZqField(bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
|
||||
const F = new ZqField(Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
|
||||
|
||||
const SEED = "mimcsponge";
|
||||
const NROUNDS = 220;
|
||||
@@ -9,7 +9,7 @@ const NROUNDS = 220;
|
||||
exports.getIV = (seed) => {
|
||||
if (typeof seed === "undefined") seed = SEED;
|
||||
const c = Web3Utils.keccak256(seed+"_iv");
|
||||
const cn = bigInt(Web3Utils.toBN(c).toString());
|
||||
const cn = Scalar.fromString(Web3Utils.toBN(c).toString());
|
||||
const iv = cn.mod(F.p);
|
||||
return iv;
|
||||
};
|
||||
@@ -24,23 +24,23 @@ exports.getConstants = (seed, nRounds) => {
|
||||
|
||||
const n1 = Web3Utils.toBN(c).mod(Web3Utils.toBN(F.p.toString()));
|
||||
const c2 = Web3Utils.padLeft(Web3Utils.toHex(n1), 64);
|
||||
cts[i] = bigInt(Web3Utils.toBN(c2).toString());
|
||||
cts[i] = F.e(Web3Utils.toBN(c2).toString());
|
||||
}
|
||||
cts[0] = bigInt(0);
|
||||
cts[cts.length - 1] = bigInt(0);
|
||||
cts[0] = F.e(0);
|
||||
cts[cts.length - 1] = F.e(0);
|
||||
return cts;
|
||||
};
|
||||
|
||||
const cts = exports.getConstants(SEED, NROUNDS);
|
||||
|
||||
exports.hash = (_xL_in, _xR_in, _k) =>{
|
||||
let xL = bigInt(_xL_in);
|
||||
let xR = bigInt(_xR_in);
|
||||
const k = bigInt(_k);
|
||||
let xL = F.e(_xL_in);
|
||||
let xR = F.e(_xR_in);
|
||||
const k = F.e(_k);
|
||||
for (let i=0; i<NROUNDS; i++) {
|
||||
const c = cts[i];
|
||||
const t = (i==0) ? F.add(xL, k) : F.add(F.add(xL, k), c);
|
||||
const xR_tmp = bigInt(xR);
|
||||
const xR_tmp = F.e(xR);
|
||||
if (i < (NROUNDS - 1)) {
|
||||
xR = xL;
|
||||
xL = F.add(xR_tmp, F.pow(t, 5));
|
||||
@@ -66,7 +66,7 @@ exports.multiHash = (arr, key, numOutputs) => {
|
||||
let C = F.zero;
|
||||
|
||||
for (let i=0; i<arr.length; i++) {
|
||||
R = F.add(R, bigInt(arr[i]));
|
||||
R = F.add(R, F.e(arr[i]));
|
||||
const S = exports.hash(R, C, key);
|
||||
R = S.xL;
|
||||
C = S.xR;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const bigInt = require("big-integer");
|
||||
const babyJub = require("./babyjub");
|
||||
const createBlakeHash = require("blake-hash");
|
||||
const blake2b = require("blake2b");
|
||||
const Scalar = require("ffjavascript").Scalar;
|
||||
|
||||
const GENPOINT_PREFIX = "PedersenGenerator";
|
||||
const windowSize = 4;
|
||||
@@ -15,7 +15,7 @@ function pedersenHash(msg) {
|
||||
|
||||
const nSegments = Math.floor((bits.length - 1)/(windowSize*nWindowsPerSegment)) +1;
|
||||
|
||||
let accP = [bigInt.zero,bigInt.one];
|
||||
let accP = [babyJub.F.zero,babyJub.F.one];
|
||||
|
||||
for (let s=0; s<nSegments; s++) {
|
||||
let nWindows;
|
||||
@@ -24,29 +24,29 @@ function pedersenHash(msg) {
|
||||
} else {
|
||||
nWindows = nWindowsPerSegment;
|
||||
}
|
||||
let escalar = bigInt.zero;
|
||||
let exp = bigInt.one;
|
||||
let escalar = Scalar.e(0);
|
||||
let exp = Scalar.e(1);
|
||||
for (let w=0; w<nWindows; w++) {
|
||||
let o = s*bitsPerSegment + w*windowSize;
|
||||
let acc = bigInt.one;
|
||||
let acc = Scalar.e(1);
|
||||
for (let b=0; ((b<windowSize-1)&&(o<bits.length)) ; b++) {
|
||||
if (bits[o]) {
|
||||
acc = acc.add( bigInt.one.shiftLeft(b) );
|
||||
acc = Scalar.add(acc, Scalar.shl(Scalar.e(1), b) );
|
||||
}
|
||||
o++;
|
||||
}
|
||||
if (o<bits.length) {
|
||||
if (bits[o]) {
|
||||
acc = bigInt.zero.minus(acc);
|
||||
acc = Scalar.neg(acc);
|
||||
}
|
||||
o++;
|
||||
}
|
||||
escalar = escalar.add(acc.times(exp));
|
||||
exp = exp.shiftLeft(windowSize+1);
|
||||
escalar = Scalar.add(escalar, Scalar.mul(acc, exp));
|
||||
exp = Scalar.shl(exp, windowSize+1);
|
||||
}
|
||||
|
||||
if (escalar.lesser(bigInt.zero)) {
|
||||
escalar = babyJub.subOrder.add(escalar);
|
||||
if (Scalar.lt(escalar, 0)) {
|
||||
escalar = Scalar.add( escalar, babyJub.subOrder);
|
||||
}
|
||||
|
||||
accP = babyJub.addPoint(accP, babyJub.mulPointEscalar(getBasePoint(s), escalar));
|
||||
@@ -63,7 +63,7 @@ function getBasePoint(pointIdx) {
|
||||
let tryIdx = 0;
|
||||
while (p==null) {
|
||||
const S = GENPOINT_PREFIX + "_" + padLeftZeros(pointIdx, 32) + "_" + padLeftZeros(tryIdx, 32);
|
||||
const h = createBlakeHash("blake256").update(S).digest();
|
||||
const h = Buffer.from(blake2b(32).update(Buffer.from(S)).digest());
|
||||
h[31] = h[31] & 0xBF; // Set 255th bit to 0 (256th is the signal and 254th is the last possible bit to 1)
|
||||
p = babyJub.unpackPoint(h);
|
||||
tryIdx++;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
const bigInt = require("big-integer");
|
||||
const Scalar = require("ffjavascript").Scalar;
|
||||
const blake2b = require("blake2b");
|
||||
const assert = require("assert");
|
||||
const ZqField = require("ffjavascript").ZqField;
|
||||
const utils = require("./utils");
|
||||
const utils = require("ffjavascript").utils;
|
||||
|
||||
const F = new ZqField(bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
|
||||
const F = new ZqField(Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
|
||||
exports.F = F;
|
||||
|
||||
const SEED = "poseidon";
|
||||
const NROUNDSF = 8;
|
||||
@@ -16,7 +17,7 @@ function getPseudoRandom(seed, n) {
|
||||
let input = Buffer.from(seed);
|
||||
let h = blake2b(32).update(input).digest();
|
||||
while (res.length<n) {
|
||||
const n = F.normalize(utils.leBuff2int(h));
|
||||
const n = F.normalize(utils.leBuff2int(Buffer.from(h)));
|
||||
res.push(n);
|
||||
h = blake2b(32).update(h).digest();
|
||||
}
|
||||
@@ -26,9 +27,9 @@ function getPseudoRandom(seed, n) {
|
||||
|
||||
function allDifferent(v) {
|
||||
for (let i=0; i<v.length; i++) {
|
||||
if (v[i].isZero()) return false;
|
||||
if (F.isZero(v[i])) return false;
|
||||
for (let j=i+1; j<v.length; j++) {
|
||||
if (v[i].equals(v[j])) return false;
|
||||
if (F.eq(v[i],v[j])) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -101,7 +102,7 @@ exports.createHash = (t, nRoundsF, nRoundsP, seed) => {
|
||||
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=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++) {
|
||||
|
||||
58
src/smt.js
58
src/smt.js
@@ -1,7 +1,6 @@
|
||||
const bigInt = require("big-integer");
|
||||
|
||||
const Scalar = require("ffjavascript").Scalar;
|
||||
const SMTMemDB = require("./smt_memdb");
|
||||
const {hash0, hash1} = require("./smt_hashes_poseidon");
|
||||
const {hash0, hash1, F} = require("./smt_hashes_poseidon");
|
||||
|
||||
class SMT {
|
||||
|
||||
@@ -11,18 +10,7 @@ class SMT {
|
||||
}
|
||||
|
||||
_splitBits(_key) {
|
||||
|
||||
let k = bigInt(_key);
|
||||
const res = [];
|
||||
|
||||
while (!k.isZero()) {
|
||||
if (k.isOdd()) {
|
||||
res.push(true);
|
||||
} else {
|
||||
res.push(false);
|
||||
}
|
||||
k = k.shiftRight(1);
|
||||
}
|
||||
const res = Scalar.bits(_key);
|
||||
|
||||
while (res.length<256) res.push(false);
|
||||
|
||||
@@ -30,8 +18,8 @@ class SMT {
|
||||
}
|
||||
|
||||
async update(_key, _newValue) {
|
||||
const key = bigInt(_key);
|
||||
const newValue = bigInt(_newValue);
|
||||
const key = Scalar.e(_key);
|
||||
const newValue = F.e(_newValue);
|
||||
|
||||
|
||||
const resFind = await this.find(key);
|
||||
@@ -79,7 +67,7 @@ class SMT {
|
||||
}
|
||||
|
||||
async delete(_key) {
|
||||
const key = bigInt(_key);
|
||||
const key = Scalar.e(_key);
|
||||
|
||||
const resFind = await this.find(key);
|
||||
if (!resFind.found) throw new Error("Key does not exists");
|
||||
@@ -99,7 +87,7 @@ class SMT {
|
||||
let mixed;
|
||||
if (resFind.siblings.length > 0) {
|
||||
const record = await this.db.get(resFind.siblings[resFind.siblings.length - 1]);
|
||||
if ((record.length == 3)&&(record[0].equals(bigInt.one))) {
|
||||
if ((record.length == 3)&&(F.eq(record[0], F.one))) {
|
||||
mixed = false;
|
||||
res.oldKey = record[1];
|
||||
res.oldValue = record[2];
|
||||
@@ -108,16 +96,16 @@ class SMT {
|
||||
} else if (record.length == 2) {
|
||||
mixed = true;
|
||||
res.oldKey = key;
|
||||
res.oldValue = bigInt(0);
|
||||
res.oldValue = F.zero;
|
||||
res.isOld0 = true;
|
||||
rtNew = bigInt.zero;
|
||||
rtNew = F.zero;
|
||||
} else {
|
||||
throw new Error("Invalid node. Database corrupted");
|
||||
}
|
||||
} else {
|
||||
rtNew = bigInt.zero;
|
||||
rtNew = F.zero;
|
||||
res.oldKey = key;
|
||||
res.oldValue = bigInt(0);
|
||||
res.oldValue = F.zero;
|
||||
res.isOld0 = true;
|
||||
}
|
||||
|
||||
@@ -126,7 +114,7 @@ class SMT {
|
||||
for (let level = resFind.siblings.length-1; level >=0; level--) {
|
||||
let newSibling = resFind.siblings[level];
|
||||
if ((level == resFind.siblings.length-1)&&(!res.isOld0)) {
|
||||
newSibling = bigInt.zero;
|
||||
newSibling = F.zero;
|
||||
}
|
||||
const oldSibling = resFind.siblings[level];
|
||||
if (keyBits[level]) {
|
||||
@@ -135,7 +123,7 @@ class SMT {
|
||||
rtOld = hash0(rtOld, oldSibling);
|
||||
}
|
||||
dels.push(rtOld);
|
||||
if (!newSibling.isZero()) {
|
||||
if (!F.isZero(newSibling)) {
|
||||
mixed = true;
|
||||
}
|
||||
|
||||
@@ -164,8 +152,8 @@ class SMT {
|
||||
}
|
||||
|
||||
async insert(_key, _value) {
|
||||
const key = bigInt(_key);
|
||||
const value = bigInt(_value);
|
||||
const key = Scalar.e(_key);
|
||||
const value = F.e(_value);
|
||||
let addedOne = false;
|
||||
const res = {};
|
||||
res.oldRoot = this.root;
|
||||
@@ -183,7 +171,7 @@ class SMT {
|
||||
if (!resFind.isOld0) {
|
||||
const oldKeyits = this._splitBits(resFind.notFoundKey);
|
||||
for (let i= res.siblings.length; oldKeyits[i] == newKeyBits[i]; i++) {
|
||||
res.siblings.push(bigInt.zero);
|
||||
res.siblings.push(F.zero);
|
||||
}
|
||||
rtOld = hash1(resFind.notFoundKey, resFind.notFoundValue);
|
||||
res.siblings.push(rtOld);
|
||||
@@ -191,7 +179,7 @@ class SMT {
|
||||
mixed = false;
|
||||
} else if (res.siblings.length >0) {
|
||||
mixed = true;
|
||||
rtOld = bigInt.zero;
|
||||
rtOld = F.zero;
|
||||
}
|
||||
|
||||
const inserts = [];
|
||||
@@ -201,7 +189,7 @@ class SMT {
|
||||
inserts.push([rt,[1, key, value]] );
|
||||
|
||||
for (let i=res.siblings.length-1; i>=0; i--) {
|
||||
if ((i<res.siblings.length-1)&&(!res.siblings[i].isZero())) {
|
||||
if ((i<res.siblings.length-1)&&(!F.isZero(res.siblings[i]))) {
|
||||
mixed = true;
|
||||
}
|
||||
if (mixed) {
|
||||
@@ -227,7 +215,7 @@ class SMT {
|
||||
}
|
||||
|
||||
if (addedOne) res.siblings.pop();
|
||||
while ((res.siblings.length>0) && (res.siblings[res.siblings.length-1].isZero())) {
|
||||
while ((res.siblings.length>0) && (F.isZero(res.siblings[res.siblings.length-1]))) {
|
||||
res.siblings.pop();
|
||||
}
|
||||
res.oldKey = resFind.notFoundKey;
|
||||
@@ -253,12 +241,12 @@ class SMT {
|
||||
if (typeof root === "undefined") root = this.root;
|
||||
|
||||
let res;
|
||||
if (root.isZero()) {
|
||||
if (F.isZero(root)) {
|
||||
res = {
|
||||
found: false,
|
||||
siblings: [],
|
||||
notFoundKey: key,
|
||||
notFoundValue: bigInt.zero,
|
||||
notFoundValue: F.zero,
|
||||
isOld0: true
|
||||
};
|
||||
return res;
|
||||
@@ -266,8 +254,8 @@ class SMT {
|
||||
|
||||
const record = await this.db.get(root);
|
||||
|
||||
if ((record.length==3)&&(record[0].equals(bigInt.one))) {
|
||||
if (record[1].equals(key)) {
|
||||
if ((record.length==3)&&(F.eq(record[0],F.one))) {
|
||||
if (F.eq(record[1],key)) {
|
||||
res = {
|
||||
found: true,
|
||||
siblings: [],
|
||||
|
||||
@@ -8,3 +8,5 @@ exports.hash0 = function (left, right) {
|
||||
exports.hash1 = function(key, value) {
|
||||
return mimc7.multiHash([key, value], bigInt.one);
|
||||
};
|
||||
|
||||
exports.F = mimc7.F;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
const Poseidon = require("./poseidon");
|
||||
const bigInt = require("big-integer");
|
||||
|
||||
const hash = Poseidon.createHash(6, 8, 57);
|
||||
|
||||
@@ -8,5 +7,7 @@ exports.hash0 = function (left, right) {
|
||||
};
|
||||
|
||||
exports.hash1 = function(key, value) {
|
||||
return hash([key, value, bigInt.one]);
|
||||
return hash([key, value, Poseidon.F.one]);
|
||||
};
|
||||
|
||||
exports.F = Poseidon.F;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
const bigInt = require("big-integer");
|
||||
|
||||
const F = require("./poseidon.js").F;
|
||||
const Scalar = require("ffjavascript").Scalar;
|
||||
|
||||
class SMTMemDb {
|
||||
constructor() {
|
||||
this.nodes = {};
|
||||
this.root = bigInt(0);
|
||||
this.root = F.zero;
|
||||
}
|
||||
|
||||
async getRoot() {
|
||||
@@ -12,13 +14,13 @@ class SMTMemDb {
|
||||
|
||||
_key2str(k) {
|
||||
// const keyS = bigInt(key).leInt2Buff(32).toString("hex");
|
||||
const keyS = bigInt(k).toString();
|
||||
const keyS = Scalar.e(k);
|
||||
return keyS;
|
||||
}
|
||||
|
||||
_normalize(n) {
|
||||
for (let i=0; i<n.length; i++) {
|
||||
n[i] = bigInt(n[i]);
|
||||
n[i] = F.e(n[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
87
src/utils.js
87
src/utils.js
@@ -1,87 +0,0 @@
|
||||
const bigInt = require("big-integer");
|
||||
|
||||
module.exports.leBuff2int = leBuff2int;
|
||||
module.exports.leInt2Buff = leInt2Buff;
|
||||
module.exports.beBuff2int = beBuff2int;
|
||||
module.exports.beInt2Buff = beInt2Buff;
|
||||
module.exports.stringifyBigInts = stringifyBigInts;
|
||||
module.exports.unstringifyBigInts = unstringifyBigInts;
|
||||
|
||||
function leBuff2int (buff) {
|
||||
let res = bigInt.zero;
|
||||
for (let i=0; i<buff.length; i++) {
|
||||
const n = bigInt(buff[i]);
|
||||
res = res.add(n.shiftLeft(i*8));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function leInt2Buff(n, len) {
|
||||
let r = n;
|
||||
let o =0;
|
||||
const buff = Buffer.alloc(len);
|
||||
while ((r.gt(bigInt.zero))&&(o<buff.length)) {
|
||||
let c = Number(r.and(bigInt(255)));
|
||||
buff[o] = c;
|
||||
o++;
|
||||
r = r.shiftRight(8);
|
||||
}
|
||||
if (r.gt(bigInt.zero)) throw new Error("Number does not feed in buffer");
|
||||
return buff;
|
||||
}
|
||||
|
||||
function beBuff2int (buff) {
|
||||
let res = bigInt.zero;
|
||||
for (let i=0; i<buff.length; i++) {
|
||||
const n = bigInt(buff[buff.length - i - 1]);
|
||||
res = res.add(n.shiftLeft(i*8));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function beInt2Buff(n, len) {
|
||||
let r = n;
|
||||
let o =len-1;
|
||||
const buff = Buffer.alloc(len);
|
||||
while ((r.greater(bigInt.zero))&&(o>=0)) {
|
||||
let c = Number(r.and(bigInt(255)));
|
||||
buff[o] = c;
|
||||
o--;
|
||||
r = r.shiftRight(8);
|
||||
}
|
||||
if (r.gt(bigInt.zero)) throw new Error("Number does not feed in buffer");
|
||||
return buff;
|
||||
}
|
||||
|
||||
|
||||
function stringifyBigInts(o) {
|
||||
if ((typeof(o) == "bigint") || o.isZero !== undefined) {
|
||||
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 unstringifyBigInts(o) {
|
||||
if ((typeof(o) == "string") && (/^[0-9]+$/.test(o) )) {
|
||||
return bigInt(o);
|
||||
} else if (Array.isArray(o)) {
|
||||
return o.map(unstringifyBigInts);
|
||||
} else if (typeof o == "object") {
|
||||
const res = {};
|
||||
for (let k in o) {
|
||||
res[k] = unstringifyBigInts(o[k]);
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user