Compare commits

..

8 Commits

Author SHA1 Message Date
Jordi Baylina
3c2b566e68 0.0.20 2019-12-04 21:57:32 +01:00
Jordi Baylina
15eadfe50c Merge branch 'master' of github.com:iden3/circomlib 2019-12-04 21:57:08 +01:00
Jordi Baylina
a1d4d1dca7 Convert constant components to functions 2019-12-04 21:57:02 +01:00
Jordi Baylina
d6e6a3b3f4 Fix assigning to signal 2019-12-03 19:16:19 +01:00
arnau
e3eb834322 Merge pull request #23 from kobigurk/fix/mimcsponge_round_constants
MiMCSponge: makes first and last round constants always zero
2019-10-12 14:03:37 +02:00
Kobi Gurkan
01a5530213 MiMCSponge: makes first and last round constants always zero 2019-10-04 17:39:53 +03:00
Jordi Baylina
50a725c174 0.0.19 2019-10-02 09:35:06 +02:00
Jordi Baylina
c4ce4cd946 multiget 2019-10-02 09:34:49 +02:00
21 changed files with 235 additions and 66 deletions

View File

@@ -1,4 +1,4 @@
/*
/*
Copyright 2018 0KIMS association.
This file is part of circom (Zero Knowledge Circuit Compiler).
@@ -71,7 +71,7 @@ template EscalarMulWindow(base, k) {
signal input sel[4];
signal output out[2];
component table;
var table;
component mux;
component adder;
@@ -86,8 +86,8 @@ template EscalarMulWindow(base, k) {
}
for (i=0; i<16; i++) {
table.out[i][0] ==> mux.c[0][i];
table.out[i][1] ==> mux.c[1][i];
mux.c[0][i] <== table[i][0];
mux.c[1][i] <== table[i][1];
}
in[0] ==> adder.x1;

View File

@@ -27,8 +27,8 @@ function pointAdd(x1,y1,x2,y2) {
return res;
}
template EscalarMulW4Table(base, k) {
signal output out[16][2];
function EscalarMulW4Table(base, k) {
var out[16][2];
var i;
var p[2];
@@ -39,11 +39,13 @@ template EscalarMulW4Table(base, k) {
dbl = pointAdd(dbl[0], dbl[1], dbl[0], dbl[1]);
}
out[0][0] <== 0;
out[0][1] <== 1;
out[0][0] = 0;
out[0][1] = 1;
for (i=1; i<16; i++) {
p = pointAdd(out[i-1][0], out[i-1][1], dbl[0], dbl[1]);
out[i][0] <== p[0];
out[i][1] <== p[1];
out[i][0] = p[0];
out[i][1] = p[1];
}
return out;
}

View File

@@ -39,8 +39,8 @@ template MiMCFeistel(nrounds) {
signal output xL_out;
signal output xR_out;
var c = [
0,
// doesn't contain the first and last round constants, which are always zero
var c_partial = [
7120861356467848435263064379192047478074060781135320967663101236819528304084,
5024705281721889198577876690145313457398658950011302225525409148828000436681,
17980351014018068290387269214713820287804403312720763401943303895585469787384,
@@ -258,8 +258,7 @@ template MiMCFeistel(nrounds) {
18224457394066545825553407391290108485121649197258948320896164404518684305122,
274945154732293792784580363548970818611304339008964723447672490026510689427,
11050822248291117548220126630860474473945266276626263036056336623671308219529,
2119542016932434047340813757208803962484943912710204325088879681995922344971,
0
2119542016932434047340813757208803962484943912710204325088879681995922344971
];
var t;
@@ -268,13 +267,19 @@ template MiMCFeistel(nrounds) {
signal xL[nrounds-1];
signal xR[nrounds-1];
var c;
for (var i=0; i<nrounds; i++) {
t = (i==0) ? k+xL_in : k + xL[i-1] + c[i];
if ((i == 0) || (i == nrounds - 1)) {
c = 0;
} else {
c = c_partial[i - 1];
}
t = (i==0) ? k+xL_in : k + xL[i-1] + c;
t2[i] <== t*t;
t4[i] <== t2[i]*t2[i];
if (i<nrounds-1) {
xL[i] <== ((i==0) ? xR_in : xR[i-1]) + t4[i]*t;
xR[i] = (i==0) ? xL_in : xL[i-1];
xR[i] <== (i==0) ? xL_in : xL[i-1];
} else {
xR_out <== xR[i-1] + t4[i]*t;
xL_out <== xL[i-1];

26
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "circomlib",
"version": "0.0.18",
"version": "0.0.20",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -348,9 +348,9 @@
}
},
"big-integer": {
"version": "1.6.44",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.44.tgz",
"integrity": "sha512-7MzElZPTyJ2fNvBkPxtFQ2fWIkVmuzw41+BZHSzpEq3ymB2MfeKp1+yXl/tS75xCx+WnyV+yb0kp+K1C3UNwmQ=="
"version": "1.6.46",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.46.tgz",
"integrity": "sha512-Vj2TNtZ8Y0XaL6HCkzJiEqfykjtv/9wVCWIutMe+QVIXLPe2tCLEzULtYvcX9WRtmNIj3Jqi5tNjIsR0N4QOsg=="
},
"binary-extensions": {
"version": "1.13.1",
@@ -601,9 +601,9 @@
}
},
"circom": {
"version": "0.0.28",
"resolved": "https://registry.npmjs.org/circom/-/circom-0.0.28.tgz",
"integrity": "sha512-cYivdFVPUAVsGFgx3/W3BQe50fwiu+w8Mq9rWA/UYLWwjAgY0Ctk+obpxGL5v9ZHJpO6pvmczLnOXmV/KqiB5g==",
"version": "0.0.34",
"resolved": "https://registry.npmjs.org/circom/-/circom-0.0.34.tgz",
"integrity": "sha512-R7yNW8PtX2xREtLYWZ/o5cfKHT/qa+CveXsGVAX1ej7mPrTat9mlEMXEy2vX//IuP9/cnYTY/KxJ2SN05PUeGA==",
"dev": true,
"requires": {
"big-integer": "^1.6.32",
@@ -3929,9 +3929,9 @@
"integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg=="
},
"p-limit": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
"integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz",
"integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==",
"requires": {
"p-try": "^2.0.0"
}
@@ -4703,9 +4703,9 @@
}
},
"snarkjs": {
"version": "0.1.18",
"resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.1.18.tgz",
"integrity": "sha512-JWZMBvPPIL424+QCY0PtreIiHTRoX4h4qYvKv3nqKPVZl0T7sw3B/ZeizrCVRz7Jr9vrwZxmzJ0XIg6D1yC8Mg==",
"version": "0.1.20",
"resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.1.20.tgz",
"integrity": "sha512-tYmWiVm1sZiB44aIh5w/3HUaTntTUC4fv+CWs4rR0gfkt2KbHTpArOqZW++/Lxujrn9IypXVhdKVUr/eE6Hxfg==",
"requires": {
"big-integer": "^1.6.43",
"chai": "^4.2.0",

View File

@@ -1,6 +1,6 @@
{
"name": "circomlib",
"version": "0.0.18",
"version": "0.0.20",
"description": "Basic circuits library for Circom",
"main": "index.js",
"directories": {
@@ -31,7 +31,7 @@
"web3": "^1.0.0-beta.55"
},
"devDependencies": {
"circom": "0.0.32",
"circom": "0.0.35",
"eslint-plugin-mocha": "^5.2.0",
"ganache-cli": "^6.4.4",
"mocha": "^5.2.0"

View File

@@ -27,6 +27,14 @@ class SMTMemDb {
return this.nodes[keyS];
}
async multiGet(keys) {
const promises = [];
for (let i=0; i<keys.length; i++) {
promises.push(this.get(keys[i]));
}
return await Promise.all(promises);
}
async setRoot(rt) {
this.root = rt;
}

View File

@@ -56,7 +56,7 @@ describe("Aliascheck test", () => {
circuit.calculateWitness({in: inp});
assert(false);
} catch(err) {
assert.equal(err.message, "Constraint doesn't match: 1 != 0");
assert(/Constraint\sdoesn't\smatch(.*)1\s!=\s0/.test(err.message) );
}
});
@@ -67,7 +67,7 @@ describe("Aliascheck test", () => {
circuit.calculateWitness({in: inp});
assert(false);
} catch(err) {
assert.equal(err.message, "Constraint doesn't match: 1 != 0");
assert(/Constraint\sdoesn't\smatch(.*)1\s!=\s0/.test(err.message) );
}
});

View File

@@ -100,11 +100,11 @@ describe("Baby Jub test", function () {
circuitTest.calculateWitness({x: 1, y: 0});
assert(false, "Should be a valid point");
} catch(err) {
assert.equal(err.message, "Constraint doesn't match: 168700 != 1");
assert(/Constraint\sdoesn't\smatch(.*)168700\s!=\s1/.test(err.message) );
}
});
it("Should extract the public key from the private one", async () => {
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));

View File

@@ -23,7 +23,7 @@ describe("Sum test", () => {
it("Should create a sum circuit", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "sum_test.circom"));
assert.equal(cirDef.nVars, 101);
assert.equal(cirDef.nVars, 97); // 32 (in1) + 32(in2) + 32(out) + 1 (carry)
const circuit = new snarkjs.Circuit(cirDef);

View File

@@ -8,7 +8,7 @@ template Main() {
var i;
var base = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203]
16950150798460657717958625567821834550301663161624707787222815936182638968203];
component escalarMul = EscalarMul(256, base);

View File

@@ -7,7 +7,7 @@ template Main() {
signal output out[2];
var base = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203]
16950150798460657717958625567821834550301663161624707787222815936182638968203];
component n2b = Num2Bits(253);

View File

@@ -8,7 +8,7 @@ template Main() {
var i;
var base = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203]
16950150798460657717958625567821834550301663161624707787222815936182638968203];
component escalarMul = EscalarMul(256, base);

View File

@@ -7,10 +7,10 @@ template Main() {
var base = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203];
component escalarMul = EscalarMulW4Table(base, 0);
var escalarMul = EscalarMulW4Table(base, 0);
for (var i=0; i<16; i++) {
out[i][0] <== escalarMul.out[i][0]*in;
out[i][1] <== escalarMul.out[i][1]*in;
out[i][0] <== escalarMul[i][0]*in;
out[i][1] <== escalarMul[i][1]*in;
}
}

View File

@@ -7,10 +7,10 @@ template Main() {
var base = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203];
component escalarMul = EscalarMulW4Table(base, 3);
var escalarMul = EscalarMulW4Table(base, 3);
for (var i=0; i<16; i++) {
out[i][0] <== escalarMul.out[i][0]*in;
out[i][1] <== escalarMul.out[i][1]*in;
out[i][0] <== escalarMul[i][0]*in;
out[i][1] <== escalarMul[i][1]*in;
}
}

View File

@@ -67,7 +67,7 @@ describe("EdDSA MiMC test", function () {
M: msg});
assert(false);
} catch(err) {
assert.equal(err.message, "Constraint doesn't match: 1 != 0");
assert(/Constraint\sdoesn't\smatch(.*)1\s!=\s0/.test(err.message) );
}
});

View File

@@ -67,7 +67,7 @@ describe("EdDSA Poseidon test", function () {
M: msg});
assert(false);
} catch(err) {
assert.equal(err.message, "Constraint doesn't match: 1 != 0");
assert(/Constraint\sdoesn't\smatch(.*)1\s!=\s0/.test(err.message) );
}
});

View File

@@ -38,6 +38,8 @@ describe("Exponentioation test", () => {
const w = circuit.calculateWitness({in: 1});
assert(circuit.checkWitness(w));
let g = [bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")]
@@ -46,12 +48,12 @@ describe("Exponentioation test", () => {
for (let i=0; i<16; i++) {
const xout1 = w[circuit.getSignalIdx(`main.out[${i}][0]`)];
const yout1 = w[circuit.getSignalIdx(`main.out[${i}][1]`)];
/*
console.log(xout1.toString());
console.log(yout1.toString());
console.log(dbl[0]);
console.log(dbl[1]);
*/
// console.log(xout1.toString());
// console.log(yout1.toString());
// console.log(dbl[0]);
// console.log(dbl[1]);
assert(xout1.equals(dbl[0]));
assert(yout1.equals(dbl[1]));
@@ -74,6 +76,8 @@ describe("Exponentioation test", () => {
const w = circuit.calculateWitness({in: 1});
assert(circuit.checkWitness(w));
let g = [snarkjs.bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
snarkjs.bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")]
@@ -87,12 +91,12 @@ describe("Exponentioation test", () => {
const xout1 = w[circuit.getSignalIdx(`main.out[${i}][0]`)];
const yout1 = w[circuit.getSignalIdx(`main.out[${i}][1]`)];
/*
console.log(xout1.toString());
console.log(yout1.toString());
console.log(dbl[0]);
console.log(dbl[1]);
*/
// console.log(xout1.toString());
// console.log(yout1.toString());
// console.log(dbl[0]);
// console.log(dbl[1]);
assert(xout1.equals(dbl[0]));
assert(yout1.equals(dbl[1]));
@@ -102,7 +106,7 @@ describe("Exponentioation test", () => {
});
it("Should exponentiate g^31", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "escalarmul_test.circom"));
const cirDef = await compiler(path.join(__dirname, "circuits", "escalarmul_test.circom"), {reduceConstraints: true});
// console.log(JSON.stringify(cirDef, null, 1));
@@ -146,12 +150,12 @@ describe("Exponentioation test", () => {
c = addPoint(c,c);
}
c = addPoint(c,g);
/*
console.log(xout2.toString());
console.log(yout2.toString());
console.log(c[0].toString());
console.log(c[1].toString());
*/
// console.log(xout2.toString());
// console.log(yout2.toString());
// console.log(c[0].toString());
// console.log(c[1].toString());
assert(xout2.equals(c[0]));
assert(yout2.equals(c[1]));

View File

@@ -43,6 +43,8 @@ describe("Mux4 test", () => {
for (let i=0; i<16; i++) {
const w = circuit.calculateWitness({ "selector": i });
assert(circuit.checkWitness(w));
assert(w[0].equals(bigInt(1)));
// console.log(i + " -> " + w[circuit.getSignalIdx("main.out")].toString());
@@ -96,6 +98,8 @@ describe("Mux4 test", () => {
for (let i=0; i<4; i++) {
const w = circuit.calculateWitness({ "selector": i });
assert(circuit.checkWitness(w));
assert(w[0].equals(bigInt(1)));
// console.log(i + " -> " + w[circuit.getSignalIdx("main.out")].toString());
@@ -118,6 +122,8 @@ describe("Mux4 test", () => {
for (let i=0; i<2; i++) {
const w = circuit.calculateWitness({ "selector": i });
assert(circuit.checkWitness(w));
assert(w[0].equals(bigInt(1)));
// console.log(i + " -> " + w[circuit.getSignalIdx("main.out")].toString());

23
test/rawsmt3.circom Normal file
View File

@@ -0,0 +1,23 @@
include "../circuits/smt/smtverifier.circom";
template SMT(nLevels) {
signal input root;
signal input mtp[nLevels];
signal input hi;
signal input hv;
component smtClaimExists = SMTVerifier(nLevels);
smtClaimExists.enabled <== 1;
smtClaimExists.fnc <== 0;
smtClaimExists.root <== root;
for (var i=0; i<nLevels; i++) {
smtClaimExists.siblings[i] <== mtp[i];
}
smtClaimExists.oldKey <== 0;
smtClaimExists.oldValue <== 0;
smtClaimExists.isOld0 <== 0;
smtClaimExists.key <== hi;
smtClaimExists.value <== hv;
}
component main = SMT(4);

View File

@@ -111,5 +111,28 @@ describe("SMT test", function () {
assert(circuit.checkWitness(w));
});
it("Check inclussion Adria case", async () => {
const e1_hi= bigInt("17124152697573569611556136390143205198134245887034837071647643529178599000839");
const e1_hv= bigInt("19650379996168153643111744440707177573540245771926102415571667548153444658179");
const e2ok_hi= bigInt("16498254692537945203721083102154618658340563351558973077349594629411025251262");
const e2ok_hv= bigInt("19650379996168153643111744440707177573540245771926102415571667548153444658179");
const e2fail_hi= bigInt("17195092312975762537892237130737365903429674363577646686847513978084990105579");
const e2fail_hv= bigInt("19650379996168153643111744440707177573540245771926102415571667548153444658179");
const tree1 = await smt.newMemEmptyTrie();
await tree1.insert(e1_hi,e1_hv);
await tree1.insert(e2ok_hi,e2ok_hv);
await testInclusion(tree1, e2ok_hi, circuit);
const tree2 = await smt.newMemEmptyTrie();
await tree2.insert(e1_hi,e1_hv);
await tree2.insert(e2fail_hi,e2fail_hv);
await testInclusion(tree2, e2fail_hi, circuit);
});
});

98
test/smtverifier_adria.js Normal file
View File

@@ -0,0 +1,98 @@
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const fs = require("fs")
const bigInt = snarkjs.bigInt;
const smt = require("../src/smt.js");
const circuitSource = `
include "../circuits/smt/smtverifier.circom";
template SMT(nLevels) {
signal input root;
signal input mtp[nLevels];
signal input hi;
signal input hv;
component smtClaimExists = SMTVerifier(nLevels);
smtClaimExists.enabled <== 1;
smtClaimExists.fnc <== 0;
smtClaimExists.root <== root;
for (var i=0; i<nLevels; i++) {
smtClaimExists.siblings[i] <== mtp[i];
}
smtClaimExists.oldKey <== 0;
smtClaimExists.oldValue <== 0;
smtClaimExists.isOld0 <== 0;
smtClaimExists.key <== hi;
smtClaimExists.value <== hv;
}
component main = SMT(4);
`;
describe("smt3test", function () {
this.timeout(200000);
let circuitFileName;
before( async () => {
circuitFileName = path.join(__dirname, ".", "rawsmt3.circom");
fs.writeFileSync(circuitFileName,circuitSource);
});
const levels = 4;
async function testsmt3(e1, e2) {
let tree = await smt.newMemEmptyTrie();
// insert e1, e2
await tree.insert(e1.hi, e1.hv);
await tree.insert(e2.hi, e2.hv);
// generate proof for e1
const findInfo = await tree.find(e1.hi);
const siblings = findInfo.siblings;
while (siblings.length < levels) siblings.push(bigInt(0));
const input = {
root: tree.root,
mtp: siblings,
hi: e1.hi,
hv: e1.hv,
};
const compiledCircuit = await compiler(
circuitFileName,
{ reduceConstraints: false }
);
const circuit = new snarkjs.Circuit(compiledCircuit);
const witness = circuit.calculateWitness(input);
circuit.checkWitness(witness);
}
it("TestSmts", async () => {
const e1 = {
hi: bigInt("17124152697573569611556136390143205198134245887034837071647643529178599000839"),
hv: bigInt("19650379996168153643111744440707177573540245771926102415571667548153444658179"),
};
const e2ok = {
hi: bigInt("16498254692537945203721083102154618658340563351558973077349594629411025251262"),
hv: bigInt("19650379996168153643111744440707177573540245771926102415571667548153444658179"),
};
const e2fail = {
hi: bigInt("17195092312975762537892237130737365903429674363577646686847513978084990105579"),
hv: bigInt("19650379996168153643111744440707177573540245771926102415571667548153444658179"),
};
console.log("test e1, e2ok");
await testsmt3(e1, e2ok);
console.log("test e1, e2fail");
await testsmt3(e1, e2fail);
});
});