@ -0,0 +1,122 @@ |
|||||
|
/* |
||||
|
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 "compconstant.circom"; |
||||
|
include "pointbits.circom"; |
||||
|
include "mimc.circom"; |
||||
|
include "bitify.circom"; |
||||
|
include "escalarmulany.circom"; |
||||
|
include "escalarmulfix.circom"; |
||||
|
|
||||
|
template EdDSAMiMCVerifier() { |
||||
|
signal input enabled; |
||||
|
signal input Ax; |
||||
|
signal input Ay; |
||||
|
|
||||
|
signal input S; |
||||
|
signal input R8x; |
||||
|
signal input R8y; |
||||
|
|
||||
|
signal input M; |
||||
|
|
||||
|
var i; |
||||
|
|
||||
|
// Ensure S<Subgroup Order |
||||
|
|
||||
|
component snum2bits = Num2Bits(253); |
||||
|
snum2bits.in <== S; |
||||
|
|
||||
|
component compConstant = CompConstant(2736030358979909402780800718157159386076813972158567259200215660948447373040); |
||||
|
|
||||
|
for (i=0; i<253; i++) { |
||||
|
snum2bits.out[i] ==> compConstant.in[i]; |
||||
|
} |
||||
|
compConstant.in[253] <== 0; |
||||
|
compConstant.out === 0; |
||||
|
|
||||
|
// Calculate the h = H(R,A, msg) |
||||
|
|
||||
|
component hash = MultiMiMC7(5, 91); |
||||
|
hash.in[0] <== R8x; |
||||
|
hash.in[1] <== R8y; |
||||
|
hash.in[2] <== Ax; |
||||
|
hash.in[3] <== Ay; |
||||
|
hash.in[4] <== M; |
||||
|
|
||||
|
component h2bits = Num2Bits_strict(); |
||||
|
h2bits.in <== hash.out; |
||||
|
|
||||
|
// Calculate second part of the right side: right2 = h*8*A |
||||
|
|
||||
|
// Multiply by 8 by adding it 3 times. This also ensure that the result is in |
||||
|
// the subgroup. |
||||
|
component dbl1 = BabyDbl(); |
||||
|
dbl1.x <== Ax; |
||||
|
dbl1.y <== Ay; |
||||
|
component dbl2 = BabyDbl(); |
||||
|
dbl2.x <== dbl1.xout; |
||||
|
dbl2.y <== dbl1.yout; |
||||
|
component dbl3 = BabyDbl(); |
||||
|
dbl3.x <== dbl2.xout; |
||||
|
dbl3.y <== dbl2.yout; |
||||
|
|
||||
|
// We check that A is not zero. |
||||
|
component isZero = IsZero(); |
||||
|
isZero.in <== dbl3.x; |
||||
|
isZero.out === 0; |
||||
|
|
||||
|
component mulAny = EscalarMulAny(254); |
||||
|
for (i=0; i<254; i++) { |
||||
|
mulAny.e[i] <== h2bits.out[i]; |
||||
|
} |
||||
|
mulAny.p[0] <== dbl3.xout; |
||||
|
mulAny.p[1] <== dbl3.yout; |
||||
|
|
||||
|
|
||||
|
// Compute the right side: right = R8 + right2 |
||||
|
|
||||
|
component addRight = BabyAdd(); |
||||
|
addRight.x1 <== R8x; |
||||
|
addRight.y1 <== R8y; |
||||
|
addRight.x2 <== mulAny.out[0]; |
||||
|
addRight.y2 <== mulAny.out[1]; |
||||
|
|
||||
|
// Calculate left side of equation left = S*B8 |
||||
|
|
||||
|
var BASE8 = [ |
||||
|
17777552123799933955779906779655732241715742912184938656739573121738514868268, |
||||
|
2626589144620713026669568689430873010625803728049924121243784502389097019475 |
||||
|
]; |
||||
|
component mulFix = EscalarMulFix(253, BASE8); |
||||
|
for (i=0; i<253; i++) { |
||||
|
mulFix.e[i] <== snum2bits.out[i]; |
||||
|
} |
||||
|
|
||||
|
// Do the comparation left == right if enabled; |
||||
|
|
||||
|
component eqCheckX = ForceEqualIfEnabled(); |
||||
|
eqCheckX.enabled <== enabled; |
||||
|
eqCheckX.in[0] <== mulFix.out[0]; |
||||
|
eqCheckX.in[1] <== addRight.xout; |
||||
|
|
||||
|
component eqCheckY = ForceEqualIfEnabled(); |
||||
|
eqCheckY.enabled <== enabled; |
||||
|
eqCheckY.in[0] <== mulFix.out[1]; |
||||
|
eqCheckY.in[1] <== addRight.yout; |
||||
|
} |
@ -0,0 +1,3 @@ |
|||||
|
exports.smt = require("./src/smt"); |
||||
|
exports.eddsa = require("./src/eddsa"); |
||||
|
exports.mimc7 = require("./src/mimc7"); |
@ -1,43 +0,0 @@ |
|||||
/* |
|
||||
fnc[0] fn[1] Function S1 S2 S3 S4 |
|
||||
0 0 NOP 0 0 0 0 |
|
||||
0 1 TRANSFER 0 1 0 1 |
|
||||
1 0 ENTRY 0 1 0 1 |
|
||||
1 1 EXIT 1 0 1 1 |
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
template rollupTx(nLevels) { |
|
||||
signal input fromIdx; // 24 |
|
||||
signal input toIdx; // 24 |
|
||||
signal input fpTxAmount; // 24 |
|
||||
|
|
||||
signal input fnc[2]; // 2 |
|
||||
|
|
||||
signal oldRoot; |
|
||||
signal newRoot; |
|
||||
|
|
||||
signal input sigR8; |
|
||||
signal input sigS; |
|
||||
|
|
||||
// State 1 |
|
||||
signal input Ax1; |
|
||||
signal input Ay1; |
|
||||
signal input St1; |
|
||||
signal input siblings1[nlevels]; |
|
||||
|
|
||||
// Required for inserts and delete |
|
||||
signal input isOld0_1; // 1 |
|
||||
signal input oldKey; |
|
||||
signal input oldValue; |
|
||||
|
|
||||
// State 2 |
|
||||
signal input Ax2; |
|
||||
signal input Ay2; |
|
||||
signal input St2; |
|
||||
signal input siblings2[nlevels]; |
|
||||
signal input isOld0_1; // 1 |
|
||||
signal input oldKey; |
|
||||
signal input oldValue; |
|
||||
|
|
||||
} |
|
@ -0,0 +1,3 @@ |
|||||
|
include "../../circuits/eddsamimc.circom"; |
||||
|
|
||||
|
component main = EdDSAMiMCVerifier(); |
@ -0,0 +1,98 @@ |
|||||
|
const chai = require("chai"); |
||||
|
const path = require("path"); |
||||
|
const snarkjs = require("snarkjs"); |
||||
|
const compiler = require("circom"); |
||||
|
|
||||
|
const eddsa = require("../src/eddsa.js"); |
||||
|
|
||||
|
const assert = chai.assert; |
||||
|
|
||||
|
const bigInt = snarkjs.bigInt; |
||||
|
|
||||
|
describe("EdDSA test", function () { |
||||
|
let circuit; |
||||
|
|
||||
|
this.timeout(100000); |
||||
|
|
||||
|
before( async () => { |
||||
|
const cirDef = await compiler(path.join(__dirname, "circuits", "eddsamimc_test.circom")); |
||||
|
|
||||
|
circuit = new snarkjs.Circuit(cirDef); |
||||
|
|
||||
|
console.log("NConstrains EdDSA: " + circuit.nConstraints); |
||||
|
}); |
||||
|
|
||||
|
it("Sign a single number", async () => { |
||||
|
const msg = bigInt(1234); |
||||
|
|
||||
|
const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex"); |
||||
|
|
||||
|
const pubKey = eddsa.prv2pub(prvKey); |
||||
|
|
||||
|
const signature = eddsa.signMiMC(prvKey, msg); |
||||
|
|
||||
|
assert(eddsa.verifyMiMC(msg, signature, pubKey)); |
||||
|
|
||||
|
const w = circuit.calculateWitness({ |
||||
|
enabled: 1, |
||||
|
Ax: pubKey[0], |
||||
|
Ay: pubKey[1], |
||||
|
R8x: signature.R8[0], |
||||
|
R8y: signature.R8[1], |
||||
|
S: signature.S, |
||||
|
M: msg}); |
||||
|
|
||||
|
assert(circuit.checkWitness(w)); |
||||
|
}); |
||||
|
|
||||
|
it("Detect Invalid signature", async () => { |
||||
|
const msg = bigInt(1234); |
||||
|
|
||||
|
const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex"); |
||||
|
|
||||
|
const pubKey = eddsa.prv2pub(prvKey); |
||||
|
|
||||
|
|
||||
|
const signature = eddsa.signMiMC(prvKey, msg); |
||||
|
|
||||
|
assert(eddsa.verifyMiMC(msg, signature, pubKey)); |
||||
|
try { |
||||
|
const w = circuit.calculateWitness({ |
||||
|
enabled: 1, |
||||
|
Ax: pubKey[0], |
||||
|
Ay: pubKey[1], |
||||
|
R8x: signature.R8[0].add(bigInt(1)), |
||||
|
R8y: signature.R8[1], |
||||
|
S: signature.S, |
||||
|
M: msg}); |
||||
|
assert(false); |
||||
|
} catch(err) { |
||||
|
assert.equal(err.message, "Constraint doesn't match: 1 != 0"); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
it("Test a dissabled circuit with a bad signature", async () => { |
||||
|
const msg = bigInt(1234); |
||||
|
|
||||
|
const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex"); |
||||
|
|
||||
|
const pubKey = eddsa.prv2pub(prvKey); |
||||
|
|
||||
|
|
||||
|
const signature = eddsa.signMiMC(prvKey, msg); |
||||
|
|
||||
|
assert(eddsa.verifyMiMC(msg, signature, pubKey)); |
||||
|
|
||||
|
const w = circuit.calculateWitness({ |
||||
|
enabled: 0, |
||||
|
Ax: pubKey[0], |
||||
|
Ay: pubKey[1], |
||||
|
R8x: signature.R8[0].add(bigInt(1)), |
||||
|
R8y: signature.R8[1], |
||||
|
S: signature.S, |
||||
|
M: msg}); |
||||
|
|
||||
|
assert(circuit.checkWitness(w)); |
||||
|
}); |
||||
|
}); |