/*
|
|
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/>.
|
|
*/
|
|
|
|
/*
|
|
|
|
┏━━━━━━━━━━━┓
|
|
┃ ┃
|
|
┃ ┃
|
|
(inx, iny) ══════════════════════════════════════════▶┃ EC Point ┃
|
|
┃ ╠═▶ (outx, outy)
|
|
╔══▶┃ Adder ┃
|
|
║ ┃ ┃
|
|
║ ┃ ┃
|
|
║ ┃ ┃
|
|
┏━━━━━━━━━━━┓ ┏━━━━━━━━━━━━┓ ║ ┗━━━━━━━━━━━┛
|
|
┃ ┃ ┃ ┃ ║
|
|
┃ ┃ ┃ ┃ ║
|
|
┃ ╠═══(p0x,p0y)═══▶┃ ┃ ║
|
|
┃ ╠═══(p1x,p1y)═══▶┃ ┃ ║
|
|
┃ ╠═══(p2x,p2y)═══▶┃ ┃ ║
|
|
┃ ╠═══(p3x,p3y)═══▶┃ ┃ ║
|
|
┃ ╠═══(p4x,p4y)═══▶┃ ┃ ║
|
|
┃ ╠═══(p5x,p5y)═══▶┃ ┃ ║
|
|
┃ ╠═══(p6x,p6y)═══▶┃ ┃ ║
|
|
┃ Constant ╠═══(p7x,p7y)═══▶┃ ┃ ║
|
|
┃ Points ┃ ┃ Mux4 ╠══╝
|
|
┃ ╠═══(p8x,p8y)═══▶┃ ┃
|
|
┃ ╠═══(p9x,p9y)═══▶┃ ┃
|
|
┃ ╠══(p10x,p10y)══▶┃ ┃
|
|
┃ ╠══(p11x,p11y)══▶┃ ┃
|
|
┃ ╠══(p12x,p12y)══▶┃ ┃
|
|
┃ ╠══(p13x,p13y)══▶┃ ┃
|
|
┃ ╠══(p14x,p14y)══▶┃ ┃
|
|
┃ ╠══(p15x,p15y)══▶┃ ┃
|
|
┃ ┃ ┃ ┃
|
|
┃ ┃ ┃ ┃
|
|
┗━━━━━━━━━━━┛ ┗━━━━━━━━━━━━┛
|
|
▲ ▲ ▲ ▲
|
|
│ │ │ │
|
|
s0 ─────────────────────────────────┘ │ │ │
|
|
s1 ────────────────────────────────────┘ │ │
|
|
s2 ───────────────────────────────────────┘ │
|
|
s3 ──────────────────────────────────────────┘
|
|
|
|
|
|
*/
|
|
|
|
include "mux4.circom";
|
|
include "escalarmulw4table.circom";
|
|
include "babyjub.circom";
|
|
|
|
template EscalarMulWindow(base, k) {
|
|
|
|
signal input in[2];
|
|
signal input sel[4];
|
|
signal output out[2];
|
|
|
|
var table;
|
|
component mux;
|
|
component adder;
|
|
|
|
var i;
|
|
|
|
table = EscalarMulW4Table(base, k);
|
|
mux = MultiMux4(2);
|
|
adder = BabyAdd();
|
|
|
|
for (i=0; i<4; i++) {
|
|
sel[i] ==> mux.s[i];
|
|
}
|
|
|
|
for (i=0; i<16; i++) {
|
|
mux.c[0][i] <== table[i][0];
|
|
mux.c[1][i] <== table[i][1];
|
|
}
|
|
|
|
in[0] ==> adder.x1;
|
|
in[1] ==> adder.y1;
|
|
|
|
mux.out[0] ==> adder.x2;
|
|
mux.out[1] ==> adder.y2;
|
|
|
|
adder.xout ==> out[0];
|
|
adder.yout ==> out[1];
|
|
}
|
|
|
|
/*
|
|
|
|
|
|
┏━━━━━━━━━┓ ┏━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━┓
|
|
┃ ┃ ┃ ┃ ┃ ┃
|
|
inp ════▶┃Window(0)┃═════▶┃Window(1)┃════════ . . . . ═════════▶┃ Window(nBlocks-1) ┃═════▶ out
|
|
┃ ┃ ┃ ┃ ┃ ┃
|
|
┗━━━━━━━━━┛ ┗━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━┛
|
|
▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲
|
|
in[0]─────────┘ │ │ │ │ │ │ │ │ │ │ │
|
|
in[1]───────────┘ │ │ │ │ │ │ │ │ │ │
|
|
in[2]─────────────┘ │ │ │ │ │ │ │ 0 0
|
|
in[3]───────────────┘ │ │ │ │ │ │
|
|
in[4]──────────────────────────┘ │ │ │ │ │
|
|
in[5]────────────────────────────┘ │ │ │ │
|
|
in[6]──────────────────────────────┘ │ │ │
|
|
in[7]────────────────────────────────┘ │ │
|
|
. │ │
|
|
. │ │
|
|
in[n-2]─────────────────────────────────────────────────────────────────────┘ │
|
|
in[n-1]───────────────────────────────────────────────────────────────────────┘
|
|
|
|
*/
|
|
|
|
template EscalarMul(n, base) {
|
|
signal input in[n];
|
|
signal input inp[2]; // Point input to be added
|
|
signal output out[2];
|
|
|
|
var nBlocks = ((n-1)>>2)+1;
|
|
var i;
|
|
var j;
|
|
|
|
component windows[nBlocks];
|
|
|
|
// Construct the windows
|
|
for (i=0; i<nBlocks; i++) {
|
|
windows[i] = EscalarMulWindow(base, i);
|
|
}
|
|
|
|
// Connect the selectors
|
|
for (i=0; i<nBlocks; i++) {
|
|
for (j=0; j<4; j++) {
|
|
if (i*4+j >= n) {
|
|
windows[i].sel[j] <== 0;
|
|
} else {
|
|
windows[i].sel[j] <== in[i*4+j];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Start with generator
|
|
windows[0].in[0] <== inp[0];
|
|
windows[0].in[1] <== inp[1];
|
|
|
|
for(i=0; i<nBlocks-1; i++) {
|
|
windows[i].out[0] ==> windows[i+1].in[0];
|
|
windows[i].out[1] ==> windows[i+1].in[1];
|
|
}
|
|
|
|
windows[nBlocks-1].out[0] ==> out[0];
|
|
windows[nBlocks-1].out[1] ==> out[1];
|
|
}
|