Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
23616427cd | ||
|
|
7c743659db | ||
|
|
f04a318800 | ||
|
|
b15c7c8089 |
@@ -28,6 +28,22 @@ include "babyjub.circom";
|
|||||||
|
|
||||||
The result should be compensated.
|
The result should be compensated.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
The scalar is s = a0 + a1*2^3 + a2*2^6 + ...... + a81*2^243
|
||||||
|
First We calculate Q = B + 2^3*B + 2^6*B + ......... + 2^246*B
|
||||||
|
|
||||||
|
Then we calculate S1 = 2*2^246*B + (1 + a0)*B + (2^3 + a1)*B + .....+ (2^243 + a81)*B
|
||||||
|
|
||||||
|
And Finaly we compute the result: RES = SQ - Q
|
||||||
|
|
||||||
|
As you can see the input of the adders cannot be equal nor zero, except for the last
|
||||||
|
substraction that it's done in montgomery.
|
||||||
|
|
||||||
|
A good way to see it is that the accumulator input of the adder >= 2^247*B and the other input
|
||||||
|
is the output of the windows that it's going to be <= 2^246*B
|
||||||
|
*/
|
||||||
template WindowMulFix() {
|
template WindowMulFix() {
|
||||||
signal input in[3];
|
signal input in[3];
|
||||||
signal input base[2];
|
signal input base[2];
|
||||||
@@ -140,54 +156,60 @@ template SegmentMulFix(nWindows) {
|
|||||||
e2m.in[1] <== base[1];
|
e2m.in[1] <== base[1];
|
||||||
|
|
||||||
component windows[nWindows];
|
component windows[nWindows];
|
||||||
component adders[nWindows-1];
|
component adders[nWindows];
|
||||||
component cadders[nWindows-1];
|
component cadders[nWindows];
|
||||||
|
|
||||||
|
// In the last step we add an extra doubler so that numbers do not match.
|
||||||
|
component dblLast = MontgomeryDouble();
|
||||||
|
|
||||||
for (i=0; i<nWindows; i++) {
|
for (i=0; i<nWindows; i++) {
|
||||||
windows[i] = WindowMulFix();
|
windows[i] = WindowMulFix();
|
||||||
|
cadders[i] = MontgomeryAdd();
|
||||||
if (i==0) {
|
if (i==0) {
|
||||||
windows[i].base[0] <== e2m.out[0];
|
windows[i].base[0] <== e2m.out[0];
|
||||||
windows[i].base[1] <== e2m.out[1];
|
windows[i].base[1] <== e2m.out[1];
|
||||||
|
cadders[i].in1[0] <== e2m.out[0];
|
||||||
|
cadders[i].in1[1] <== e2m.out[1];
|
||||||
} else {
|
} else {
|
||||||
windows[i].base[0] <== windows[i-1].out8[0];
|
windows[i].base[0] <== windows[i-1].out8[0];
|
||||||
windows[i].base[1] <== windows[i-1].out8[1];
|
windows[i].base[1] <== windows[i-1].out8[1];
|
||||||
|
cadders[i].in1[0] <== cadders[i-1].out[0];
|
||||||
adders[i-1] = MontgomeryAdd();
|
cadders[i].in1[1] <== cadders[i-1].out[1];
|
||||||
cadders[i-1] = MontgomeryAdd();
|
}
|
||||||
if (i==1) {
|
if (i<nWindows-1) {
|
||||||
adders[i-1].in1[0] <== windows[0].out[0];
|
cadders[i].in2[0] <== windows[i].out8[0];
|
||||||
adders[i-1].in1[1] <== windows[0].out[1];
|
cadders[i].in2[1] <== windows[i].out8[1];
|
||||||
cadders[i-1].in1[0] <== e2m.out[0];
|
} else {
|
||||||
cadders[i-1].in1[1] <== e2m.out[1];
|
dblLast.in[0] <== windows[i].out8[0];
|
||||||
} else {
|
dblLast.in[1] <== windows[i].out8[1];
|
||||||
adders[i-1].in1[0] <== adders[i-2].out[0];
|
cadders[i].in2[0] <== dblLast.out[0];
|
||||||
adders[i-1].in1[1] <== adders[i-2].out[1];
|
cadders[i].in2[1] <== dblLast.out[1];
|
||||||
cadders[i-1].in1[0] <== cadders[i-2].out[0];
|
|
||||||
cadders[i-1].in1[1] <== cadders[i-2].out[1];
|
|
||||||
}
|
|
||||||
adders[i-1].in2[0] <== windows[i].out[0];
|
|
||||||
adders[i-1].in2[1] <== windows[i].out[1];
|
|
||||||
cadders[i-1].in2[0] <== windows[i-1].out8[0];
|
|
||||||
cadders[i-1].in2[1] <== windows[i-1].out8[1];
|
|
||||||
}
|
}
|
||||||
for (j=0; j<3; j++) {
|
for (j=0; j<3; j++) {
|
||||||
windows[i].in[j] <== e[3*i+j];
|
windows[i].in[j] <== e[3*i+j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i=0; i<nWindows; i++) {
|
||||||
|
adders[i] = MontgomeryAdd();
|
||||||
|
if (i==0) {
|
||||||
|
adders[i].in1[0] <== dblLast.out[0];
|
||||||
|
adders[i].in1[1] <== dblLast.out[1];
|
||||||
|
} else {
|
||||||
|
adders[i].in1[0] <== adders[i-1].out[0];
|
||||||
|
adders[i].in1[1] <== adders[i-1].out[1];
|
||||||
|
}
|
||||||
|
adders[i].in2[0] <== windows[i].out[0];
|
||||||
|
adders[i].in2[1] <== windows[i].out[1];
|
||||||
|
}
|
||||||
|
|
||||||
component m2e = Montgomery2Edwards();
|
component m2e = Montgomery2Edwards();
|
||||||
component cm2e = Montgomery2Edwards();
|
component cm2e = Montgomery2Edwards();
|
||||||
|
|
||||||
if (nWindows > 1) {
|
m2e.in[0] <== adders[nWindows-1].out[0];
|
||||||
m2e.in[0] <== adders[nWindows-2].out[0];
|
m2e.in[1] <== adders[nWindows-1].out[1];
|
||||||
m2e.in[1] <== adders[nWindows-2].out[1];
|
cm2e.in[0] <== cadders[nWindows-1].out[0];
|
||||||
cm2e.in[0] <== cadders[nWindows-2].out[0];
|
cm2e.in[1] <== cadders[nWindows-1].out[1];
|
||||||
cm2e.in[1] <== cadders[nWindows-2].out[1];
|
|
||||||
} else {
|
|
||||||
m2e.in[0] <== windows[0].out[0];
|
|
||||||
m2e.in[1] <== windows[0].out[1];
|
|
||||||
cm2e.in[0] <== e2m.out[0];
|
|
||||||
cm2e.in[1] <== e2m.out[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
component cAdd = BabyAdd();
|
component cAdd = BabyAdd();
|
||||||
cAdd.x1 <== m2e.out[0];
|
cAdd.x1 <== m2e.out[0];
|
||||||
@@ -195,7 +217,6 @@ template SegmentMulFix(nWindows) {
|
|||||||
cAdd.x2 <== -cm2e.out[0];
|
cAdd.x2 <== -cm2e.out[0];
|
||||||
cAdd.y2 <== cm2e.out[1];
|
cAdd.y2 <== cm2e.out[1];
|
||||||
|
|
||||||
|
|
||||||
cAdd.xout ==> out[0];
|
cAdd.xout ==> out[0];
|
||||||
cAdd.yout ==> out[1];
|
cAdd.yout ==> out[1];
|
||||||
|
|
||||||
@@ -214,7 +235,7 @@ template EscalarMulFix(n, BASE) {
|
|||||||
signal input e[n]; // Input in binary format
|
signal input e[n]; // Input in binary format
|
||||||
signal output out[2]; // Point (Twisted format)
|
signal output out[2]; // Point (Twisted format)
|
||||||
|
|
||||||
var nsegments = (n-1)\249 +1;
|
var nsegments = (n-1)\246 +1; // 249 probably would work. But I'm not sure and for security I keep 246
|
||||||
var nlastsegment = n - (nsegments-1)*249;
|
var nlastsegment = n - (nsegments-1)*249;
|
||||||
|
|
||||||
component segments[nsegments];
|
component segments[nsegments];
|
||||||
|
|||||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "circomlib",
|
"name": "circomlib",
|
||||||
"version": "0.0.10",
|
"version": "0.0.12",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "circomlib",
|
"name": "circomlib",
|
||||||
"version": "0.0.10",
|
"version": "0.0.12",
|
||||||
"description": "Basic circuits library for Circom",
|
"description": "Basic circuits library for Circom",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
|
|||||||
@@ -50,6 +50,51 @@ describe("Escalarmul test", function () {
|
|||||||
assert(yout.equals(babyjub.Base8[1]));
|
assert(yout.equals(babyjub.Base8[1]));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Should generate scalar mul of a specific constant", async () => {
|
||||||
|
|
||||||
|
const s = bigInt("2351960337287830298912035165133676222414898052661454064215017316447594616519");
|
||||||
|
const base8 = [
|
||||||
|
bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
|
||||||
|
bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475")
|
||||||
|
];
|
||||||
|
|
||||||
|
const w = circuit.calculateWitness({"e": s});
|
||||||
|
|
||||||
|
assert(circuit.checkWitness(w));
|
||||||
|
|
||||||
|
const xout = w[circuit.getSignalIdx("main.out[0]")];
|
||||||
|
const yout = w[circuit.getSignalIdx("main.out[1]")];
|
||||||
|
|
||||||
|
const expectedRes = babyjub.mulPointEscalar(base8, s);
|
||||||
|
|
||||||
|
assert(xout.equals(expectedRes[0]));
|
||||||
|
assert(yout.equals(expectedRes[1]));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should generate scalar mul of the firsts 50 elements", async () => {
|
||||||
|
|
||||||
|
const base8 = [
|
||||||
|
bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
|
||||||
|
bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475")
|
||||||
|
];
|
||||||
|
|
||||||
|
for (let i=0; i<50; i++) {
|
||||||
|
const s = bigInt(i);
|
||||||
|
|
||||||
|
const w = circuit.calculateWitness({"e": s});
|
||||||
|
|
||||||
|
assert(circuit.checkWitness(w));
|
||||||
|
|
||||||
|
const xout = w[circuit.getSignalIdx("main.out[0]")];
|
||||||
|
const yout = w[circuit.getSignalIdx("main.out[1]")];
|
||||||
|
|
||||||
|
const expectedRes = babyjub.mulPointEscalar(base8, s);
|
||||||
|
|
||||||
|
assert(xout.equals(expectedRes[0]));
|
||||||
|
assert(yout.equals(expectedRes[1]));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it("If multiply by order should return 0", async () => {
|
it("If multiply by order should return 0", async () => {
|
||||||
|
|
||||||
const w = circuit.calculateWitness({"e": babyjub.subOrder });
|
const w = circuit.calculateWitness({"e": babyjub.subOrder });
|
||||||
|
|||||||
Reference in New Issue
Block a user