re-added zkrsa

This commit is contained in:
Youssef El Saadany
2023-07-22 14:35:37 +02:00
parent 77490b59b5
commit 29e259be6e
473 changed files with 72958 additions and 0 deletions

3
zkrsa/.gitattributes vendored Normal file
View File

@@ -0,0 +1,3 @@
*.vk_proof filter=lfs diff=lfs merge=lfs -text
*.vk_verifier filter=lfs diff=lfs merge=lfs -text
circom-rsa-verify/** linguist-vendored

14
zkrsa/.gitignore vendored Normal file
View File

@@ -0,0 +1,14 @@
node_modules
*example*
.DS_Store
circuit*.json
adhaar.pdf
scripts/extract.ts
*.pem
.vercel
bin
inputs
vkeys
witness
proofs
publicSignals

4
zkrsa/.husky/pre-commit Executable file
View File

@@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
cd frontend && yarn test && yarn pretty-quick --staged

48
zkrsa/README.md Normal file
View File

@@ -0,0 +1,48 @@
### zkRSA
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
This repository's goal is to perform zero knowledge (zk) proofs generation and verification of RSA signatures. All from within a web browser, with local computing resources.
The `circom-rsa-verify` folder contains all necessary circuits and tests for generating zk proofs of valid RSA signatures. It has been cloned from [here](https://github.com/zkp-application/circom-rsa-verify). You should check it out!
The `frontend` folder contains the UI for generating or verifying proofs of valid RSA signatures using circom.
### Generating RSA-SHA256 signatures from the CLI
To generate signatures from the CLI - note that your message does not need to be quoted and can be of arbitrary length -, you can clone this repo and run:
```sh
$ yarn install
$ yarn sign this is a message to sign
```
It will log a new signature, generated out of an randomly generated RSA keypair - uses `node:crypto` -. You can copy those values and use them directly within the [zkRSA UI](https://zkrsa.vercel.app/) for generating a new proof.
### Verifying proofs
On the zkRSA UI, you can generate and verify proofs for valid RSA signatures. The verify tab accepts a JSON with the following format:
```js
{
"proof": proof,
"publicSignals": publicSignals
}
```
This is the output format when downloading a proof from the "generate" tab. You can also pre-format your own proof to verify it from the UI.
### Running a frontend locally
To run the UI locally you can clone the repo and run:
```sh
$ cd frontend && yarn install
$ yarn dev
```
There are a few other commands within `frontend/package.json` file, for testing or building the project.
### Links
- [Grant proposal V2](https://hackmd.io/DoZPolTRRN-WNYheT7MauA)

6
zkrsa/circom-rsa-verify/.gitmodules vendored Normal file
View File

@@ -0,0 +1,6 @@
[submodule "circomlib"]
path = circomlib
url = https://github.com/iden3/circomlib.git
[submodule "circom-bigint"]
path = circom-bigint
url = https://github.com/jacksoom/circom-bigint.git

21
zkrsa/circom-rsa-verify/LICENSE vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 zkp-application
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

25
zkrsa/circom-rsa-verify/README.md vendored Normal file
View File

@@ -0,0 +1,25 @@
# circom-rsa-verify
This repository contains an implementation of a Zero Knowledge Proof for RSA signature verify for the circom language.
Currently supported pkcs1v15 + sha256 and exponent is 65537
# Getting started
Running circuits test cases
```sh
git submodule update --init --recursive; npm install; npm test
```
## Circuits Benchmark
RSA verify: pkcs1v15/sha256/2048 bits key
* Env: Mac mini (M1, 2020). 8 cores. 8 threads
* Memory consumption: 1.7G
* Time consumption: 150s
## The circom compiler
This repository uses a modified version of the circom compiler found at
[alex-ozdemir/circom](https://github.com/alex-ozdemir/circom).
It includes a few extra features not found in the original:
* Clearer error printouts
* More comprehensive/informative treatment of `log` statements
* A new type `int` which enables bigints to be handled during witness
computations.
* `compute` blocks

View File

@@ -0,0 +1 @@
node_modules

View File

@@ -0,0 +1,3 @@
[submodule "circomlib"]
path = circomlib
url = https://github.com/iden3/circomlib

View File

@@ -0,0 +1,32 @@
# circom-bigint
This repository contains an implementation of arbitrary-precision natural
numbers for the [`circom`](https://github.com/iden3/circom) language.
## Getting Started
First you'll need a copy of `circomlib` within this repository. You can get it
by running
git submodule update --init --recursive
Then you'll need to install a local copy of the `circom` compiler and the
testing frameworks
npm install
Then you can run the tests
npm test
## The circom compiler
This repository uses a modified version of the circom compiler found at
[alex-ozdemir/circom](https://github.com/alex-ozdemir/circom).
It includes a few extra features not found in the original:
* Clearer error printouts
* More comprehensive/informative treatment of `log` statements
* A new type `int` which enables bigints to be handled during witness
computations.
* `compute` blocks

View File

@@ -0,0 +1,33 @@
module.exports = {
"plugins": [
"mocha"
],
"env": {
"es6": true,
"node": true,
"mocha": true
},
"parserOptions": {
"ecmaVersion": 2017
},
"extends": "eslint:recommended",
"rules": {
"indent": [
"error",
4
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"double"
],
"semi": [
"error",
"always"
],
"mocha/no-exclusive-tests": "error"
}
};

View File

@@ -0,0 +1,65 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# next.js build output
.next
tmp
.DS_Store

View File

@@ -0,0 +1,4 @@
# cirpedersen
Pedersen Hash and Exponentiation circuits using Baby Jub Curve in circom language

View File

@@ -0,0 +1,83 @@
const bn128 = require("snarkjs").bn128;
const bigInt = require("snarkjs").bigInt;
const createBlakeHash = require("blake-hash");
const babyJub = require("../src/babyjub");
function getPoint(S) {
const F = bn128.Fr;
const h = createBlakeHash("blake256").update(S).digest();
if (h.length != 32) {
throw new Error("Invalid length")
}
let sign = false;
if (h[31] & 0x80) {
h[31] = h[31] & 0x7F;
sign = true;
}
let y = bigInt(0);
for (let i=0; i<32; i++) {
y = y.shl(8);
y = y.add(bigInt(h[i]));
}
const a = bigInt("168700");
const d = bigInt("168696");
const y2 = F.square(y);
let x = F.sqrt(F.div(
F.sub(F.one, y2),
F.sub(a, F.mul(d, y2))));
if (x == null) return null;
if (sign) x = F.neg(x);
const p = [bn128.Fr.affine(x), bn128.Fr.affine(y)];
const p8 = babyJub.mulPointEscalar(p, 8);
return p8;
}
function generatePoint(S) {
let p= null;
let idx = 0;
while (p==null) {
let sidx = "" + idx;
while (sidx.length<16) sidx = "0"+sidx;
p = getPoint(S+"_"+sidx);
idx++;
}
if (!babyJub.inCurve(p)){
throw new Error("Point not in curve");
}
return p;
}
const g = [
bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")];
// Sanity check
if (!babyJub.inCurve(g)) {
throw new Error("Generator not In curve -> Some thing goes wrong...");
}
for (let i=0; i<25; i++) {
let S = "" +i;
while (S.length<16) S = "0"+S;
const P = generatePoint("Iden3_PedersenGenerator_"+S);
console.log(`[${P[0].toString()}, ${P[1].toString()}]`);
}

View File

@@ -0,0 +1,14 @@
* compconstant - Returns 1 if `in` (expanded to binary array) > `ct`
* aliascheck - check if `in` (expanded to binary array) oveflowed its 254 bits (<= -1)
* babyjub - twisted Edwards curve 168700.x^2 + y^2 = 1 + 168696.x^2.y^2
* BabyAdd - (`xout`,`yout`) = (`x1`,`y1`) + (`x2`,`y2`)
* BabyDbl - (`xout`,`yout`) = 2*(`x`,`y`)
* BabyCheck - check that (`x`,`y`) is on the curve
* binsub - binary subtraction
* gates - logical gates
* mimc - SNARK-friendly hash Minimal Multiplicative Complexity.
* https://eprint.iacr.org/2016/492.pdf
* zcash/zcash#2233
* smt - Sparse Merkle Tree
* https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751
* montgomery https://en.wikipedia.org/wiki/Montgomery_curve

View File

@@ -0,0 +1,32 @@
/*
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";
template AliasCheck() {
signal input in[254];
component compConstant = CompConstant(-1);
for (var i=0; i<254; i++) in[i] ==> compConstant.in[i];
compConstant.out === 0;
}

View File

@@ -0,0 +1,106 @@
/*
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 "bitify.circom";
include "escalarmulfix.circom";
template BabyAdd() {
signal input x1;
signal input y1;
signal input x2;
signal input y2;
signal output xout;
signal output yout;
signal beta;
signal gamma;
signal delta;
signal tau;
var a = 168700;
var d = 168696;
beta <== x1*y2;
gamma <== y1*x2;
delta <== (-a*x1+y1)*(x2 + y2);
tau <== beta * gamma;
xout <-- (beta + gamma) / (1+ d*tau);
(1+ d*tau) * xout === (beta + gamma);
yout <-- (delta + a*beta - gamma) / (1-d*tau);
(1-d*tau)*yout === (delta + a*beta - gamma);
}
template BabyDbl() {
signal input x;
signal input y;
signal output xout;
signal output yout;
component adder = BabyAdd();
adder.x1 <== x;
adder.y1 <== y;
adder.x2 <== x;
adder.y2 <== y;
adder.xout ==> xout;
adder.yout ==> yout;
}
template BabyCheck() {
signal input x;
signal input y;
signal x2;
signal y2;
var a = 168700;
var d = 168696;
x2 <== x*x;
y2 <== y*y;
a*x2 + y2 === 1 + d*x2*y2;
}
// Extracts the public key from private key
template BabyPbk() {
signal private input in;
signal output Ax;
signal output Ay;
var BASE8 = [
5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203
];
component pvkBits = Num2Bits(253);
pvkBits.in <== in;
component mulFix = EscalarMulFix(253, BASE8);
var i;
for (i=0; i<253; i++) {
mulFix.e[i] <== pvkBits.out[i];
}
Ax <== mulFix.out[0];
Ay <== mulFix.out[1];
}

View File

@@ -0,0 +1,71 @@
/*
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/>.
*/
/*
This component creates a binary substraction.
Main Constraint:
(in[0][0] * 2^0 + in[0][1] * 2^1 + ..... + in[0][n-1] * 2^(n-1)) +
+ 2^n
- (in[1][0] * 2^0 + in[1][1] * 2^1 + ..... + in[1][n-1] * 2^(n-1))
===
out[0] * 2^0 + out[1] * 2^1 + + out[n-1] *2^(n-1) + aux
out[0] * (out[0] - 1) === 0
out[1] * (out[0] - 1) === 0
.
.
.
out[n-1] * (out[n-1] - 1) === 0
aux * (aux-1) == 0
*/
template BinSub(n) {
signal input in[2][n];
signal output out[n];
signal aux;
var lin = 2**n;
var lout = 0;
for (var i=0; i<n; i++) {
lin = lin + in[0][i]*(2**i);
lin = lin - in[1][i]*(2**i);
}
for (var i=0; i<n; i++) {
out[i] <-- (lin >> i) & 1;
// Ensure out is binary
out[i] * (out[i] - 1) === 0;
lout = lout + out[i]*(2**i);
}
aux <-- (lin >> n) & 1;
aux*(aux-1) === 0;
lout = lout + aux*(2**n);
// Ensure the sum;
lin === lout;
}

View File

@@ -0,0 +1,93 @@
/*
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/>.
*/
/*
Binary Sum
==========
This component creates a binary sum componet of ops operands and n bits each operand.
e is Number of carries: Depends on the number of operands in the input.
Main Constraint:
in[0][0] * 2^0 + in[0][1] * 2^1 + ..... + in[0][n-1] * 2^(n-1) +
+ in[1][0] * 2^0 + in[1][1] * 2^1 + ..... + in[1][n-1] * 2^(n-1) +
+ ..
+ in[ops-1][0] * 2^0 + in[ops-1][1] * 2^1 + ..... + in[ops-1][n-1] * 2^(n-1) +
===
out[0] * 2^0 + out[1] * 2^1 + + out[n+e-1] *2(n+e-1)
To waranty binary outputs:
out[0] * (out[0] - 1) === 0
out[1] * (out[0] - 1) === 0
.
.
.
out[n+e-1] * (out[n+e-1] - 1) == 0
*/
/*
This function calculates the number of extra bits in the output to do the full sum.
*/
function nbits(a) {
var n = 1;
var r = 0;
while (n-1<a) {
r++;
n *= 2;
}
return r;
}
template BinSum(n, ops) {
var nout = nbits((2**n -1)*ops);
signal input in[ops][n];
signal output out[nout];
var lin = 0;
var lout = 0;
var k;
var j;
for (k=0; k<n; k++) {
for (j=0; j<ops; j++) {
lin += in[j][k] * 2**k;
}
}
for (k=0; k<nout; k++) {
out[k] <-- (lin >> k) & 1;
// Ensure out is binary
out[k] * (out[k] - 1) === 0;
lout += out[k] * 2**k;
}
// Ensure the sum;
lin === lout;
}

View File

@@ -0,0 +1,101 @@
/*
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 "comparators.circom";
include "aliascheck.circom";
template Num2Bits(n) {
signal input in;
signal output out[n];
var lc1=0;
for (var i = 0; i<n; i++) {
out[i] <-- (in >> i) & 1;
out[i] * (out[i] -1 ) === 0;
lc1 += out[i] * 2**i;
}
lc1 === in;
}
template Num2Bits_strict() {
signal input in;
signal output out[254];
component aliasCheck = AliasCheck();
component n2b = Num2Bits(254);
in ==> n2b.in;
for (var i=0; i<254; i++) {
n2b.out[i] ==> out[i];
n2b.out[i] ==> aliasCheck.in[i];
}
}
template Bits2Num(n) {
signal input in[n];
signal output out;
var lc1=0;
for (var i = 0; i<n; i++) {
lc1 += in[i] * 2**i;
}
lc1 ==> out;
}
template Bits2Num_strict() {
signal input in[n];
signal output out;
component aliasCheck = AliasCheck();
component b2n = Bits2Num(254);
for (var i=0; i<254; i++) {
in[i] ==> b2n.in[i];
in[i] ==> aliasCheck.in[i];
}
b2n.out ==> out;
}
template Num2BitsNeg(n) {
signal input in;
signal output out[n];
var lc1=0;
component isZero;
isZero = IsZero();
var neg = n == 0 ? 0 : 2**n - in;
for (var i = 0; i<n; i++) {
out[i] <-- (neg >> i) & 1;
out[i] * (out[i] -1 ) === 0;
lc1 += out[i] * 2**i;
}
in ==> isZero.in;
lc1 + isZero.out * 2**n === 2**n - in;
}

View File

@@ -0,0 +1,139 @@
/*
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 "bitify.circom";
include "binsum.circom";
template IsZero() {
signal input in;
signal output out;
signal inv;
inv <-- in!=0 ? 1/in : 0;
out <== -in*inv +1;
in*out === 0;
}
template IsEqual() {
signal input in[2];
signal output out;
component isz = IsZero();
in[1] - in[0] ==> isz.in;
isz.out ==> out;
}
template ForceEqualIfEnabled() {
signal input enabled;
signal input in[2];
component isz = IsZero();
in[1] - in[0] ==> isz.in;
(1 - isz.out)*enabled === 0;
}
/*
// N is the number of bits the input have.
// The MSF is the sign bit.
template LessThan(n) {
signal input in[2];
signal output out;
component num2Bits0;
component num2Bits1;
component adder;
adder = BinSum(n, 2);
num2Bits0 = Num2Bits(n);
num2Bits1 = Num2BitsNeg(n);
in[0] ==> num2Bits0.in;
in[1] ==> num2Bits1.in;
var i;
for (i=0;i<n;i++) {
num2Bits0.out[i] ==> adder.in[0][i];
num2Bits1.out[i] ==> adder.in[1][i];
}
adder.out[n-1] ==> out;
}
*/
template LessThan(n) {
signal input in[2];
signal output out;
component n2b = Num2Bits(n*2+1);
n2b.in <== in[0]+ (1<<n) - in[1];
out <== 1-n2b.out[n];
}
// N is the number of bits the input have.
// The MSF is the sign bit.
template LessEqThan(n) {
signal input in[2];
signal output out;
component lt = LessThan(n);
lt.in[0] <== in[0];
lt.in[1] <== in[1]+1;
lt.out ==> out;
}
// N is the number of bits the input have.
// The MSF is the sign bit.
template GreaterThan(n) {
signal input in[2];
signal output out;
component lt = LessThan(n);
lt.in[0] <== in[1];
lt.in[1] <== in[0];
lt.out ==> out;
}
// N is the number of bits the input have.
// The MSF is the sign bit.
template GreaterEqThan(n) {
signal input in[2];
signal output out;
component lt = LessThan(n);
lt.in[0] <== in[1];
lt.in[1] <== in[0]+1;
lt.out ==> out;
}

View File

@@ -0,0 +1,74 @@
/*
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 "bitify.circom";
// Returns 1 if in (in binary) > ct
template CompConstant(ct) {
signal input in[254];
signal output out;
signal parts[127];
signal sout;
var clsb;
var cmsb;
var slsb;
var smsb;
var sum=0;
var b = (1 << 128) -1;
var a = 1;
var e = 1;
var i;
for (i=0;i<127; i++) {
clsb = (ct >> (i*2)) & 1;
cmsb = (ct >> (i*2+1)) & 1;
slsb = in[i*2];
smsb = in[i*2+1];
if ((cmsb==0)&(clsb==0)) {
parts[i] <== -b*smsb*slsb + b*smsb + b*slsb;
} else if ((cmsb==0)&(clsb==1)) {
parts[i] <== a*smsb*slsb - a*slsb + b*smsb - a*smsb + a;
} else if ((cmsb==1)&(clsb==0)) {
parts[i] <== b*smsb*slsb - a*smsb + a;
} else {
parts[i] <== -a*smsb*slsb + a;
}
sum = sum + parts[i];
b = b -e;
a = a +e;
e = e*2;
}
sout <== sum;
component num2bits = Num2Bits(135);
num2bits.in <== sout;
out <== num2bits.out[127];
}

View File

@@ -0,0 +1,138 @@
/*
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 "pedersen.circom";
include "escalarmulany.circom";
include "escalarmulfix.circom";
template EdDSAVerifier(n) {
signal input msg[n];
signal input A[256];
signal input R8[256];
signal input S[256];
signal Ax;
signal Ay;
signal R8x;
signal R8y;
var i;
// Ensure S<Subgroup Order
component compConstant = CompConstant(2736030358979909402780800718157159386076813972158567259200215660948447373040);
for (i=0; i<254; i++) {
S[i] ==> compConstant.in[i];
}
compConstant.out === 0;
S[254] === 0;
S[255] === 0;
// Convert A to Field elements (And verify A)
component bits2pointA = Bits2Point_Strict();
for (i=0; i<256; i++) {
bits2pointA.in[i] <== A[i];
}
Ax <== bits2pointA.out[0];
Ay <== bits2pointA.out[1];
// Convert R8 to Field elements (And verify R8)
component bits2pointR8 = Bits2Point_Strict();
for (i=0; i<256; i++) {
bits2pointR8.in[i] <== R8[i];
}
R8x <== bits2pointR8.out[0];
R8y <== bits2pointR8.out[1];
// Calculate the h = H(R,A, msg)
component hash = Pedersen(512+n);
for (i=0; i<256; i++) {
hash.in[i] <== R8[i];
hash.in[256+i] <== A[i];
}
for (i=0; i<n; i++) {
hash.in[512+i] <== msg[i];
}
component point2bitsH = Point2Bits_Strict();
point2bitsH.in[0] <== hash.out[0];
point2bitsH.in[1] <== hash.out[1];
// 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(256);
for (i=0; i<256; i++) {
mulAny.e[i] <== point2bitsH.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 = [
5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203
];
component mulFix = EscalarMulFix(256, BASE8);
for (i=0; i<256; i++) {
mulFix.e[i] <== S[i];
}
// Do the comparation left == right
mulFix.out[0] === addRight.xout;
mulFix.out[1] === addRight.yout;
}

View File

@@ -0,0 +1,123 @@
/*
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;
hash.k <== 0;
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 = [
5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203
];
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;
}

View File

@@ -0,0 +1,123 @@
/*
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 "mimcsponge.circom";
include "bitify.circom";
include "escalarmulany.circom";
include "escalarmulfix.circom";
template EdDSAMiMCSpongeVerifier() {
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 = MiMCSponge(5, 220, 1);
hash.ins[0] <== R8x;
hash.ins[1] <== R8y;
hash.ins[2] <== Ax;
hash.ins[3] <== Ay;
hash.ins[4] <== M;
hash.k <== 0;
component h2bits = Num2Bits_strict();
h2bits.in <== hash.outs[0];
// 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 = [
5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203
];
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;
}

View File

@@ -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 "poseidon.circom";
include "bitify.circom";
include "escalarmulany.circom";
include "escalarmulfix.circom";
template EdDSAPoseidonVerifier() {
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 = Poseidon(5, 6, 8, 57);
hash.inputs[0] <== R8x;
hash.inputs[1] <== R8y;
hash.inputs[2] <== Ax;
hash.inputs[3] <== Ay;
hash.inputs[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 = [
5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203
];
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;
}

View File

@@ -0,0 +1,165 @@
/*
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];
component 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++) {
table.out[i][0] ==> mux.c[0][i];
table.out[i][1] ==> mux.c[1][i];
}
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];
}

View File

@@ -0,0 +1,192 @@
/*
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 "montgomery.circom";
include "babyjub.circom";
template Multiplexor2() {
signal input sel;
signal input in[2][2];
signal output out[2];
out[0] <== (in[1][0] - in[0][0])*sel + in[0][0];
out[1] <== (in[1][1] - in[0][1])*sel + in[0][1];
}
template BitElementMulAny() {
signal input sel;
signal input dblIn[2];
signal input addIn[2];
signal output dblOut[2];
signal output addOut[2];
component doubler = MontgomeryDouble();
component adder = MontgomeryAdd();
component selector = Multiplexor2();
sel ==> selector.sel;
dblIn[0] ==> doubler.in[0];
dblIn[1] ==> doubler.in[1];
doubler.out[0] ==> adder.in1[0];
doubler.out[1] ==> adder.in1[1];
addIn[0] ==> adder.in2[0];
addIn[1] ==> adder.in2[1];
addIn[0] ==> selector.in[0][0];
addIn[1] ==> selector.in[0][1];
adder.out[0] ==> selector.in[1][0];
adder.out[1] ==> selector.in[1][1];
doubler.out[0] ==> dblOut[0];
doubler.out[1] ==> dblOut[1];
selector.out[0] ==> addOut[0];
selector.out[1] ==> addOut[1];
}
// p is montgomery point
// n must be <= 248
// returns out in twisted edwards
// Double is in montgomery to be linked;
template SegmentMulAny(n) {
signal input e[n];
signal input p[2];
signal output out[2];
signal output dbl[2];
component bits[n-1];
component e2m = Edwards2Montgomery();
p[0] ==> e2m.in[0];
p[1] ==> e2m.in[1];
var i;
bits[0] = BitElementMulAny();
e2m.out[0] ==> bits[0].dblIn[0]
e2m.out[1] ==> bits[0].dblIn[1]
e2m.out[0] ==> bits[0].addIn[0]
e2m.out[1] ==> bits[0].addIn[1]
e[1] ==> bits[0].sel;
for (i=1; i<n-1; i++) {
bits[i] = BitElementMulAny();
bits[i-1].dblOut[0] ==> bits[i].dblIn[0]
bits[i-1].dblOut[1] ==> bits[i].dblIn[1]
bits[i-1].addOut[0] ==> bits[i].addIn[0]
bits[i-1].addOut[1] ==> bits[i].addIn[1]
e[i+1] ==> bits[i].sel;
}
bits[n-2].dblOut[0] ==> dbl[0];
bits[n-2].dblOut[1] ==> dbl[1];
component m2e = Montgomery2Edwards();
bits[n-2].addOut[0] ==> m2e.in[0];
bits[n-2].addOut[1] ==> m2e.in[1];
component eadder = BabyAdd();
m2e.out[0] ==> eadder.x1;
m2e.out[1] ==> eadder.y1;
-p[0] ==> eadder.x2;
p[1] ==> eadder.y2;
component lastSel = Multiplexor2();
e[0] ==> lastSel.sel;
eadder.xout ==> lastSel.in[0][0];
eadder.yout ==> lastSel.in[0][1];
m2e.out[0] ==> lastSel.in[1][0];
m2e.out[1] ==> lastSel.in[1][1];
lastSel.out[0] ==> out[0];
lastSel.out[1] ==> out[1];
}
// This function assumes that p is in the subgroup and it is different to 0
template EscalarMulAny(n) {
signal input e[n]; // Input in binary format
signal input p[2]; // Point (Twisted format)
signal output out[2]; // Point (Twisted format)
var nsegments = (n-1)\148 +1;
var nlastsegment = n - (nsegments-1)*148;
component segments[nsegments];
component doublers[nsegments-1];
component m2e[nsegments-1];
component adders[nsegments-1];
var s;
var i;
var nseg;
for (s=0; s<nsegments; s++) {
nseg = (s < nsegments-1) ? 148 : nlastsegment;
segments[s] = SegmentMulAny(nseg);
for (i=0; i<nseg; i++) {
e[s*148+i] ==> segments[s].e[i];
}
if (s==0) {
p[0] ==> segments[s].p[0];
p[1] ==> segments[s].p[1];
} else {
doublers[s-1] = MontgomeryDouble();
m2e[s-1] = Montgomery2Edwards();
adders[s-1] = BabyAdd();
segments[s-1].dbl[0] ==> doublers[s-1].in[0];
segments[s-1].dbl[1] ==> doublers[s-1].in[1];
doublers[s-1].out[0] ==> m2e[s-1].in[0];
doublers[s-1].out[1] ==> m2e[s-1].in[1];
m2e[s-1].out[0] ==> segments[s].p[0];
m2e[s-1].out[1] ==> segments[s].p[1];
if (s==1) {
segments[s-1].out[0] ==> adders[s-1].x1;
segments[s-1].out[1] ==> adders[s-1].y1;
} else {
adders[s-2].xout ==> adders[s-1].x1;
adders[s-2].yout ==> adders[s-1].y1;
}
segments[s].out[0] ==> adders[s-1].x2;
segments[s].out[1] ==> adders[s-1].y2;
}
}
if (nsegments == 1) {
segments[0].out[0] ==> out[0];
segments[0].out[1] ==> out[1];
} else {
adders[nsegments-2].xout ==> out[0];
adders[nsegments-2].yout ==> out[1];
}
}

View File

@@ -0,0 +1,298 @@
/*
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 "mux3.circom";
include "montgomery.circom";
include "babyjub.circom";
/*
Window of 3 elements, it calculates
out = base + base*in[0] + 2*base*in[1] + 4*base*in[2]
out4 = 4*base
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() {
signal input in[3];
signal input base[2];
signal output out[2];
signal output out8[2]; // Returns 8*Base (To be linked)
component mux = MultiMux3(2);
mux.s[0] <== in[0];
mux.s[1] <== in[1];
mux.s[2] <== in[2];
component dbl2 = MontgomeryDouble();
component adr3 = MontgomeryAdd();
component adr4 = MontgomeryAdd();
component adr5 = MontgomeryAdd();
component adr6 = MontgomeryAdd();
component adr7 = MontgomeryAdd();
component adr8 = MontgomeryAdd();
// in[0] -> 1*BASE
mux.c[0][0] <== base[0];
mux.c[1][0] <== base[1];
// in[1] -> 2*BASE
dbl2.in[0] <== base[0];
dbl2.in[1] <== base[1];
mux.c[0][1] <== dbl2.out[0];
mux.c[1][1] <== dbl2.out[1];
// in[2] -> 3*BASE
adr3.in1[0] <== base[0];
adr3.in1[1] <== base[1];
adr3.in2[0] <== dbl2.out[0];
adr3.in2[1] <== dbl2.out[1];
mux.c[0][2] <== adr3.out[0];
mux.c[1][2] <== adr3.out[1];
// in[3] -> 4*BASE
adr4.in1[0] <== base[0];
adr4.in1[1] <== base[1];
adr4.in2[0] <== adr3.out[0];
adr4.in2[1] <== adr3.out[1];
mux.c[0][3] <== adr4.out[0];
mux.c[1][3] <== adr4.out[1];
// in[4] -> 5*BASE
adr5.in1[0] <== base[0];
adr5.in1[1] <== base[1];
adr5.in2[0] <== adr4.out[0];
adr5.in2[1] <== adr4.out[1];
mux.c[0][4] <== adr5.out[0];
mux.c[1][4] <== adr5.out[1];
// in[5] -> 6*BASE
adr6.in1[0] <== base[0];
adr6.in1[1] <== base[1];
adr6.in2[0] <== adr5.out[0];
adr6.in2[1] <== adr5.out[1];
mux.c[0][5] <== adr6.out[0];
mux.c[1][5] <== adr6.out[1];
// in[6] -> 7*BASE
adr7.in1[0] <== base[0];
adr7.in1[1] <== base[1];
adr7.in2[0] <== adr6.out[0];
adr7.in2[1] <== adr6.out[1];
mux.c[0][6] <== adr7.out[0];
mux.c[1][6] <== adr7.out[1];
// in[7] -> 8*BASE
adr8.in1[0] <== base[0];
adr8.in1[1] <== base[1];
adr8.in2[0] <== adr7.out[0];
adr8.in2[1] <== adr7.out[1];
mux.c[0][7] <== adr8.out[0];
mux.c[1][7] <== adr8.out[1];
out8[0] <== adr8.out[0];
out8[1] <== adr8.out[1];
out[0] <== mux.out[0];
out[1] <== mux.out[1];
}
/*
This component does a multiplication of a escalar times a fix base
Signals:
e: The scalar in bits
base: the base point in edwards format
out: The result
dbl: Point in Edwards to be linked to the next segment.
*/
template SegmentMulFix(nWindows) {
signal input e[nWindows*3];
signal input base[2];
signal output out[2];
signal output dbl[2];
var i;
var j;
// Convert the base to montgomery
component e2m = Edwards2Montgomery();
e2m.in[0] <== base[0];
e2m.in[1] <== base[1];
component windows[nWindows];
component adders[nWindows];
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++) {
windows[i] = WindowMulFix();
cadders[i] = MontgomeryAdd();
if (i==0) {
windows[i].base[0] <== e2m.out[0];
windows[i].base[1] <== e2m.out[1];
cadders[i].in1[0] <== e2m.out[0];
cadders[i].in1[1] <== e2m.out[1];
} else {
windows[i].base[0] <== windows[i-1].out8[0];
windows[i].base[1] <== windows[i-1].out8[1];
cadders[i].in1[0] <== cadders[i-1].out[0];
cadders[i].in1[1] <== cadders[i-1].out[1];
}
if (i<nWindows-1) {
cadders[i].in2[0] <== windows[i].out8[0];
cadders[i].in2[1] <== windows[i].out8[1];
} else {
dblLast.in[0] <== windows[i].out8[0];
dblLast.in[1] <== windows[i].out8[1];
cadders[i].in2[0] <== dblLast.out[0];
cadders[i].in2[1] <== dblLast.out[1];
}
for (j=0; j<3; 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 cm2e = Montgomery2Edwards();
m2e.in[0] <== adders[nWindows-1].out[0];
m2e.in[1] <== adders[nWindows-1].out[1];
cm2e.in[0] <== cadders[nWindows-1].out[0];
cm2e.in[1] <== cadders[nWindows-1].out[1];
component cAdd = BabyAdd();
cAdd.x1 <== m2e.out[0];
cAdd.y1 <== m2e.out[1];
cAdd.x2 <== -cm2e.out[0];
cAdd.y2 <== cm2e.out[1];
cAdd.xout ==> out[0];
cAdd.yout ==> out[1];
windows[nWindows-1].out8[0] ==> dbl[0];
windows[nWindows-1].out8[1] ==> dbl[1];
}
/*
This component multiplies a escalar times a fixed point BASE (twisted edwards format)
Signals
e: The escalar in binary format
out: The output point in twisted edwards
*/
template EscalarMulFix(n, BASE) {
signal input e[n]; // Input in binary format
signal output out[2]; // Point (Twisted format)
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;
component segments[nsegments];
component m2e[nsegments-1];
component adders[nsegments-1];
var s;
var i;
var nseg;
var nWindows
for (s=0; s<nsegments; s++) {
nseg = (s < nsegments-1) ? 249 : nlastsegment;
nWindows = ((nseg - 1)\3)+1;
segments[s] = SegmentMulFix(nWindows);
for (i=0; i<nseg; i++) {
segments[s].e[i] <== e[s*249+i];
}
for (i = nseg; i<nWindows*3; i++) {
segments[s].e[i] <== 0;
}
if (s==0) {
segments[s].base[0] <== BASE[0];
segments[s].base[1] <== BASE[1];
} else {
m2e[s-1] = Montgomery2Edwards();
adders[s-1] = BabyAdd();
segments[s-1].dbl[0] ==> m2e[s-1].in[0];
segments[s-1].dbl[1] ==> m2e[s-1].in[1];
m2e[s-1].out[0] ==> segments[s].base[0];
m2e[s-1].out[1] ==> segments[s].base[1];
if (s==1) {
segments[s-1].out[0] ==> adders[s-1].x1;
segments[s-1].out[1] ==> adders[s-1].y1;
} else {
adders[s-2].xout ==> adders[s-1].x1;
adders[s-2].yout ==> adders[s-1].y1;
}
segments[s].out[0] ==> adders[s-1].x2;
segments[s].out[1] ==> adders[s-1].y2;
}
}
if (nsegments == 1) {
segments[0].out[0] ==> out[0];
segments[0].out[1] ==> out[1];
} else {
adders[nsegments-2].xout ==> out[0];
adders[nsegments-2].yout ==> out[1];
}
}

View File

@@ -0,0 +1,49 @@
/*
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/>.
*/
function pointAdd(x1,y1,x2,y2) {
var a = 168700;
var d = 168696;
var res[2];
res[0] = (x1*y2 + y1*x2) / (1 + d*x1*x2*y1*y2);
res[1] = (y1*y2 - a*x1*x2) / (1 - d*x1*x2*y1*y2);
return res;
}
template EscalarMulW4Table(base, k) {
signal output out[16][2];
var i;
var p[2];
var dbl = base;
for (i=0; i<k*4; i++) {
dbl = pointAdd(dbl[0], dbl[1], dbl[0], dbl[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];
}
}

View File

@@ -0,0 +1,92 @@
/*
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/>.
*/
template XOR() {
signal input a;
signal input b;
signal output out;
out <== a + b - 2*a*b;
}
template AND() {
signal input a;
signal input b;
signal output out;
out <== a*b;
}
template OR() {
signal input a;
signal input b;
signal output out;
out <== a + b - a*b;
}
template NOT() {
signal input in;
signal output out;
out <== 1 + in - 2*in;
}
template NAND() {
signal input a;
signal input b;
signal output out;
out <== 1 - a*b;
}
template NOR() {
signal input a;
signal input b;
signal output out;
out <== a*b + 1 - a - b;
}
template MultiAND(n) {
signal input in[n];
signal output out;
if (n==1) {
out <== in[0];
} else if (n==2) {
component and1 = AND();
and1.a <== in[0];
and1.b <== in[1];
out <== and1.out;
} else {
component and2 = AND();
component ands[2];
var n1 = n\2;
var n2 = n-n\2;
ands[0] = MultiAND(n1);
ands[1] = MultiAND(n2);
for (var i=0; i<n1; i++) ands[0].in[i] <== in[i];
for (var i=0; i<n2; i++) ands[1].in[i] <== in[n1+i];
and2.a <== ands[0].out;
and2.b <== ands[1].out;
out <== and2.out;
}
}

View File

@@ -0,0 +1,155 @@
/*
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/>.
*/
template MiMC7(nrounds) {
signal input x_in;
signal input k;
signal output out;
var c = [
0,
20888961410941983456478427210666206549300505294776164667214940546594746570981,
15265126113435022738560151911929040668591755459209400716467504685752745317193,
8334177627492981984476504167502758309043212251641796197711684499645635709656,
1374324219480165500871639364801692115397519265181803854177629327624133579404,
11442588683664344394633565859260176446561886575962616332903193988751292992472,
2558901189096558760448896669327086721003508630712968559048179091037845349145,
11189978595292752354820141775598510151189959177917284797737745690127318076389,
3262966573163560839685415914157855077211340576201936620532175028036746741754,
17029914891543225301403832095880481731551830725367286980611178737703889171730,
4614037031668406927330683909387957156531244689520944789503628527855167665518,
19647356996769918391113967168615123299113119185942498194367262335168397100658,
5040699236106090655289931820723926657076483236860546282406111821875672148900,
2632385916954580941368956176626336146806721642583847728103570779270161510514,
17691411851977575435597871505860208507285462834710151833948561098560743654671,
11482807709115676646560379017491661435505951727793345550942389701970904563183,
8360838254132998143349158726141014535383109403565779450210746881879715734773,
12663821244032248511491386323242575231591777785787269938928497649288048289525,
3067001377342968891237590775929219083706800062321980129409398033259904188058,
8536471869378957766675292398190944925664113548202769136103887479787957959589,
19825444354178182240559170937204690272111734703605805530888940813160705385792,
16703465144013840124940690347975638755097486902749048533167980887413919317592,
13061236261277650370863439564453267964462486225679643020432589226741411380501,
10864774797625152707517901967943775867717907803542223029967000416969007792571,
10035653564014594269791753415727486340557376923045841607746250017541686319774,
3446968588058668564420958894889124905706353937375068998436129414772610003289,
4653317306466493184743870159523234588955994456998076243468148492375236846006,
8486711143589723036499933521576871883500223198263343024003617825616410932026,
250710584458582618659378487568129931785810765264752039738223488321597070280,
2104159799604932521291371026105311735948154964200596636974609406977292675173,
16313562605837709339799839901240652934758303521543693857533755376563489378839,
6032365105133504724925793806318578936233045029919447519826248813478479197288,
14025118133847866722315446277964222215118620050302054655768867040006542798474,
7400123822125662712777833064081316757896757785777291653271747396958201309118,
1744432620323851751204287974553233986555641872755053103823939564833813704825,
8316378125659383262515151597439205374263247719876250938893842106722210729522,
6739722627047123650704294650168547689199576889424317598327664349670094847386,
21211457866117465531949733809706514799713333930924902519246949506964470524162,
13718112532745211817410303291774369209520657938741992779396229864894885156527,
5264534817993325015357427094323255342713527811596856940387954546330728068658,
18884137497114307927425084003812022333609937761793387700010402412840002189451,
5148596049900083984813839872929010525572543381981952060869301611018636120248,
19799686398774806587970184652860783461860993790013219899147141137827718662674,
19240878651604412704364448729659032944342952609050243268894572835672205984837,
10546185249390392695582524554167530669949955276893453512788278945742408153192,
5507959600969845538113649209272736011390582494851145043668969080335346810411,
18177751737739153338153217698774510185696788019377850245260475034576050820091,
19603444733183990109492724100282114612026332366576932662794133334264283907557,
10548274686824425401349248282213580046351514091431715597441736281987273193140,
1823201861560942974198127384034483127920205835821334101215923769688644479957,
11867589662193422187545516240823411225342068709600734253659804646934346124945,
18718569356736340558616379408444812528964066420519677106145092918482774343613,
10530777752259630125564678480897857853807637120039176813174150229243735996839,
20486583726592018813337145844457018474256372770211860618687961310422228379031,
12690713110714036569415168795200156516217175005650145422920562694422306200486,
17386427286863519095301372413760745749282643730629659997153085139065756667205,
2216432659854733047132347621569505613620980842043977268828076165669557467682,
6309765381643925252238633914530877025934201680691496500372265330505506717193,
20806323192073945401862788605803131761175139076694468214027227878952047793390,
4037040458505567977365391535756875199663510397600316887746139396052445718861,
19948974083684238245321361840704327952464170097132407924861169241740046562673,
845322671528508199439318170916419179535949348988022948153107378280175750024,
16222384601744433420585982239113457177459602187868460608565289920306145389382,
10232118865851112229330353999139005145127746617219324244541194256766741433339,
6699067738555349409504843460654299019000594109597429103342076743347235369120,
6220784880752427143725783746407285094967584864656399181815603544365010379208,
6129250029437675212264306655559561251995722990149771051304736001195288083309,
10773245783118750721454994239248013870822765715268323522295722350908043393604,
4490242021765793917495398271905043433053432245571325177153467194570741607167,
19596995117319480189066041930051006586888908165330319666010398892494684778526,
837850695495734270707668553360118467905109360511302468085569220634750561083,
11803922811376367215191737026157445294481406304781326649717082177394185903907,
10201298324909697255105265958780781450978049256931478989759448189112393506592,
13564695482314888817576351063608519127702411536552857463682060761575100923924,
9262808208636973454201420823766139682381973240743541030659775288508921362724,
173271062536305557219323722062711383294158572562695717740068656098441040230,
18120430890549410286417591505529104700901943324772175772035648111937818237369,
20484495168135072493552514219686101965206843697794133766912991150184337935627,
19155651295705203459475805213866664350848604323501251939850063308319753686505,
11971299749478202793661982361798418342615500543489781306376058267926437157297,
18285310723116790056148596536349375622245669010373674803854111592441823052978,
7069216248902547653615508023941692395371990416048967468982099270925308100727,
6465151453746412132599596984628739550147379072443683076388208843341824127379,
16143532858389170960690347742477978826830511669766530042104134302796355145785,
19362583304414853660976404410208489566967618125972377176980367224623492419647,
1702213613534733786921602839210290505213503664731919006932367875629005980493,
10781825404476535814285389902565833897646945212027592373510689209734812292327,
4212716923652881254737947578600828255798948993302968210248673545442808456151,
7594017890037021425366623750593200398174488805473151513558919864633711506220,
18979889247746272055963929241596362599320706910852082477600815822482192194401,
13602139229813231349386885113156901793661719180900395818909719758150455500533
];
var t;
signal t2[nrounds];
signal t4[nrounds];
signal t6[nrounds];
signal t7[nrounds-1];
for (var i=0; i<nrounds; i++) {
t = (i==0) ? k+x_in : k + t7[i-1] + c[i];
t2[i] <== t*t;
t4[i] <== t2[i]*t2[i];
t6[i] <== t4[i]*t2[i];
if (i<nrounds-1) {
t7[i] <== t6[i]*t;
} else {
out <== t6[i]*t + k;
}
}
}
template MultiMiMC7(nInputs, nRounds) {
signal input in[nInputs];
signal input k;
signal output out;
signal r[nInputs +1];
component mims[nInputs];
r[0] <== k;
for (var i=0; i<nInputs; i++) {
mims[i] = MiMC7(nRounds);
mims[i].x_in <== in[i];
mims[i].k <== r[i];
r[i+1] <== r[i] + in[i] + mims[i].out;
}
out <== r[nInputs];
}

View File

@@ -0,0 +1,283 @@
// implements MiMC-2n/n as hash using a sponge construction.
// log_5(21888242871839275222246405745257275088548364400416034343698204186575808495617) ~= 110
// => nRounds should be 220
template MiMCSponge(nInputs, nRounds, nOutputs) {
signal input ins[nInputs];
signal input k;
signal output outs[nOutputs];
// S = R||C
component S[nInputs + nOutputs - 1];
for (var i = 0; i < nInputs; i++) {
S[i] = MiMCFeistel(nRounds);
S[i].k <== k;
if (i == 0) {
S[i].xL_in <== ins[0];
S[i].xR_in <== 0;
} else {
S[i].xL_in <== S[i-1].xL_out + ins[i];
S[i].xR_in <== S[i-1].xR_out;
}
}
outs[0] = S[nInputs - 1].xL_out;
for (var i = 0; i < nOutputs - 1; i++) {
S[nInputs + i] = MiMCFeistel(nRounds);
S[nInputs + i].k <== k;
S[nInputs + i].xL_in <== S[nInputs + i - 1].xL_out;
S[nInputs + i].xR_in <== S[nInputs + i - 1].xR_out;
outs[i + 1] <== S[nInputs + i].xL_out;
}
}
template MiMCFeistel(nrounds) {
signal input xL_in;
signal input xR_in;
signal input k;
signal output xL_out;
signal output xR_out;
var c = [
0,
7120861356467848435263064379192047478074060781135320967663101236819528304084,
5024705281721889198577876690145313457398658950011302225525409148828000436681,
17980351014018068290387269214713820287804403312720763401943303895585469787384,
19886576439381707240399940949310933992335779767309383709787331470398675714258,
1213715278223786725806155661738676903520350859678319590331207960381534602599,
18162138253399958831050545255414688239130588254891200470934232514682584734511,
7667462281466170157858259197976388676420847047604921256361474169980037581876,
7207551498477838452286210989212982851118089401128156132319807392460388436957,
9864183311657946807255900203841777810810224615118629957816193727554621093838,
4798196928559910300796064665904583125427459076060519468052008159779219347957,
17387238494588145257484818061490088963673275521250153686214197573695921400950,
10005334761930299057035055370088813230849810566234116771751925093634136574742,
11897542014760736209670863723231849628230383119798486487899539017466261308762,
16771780563523793011283273687253985566177232886900511371656074413362142152543,
749264854018824809464168489785113337925400687349357088413132714480582918506,
3683645737503705042628598550438395339383572464204988015434959428676652575331,
7556750851783822914673316211129907782679509728346361368978891584375551186255,
20391289379084797414557439284689954098721219201171527383291525676334308303023,
18146517657445423462330854383025300323335289319277199154920964274562014376193,
8080173465267536232534446836148661251987053305394647905212781979099916615292,
10796443006899450245502071131975731672911747129805343722228413358507805531141,
5404287610364961067658660283245291234008692303120470305032076412056764726509,
4623894483395123520243967718315330178025957095502546813929290333264120223168,
16845753148201777192406958674202574751725237939980634861948953189320362207797,
4622170486584704769521001011395820886029808520586507873417553166762370293671,
16688277490485052681847773549197928630624828392248424077804829676011512392564,
11878652861183667748838188993669912629573713271883125458838494308957689090959,
2436445725746972287496138382764643208791713986676129260589667864467010129482,
1888098689545151571063267806606510032698677328923740058080630641742325067877,
148924106504065664829055598316821983869409581623245780505601526786791681102,
18875020877782404439294079398043479420415331640996249745272087358069018086569,
15189693413320228845990326214136820307649565437237093707846682797649429515840,
19669450123472657781282985229369348220906547335081730205028099210442632534079,
5521922218264623411380547905210139511350706092570900075727555783240701821773,
4144769320246558352780591737261172907511489963810975650573703217887429086546,
10097732913112662248360143041019433907849917041759137293018029019134392559350,
1720059427972723034107765345743336447947522473310069975142483982753181038321,
6302388219880227251325608388535181451187131054211388356563634768253301290116,
6745410632962119604799318394592010194450845483518862700079921360015766217097,
10858157235265583624235850660462324469799552996870780238992046963007491306222,
20241898894740093733047052816576694435372877719072347814065227797906130857593,
10165780782761211520836029617746977303303335603838343292431760011576528327409,
2832093654883670345969792724123161241696170611611744759675180839473215203706,
153011722355526826233082383360057587249818749719433916258246100068258954737,
20196970640587451358539129330170636295243141659030208529338914906436009086943,
3180973917010545328313139835982464870638521890385603025657430208141494469656,
17198004293191777441573635123110935015228014028618868252989374962722329283022,
7642160509228669138628515458941659189680509753651629476399516332224325757132,
19346204940546791021518535594447257347218878114049998691060016493806845179755,
11501810868606870391127866188394535330696206817602260610801897042898616817272,
3113973447392053821824427670386252797811804954746053461397972968381571297505,
6545064306297957002139416752334741502722251869537551068239642131448768236585,
5203908808704813498389265425172875593837960384349653691918590736979872578408,
2246692432011290582160062129070762007374502637007107318105405626910313810224,
11760570435432189127645691249600821064883781677693087773459065574359292849137,
5543749482491340532547407723464609328207990784853381797689466144924198391839,
8837549193990558762776520822018694066937602576881497343584903902880277769302,
12855514863299373699594410385788943772765811961581749194183533625311486462501,
5363660674689121676875069134269386492382220935599781121306637800261912519729,
13162342403579303950549728848130828093497701266240457479693991108217307949435,
916941639326869583414469202910306428966657806899788970948781207501251816730,
15618589556584434434009868216186115416835494805174158488636000580759692174228,
8959562060028569701043973060670353733575345393653685776974948916988033453971,
16390754464333401712265575949874369157699293840516802426621216808905079127650,
168282396747788514908709091757591226095443902501365500003618183905496160435,
8327443473179334761744301768309008451162322941906921742120510244986704677004,
17213012626801210615058753489149961717422101711567228037597150941152495100640,
10394369641533736715250242399198097296122982486516256408681925424076248952280,
17784386835392322654196171115293700800825771210400152504776806618892170162248,
16533189939837087893364000390641148516479148564190420358849587959161226782982,
18725396114211370207078434315900726338547621160475533496863298091023511945076,
7132325028834551397904855671244375895110341505383911719294705267624034122405,
148317947440800089795933930720822493695520852448386394775371401743494965187,
19001050671757720352890779127693793630251266879994702723636759889378387053056,
18824274411769830274877839365728651108434404855803844568234862945613766611460,
12771414330193951156383998390424063470766226667986423961689712557338777174205,
11332046574800279729678603488745295198038913503395629790213378101166488244657,
9607550223176946388146938069307456967842408600269548190739947540821716354749,
8756385288462344550200229174435953103162307705310807828651304665320046782583,
176061952957067086877570020242717222844908281373122372938833890096257042779,
12200212977482648306758992405065921724409841940671166017620928947866825250857,
10868453624107875516866146499877130701929063632959660262366632833504750028858,
2016095394399807253596787752134573207202567875457560571095586743878953450738,
21815578223768330433802113452339488275704145896544481092014911825656390567514,
4923772847693564777744725640710197015181591950368494148029046443433103381621,
1813584943682214789802230765734821149202472893379265320098816901270224589984,
10810123816265612772922113403831964815724109728287572256602010709288980656498,
1153669123397255702524721206511185557982017410156956216465120456256288427021,
5007518659266430200134478928344522649876467369278722765097865662497773767152,
2511432546938591792036639990606464315121646668029252285288323664350666551637,
32883284540320451295484135704808083452381176816565850047310272290579727564,
10484856914279112612610993418405543310546746652738541161791501150994088679557,
2026733759645519472558796412979210009170379159866522399881566309631434814953,
14731806221235869882801331463708736361296174006732553130708107037190460654379,
14740327483193277147065845135561988641238516852487657117813536909482068950652,
18787428285295558781869865751953016580493190547148386433580291216673009884554,
3804047064713122820157099453648459188816376755739202017447862327783289895072,
16709604795697901641948603019242067672006293290826991671766611326262532802914,
11061717085931490100602849654034280576915102867237101935487893025907907250695,
2821730726367472966906149684046356272806484545281639696873240305052362149654,
17467794879902895769410571945152708684493991588672014763135370927880883292655,
1571520786233540988201616650622796363168031165456869481368085474420849243232,
10041051776251223165849354194892664881051125330236567356945669006147134614302,
3981753758468103976812813304477670033098707002886030847251581853700311567551,
4365864398105436789177703571412645548020537580493599380018290523813331678900,
2391801327305361293476178683853802679507598622000359948432171562543560193350,
214219368547551689972421167733597094823289857206402800635962137077096090722,
18192064100315141084242006659317257023098826945893371479835220462302399655674,
15487549757142039139328911515400805508248576685795694919457041092150651939253,
10142447197759703415402259672441315777933858467700579946665223821199077641122,
11246573086260753259993971254725613211193686683988426513880826148090811891866,
6574066859860991369704567902211886840188702386542112593710271426704432301235,
11311085442652291634822798307831431035776248927202286895207125867542470350078,
20977948360215259915441258687649465618185769343138135384346964466965010873779,
792781492853909872425531014397300057232399608769451037135936617996830018501,
5027602491523497423798779154966735896562099398367163998686335127580757861872,
14595204575654316237672764823862241845410365278802914304953002937313300553572,
13973538843621261113924259058427434053808430378163734641175100160836376897004,
16395063164993626722686882727042150241125309409717445381854913964674649318585,
8465768840047024550750516678171433288207841931251654898809033371655109266663,
21345603324471810861925019445720576814602636473739003852898308205213912255830,
21171984405852590343970239018692870799717057961108910523876770029017785940991,
10761027113757988230637066281488532903174559953630210849190212601991063767647,
6678298831065390834922566306988418588227382406175769592902974103663687992230,
4993662582188632374202316265508850988596880036291765531885657575099537176757,
18364168158495573675698600238443218434246806358811328083953887470513967121206,
3506345610354615013737144848471391553141006285964325596214723571988011984829,
248732676202643792226973868626360612151424823368345645514532870586234380100,
10090204501612803176317709245679152331057882187411777688746797044706063410969,
21297149835078365363970699581821844234354988617890041296044775371855432973500,
16729368143229828574342820060716366330476985824952922184463387490091156065099,
4467191506765339364971058668792642195242197133011672559453028147641428433293,
8677548159358013363291014307402600830078662555833653517843708051504582990832,
1022951765127126818581466247360193856197472064872288389992480993218645055345,
1888195070251580606973417065636430294417895423429240431595054184472931224452,
4221265384902749246920810956363310125115516771964522748896154428740238579824,
2825393571154632139467378429077438870179957021959813965940638905853993971879,
19171031072692942278056619599721228021635671304612437350119663236604712493093,
10780807212297131186617505517708903709488273075252405602261683478333331220733,
18230936781133176044598070768084230333433368654744509969087239465125979720995,
16901065971871379877929280081392692752968612240624985552337779093292740763381,
146494141603558321291767829522948454429758543710648402457451799015963102253,
2492729278659146790410698334997955258248120870028541691998279257260289595548,
2204224910006646535594933495262085193210692406133533679934843341237521233504,
16062117410185840274616925297332331018523844434907012275592638570193234893570,
5894928453677122829055071981254202951712129328678534592916926069506935491729,
4947482739415078212217504789923078546034438919537985740403824517728200332286,
16143265650645676880461646123844627780378251900510645261875867423498913438066,
397690828254561723549349897112473766901585444153303054845160673059519614409,
11272653598912269895509621181205395118899451234151664604248382803490621227687,
15566927854306879444693061574322104423426072650522411176731130806720753591030,
14222898219492484180162096141564251903058269177856173968147960855133048449557,
16690275395485630428127725067513114066329712673106153451801968992299636791385,
3667030990325966886479548860429670833692690972701471494757671819017808678584,
21280039024501430842616328642522421302481259067470872421086939673482530783142,
15895485136902450169492923978042129726601461603404514670348703312850236146328,
7733050956302327984762132317027414325566202380840692458138724610131603812560,
438123800976401478772659663183448617575635636575786782566035096946820525816,
814913922521637742587885320797606426167962526342166512693085292151314976633,
12368712287081330853637674140264759478736012797026621876924395982504369598764,
2494806857395134874309386694756263421445039103814920780777601708371037591569,
16101132301514338989512946061786320637179843435886825102406248183507106312877,
6252650284989960032925831409804233477770646333900692286731621844532438095656,
9277135875276787021836189566799935097400042171346561246305113339462708861695,
10493603554686607050979497281838644324893776154179810893893660722522945589063,
8673089750662709235894359384294076697329948991010184356091130382437645649279,
9558393272910366944245875920138649617479779893610128634419086981339060613250,
19012287860122586147374214541764572282814469237161122489573881644994964647218,
9783723818270121678386992630754842961728702994964214799008457449989291229500,
15550788416669474113213749561488122552422887538676036667630838378023479382689,
15016165746156232864069722572047169071786333815661109750860165034341572904221,
6506225705710197163670556961299945987488979904603689017479840649664564978574,
10796631184889302076168355684722130903785890709107732067446714470783437829037,
19871836214837460419845806980869387567383718044439891735114283113359312279540,
20871081766843466343749609089986071784031203517506781251203251608363835140622,
5100105771517691442278432864090229416166996183792075307747582375962855820797,
8777887112076272395250620301071581171386440850451972412060638225741125310886,
5300440870136391278944213332144327695659161151625757537632832724102670898756,
1205448543652932944633962232545707633928124666868453915721030884663332604536,
5542499997310181530432302492142574333860449305424174466698068685590909336771,
11028094245762332275225364962905938096659249161369092798505554939952525894293,
19187314764836593118404597958543112407224947638377479622725713735224279297009,
17047263688548829001253658727764731047114098556534482052135734487985276987385,
19914849528178967155534624144358541535306360577227460456855821557421213606310,
2929658084700714257515872921366736697080475676508114973627124569375444665664,
15092262360719700162343163278648422751610766427236295023221516498310468956361,
21578580340755653236050830649990190843552802306886938815497471545814130084980,
1258781501221760320019859066036073675029057285507345332959539295621677296991,
3819598418157732134449049289585680301176983019643974929528867686268702720163,
8653175945487997845203439345797943132543211416447757110963967501177317426221,
6614652990340435611114076169697104582524566019034036680161902142028967568142,
19212515502973904821995111796203064175854996071497099383090983975618035391558,
18664315914479294273286016871365663486061896605232511201418576829062292269769,
11498264615058604317482574216318586415670903094838791165247179252175768794889,
10814026414212439999107945133852431304483604215416531759535467355316227331774,
17566185590731088197064706533119299946752127014428399631467913813769853431107,
14016139747289624978792446847000951708158212463304817001882956166752906714332,
8242601581342441750402731523736202888792436665415852106196418942315563860366,
9244680976345080074252591214216060854998619670381671198295645618515047080988,
12216779172735125538689875667307129262237123728082657485828359100719208190116,
10702811721859145441471328511968332847175733707711670171718794132331147396634,
6479667912792222539919362076122453947926362746906450079329453150607427372979,
15117544653571553820496948522381772148324367479772362833334593000535648316185,
6842203153996907264167856337497139692895299874139131328642472698663046726780,
12732823292801537626009139514048596316076834307941224506504666470961250728055,
6936272626871035740815028148058841877090860312517423346335878088297448888663,
17297554111853491139852678417579991271009602631577069694853813331124433680030,
16641596134749940573104316021365063031319260205559553673368334842484345864859,
7400481189785154329569470986896455371037813715804007747228648863919991399081,
2273205422216987330510475127669563545720586464429614439716564154166712854048,
15162538063742142685306302282127534305212832649282186184583465569986719234456,
5628039096440332922248578319648483863204530861778160259559031331287721255522,
16085392195894691829567913404182676871326863890140775376809129785155092531260,
14227467863135365427954093998621993651369686288941275436795622973781503444257,
18224457394066545825553407391290108485121649197258948320896164404518684305122,
274945154732293792784580363548970818611304339008964723447672490026510689427,
11050822248291117548220126630860474473945266276626263036056336623671308219529,
2119542016932434047340813757208803962484943912710204325088879681995922344971,
0
];
var t;
signal t2[nrounds];
signal t4[nrounds];
signal xL[nrounds-1];
signal xR[nrounds-1];
for (var i=0; i<nrounds; i++) {
t = (i==0) ? k+xL_in : k + xL[i-1] + c[i];
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];
} else {
xR_out <== xR[i-1] + t4[i]*t;
xL_out <== xL[i-1];
}
}
}

View File

@@ -0,0 +1,141 @@
/*
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/>.
*/
/*
Source: https://en.wikipedia.org/wiki/Montgomery_curve
1 + y 1 + y
[u, v] = [ ------- , ---------- ]
1 - y (1 - y)x
*/
template Edwards2Montgomery() {
signal input in[2];
signal output out[2];
out[0] <-- (1 + in[1]) / (1 - in[1]);
out[1] <-- out[0] / in[0];
out[0] * (1-in[1]) === (1 + in[1]);
out[1] * in[0] === out[0];
}
/*
u u - 1
[x, y] = [ ---, ------- ]
v u + 1
*/
template Montgomery2Edwards() {
signal input in[2];
signal output out[2];
out[0] <-- in[0] / in[1];
out[1] <-- (in[0] - 1) / (in[0] + 1);
out[0] * in[1] === in[0];
out[1] * (in[0] + 1) === in[0] - 1;
}
/*
x2 - x1
lamda = ---------
y2 - y1
x3 + A + x1 + x2
x3 = B * lamda^2 - A - x1 -x2 => lamda^2 = ------------------
B
y3 = (2*x1 + x2 + A)*lamda - B*lamda^3 - y1 =>
=> y3 = lamda * ( 2*x1 + x2 + A - x3 - A - x1 - x2) - y1 =>
=> y3 = lamda * ( x1 - x3 ) - y1
----------
y2 - y1
lamda = ---------
x2 - x1
x3 = B * lamda^2 - A - x1 -x2
y3 = lamda * ( x1 - x3 ) - y1
*/
template MontgomeryAdd() {
signal input in1[2];
signal input in2[2];
signal output out[2];
var a = 168700;
var d = 168696;
var A = (2 * (a + d)) / (a - d);
var B = 4 / (a - d);
signal lamda;
lamda <-- (in2[1] - in1[1]) / (in2[0] - in1[0]);
lamda * (in2[0] - in1[0]) === (in2[1] - in1[1]);
out[0] <== B*lamda*lamda - A - in1[0] -in2[0];
out[1] <== lamda * (in1[0] - out[0]) - in1[1];
}
/*
x1_2 = x1*x1
3*x1_2 + 2*A*x1 + 1
lamda = ---------------------
2*B*y1
x3 = B * lamda^2 - A - x1 -x1
y3 = lamda * ( x1 - x3 ) - y1
*/
template MontgomeryDouble() {
signal input in[2];
signal output out[2];
var a = 168700;
var d = 168696;
var A = (2 * (a + d)) / (a - d);
var B = 4 / (a - d);
signal lamda;
signal x1_2;
x1_2 <== in[0] * in[0];
lamda <-- (3*x1_2 + 2*A*in[0] + 1 ) / (2*B*in[1]);
lamda * (2*B*in[1]) === (3*x1_2 + 2*A*in[0] + 1 );
out[0] <== B*lamda*lamda - A - 2*in[0];
out[1] <== lamda * (in[0] - out[0]) - in[1];
}

View File

@@ -0,0 +1,113 @@
/*
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/>.
*/
/*
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/>.
*/
// --> Assignation without constraint
// <-- Assignation without constraint
// === Constraint
// <== Assignation with constraint
// ==> Assignation with constraint
// All variables are members of the field F[p]
// https://github.com/zcash-hackworks/sapling-crypto
// https://github.com/ebfull/bellman
/*
function log2(a) {
if (a==0) {
return 0;
}
let n = 1;
let r = 1;
while (n<a) {
r++;
n *= 2;
}
return r;
}
*/
template EscalarProduct(w) {
signal input in1[w];
signal input in2[w];
signal output out;
signal aux[w];
var lc = 0;
for (var i=0; i<w; i++) {
aux[i] <== in1[i]*in2[i];
lc = lc + aux[i];
}
out <== lc;
}
template Decoder(w) {
signal input inp;
signal output out[w];
signal output success;
var lc=0;
for (var i=0; i<w; i++) {
out[i] <-- (inp == i) ? 1 : 0;
out[i] * (inp-i) === 0;
lc = lc + out[i];
}
lc ==> success;
success * (success -1) === 0;
}
template Multiplexer(wIn, nIn) {
signal input inp[nIn][wIn];
signal input sel;
signal output out[wIn];
component dec = Decoder(nIn);
component ep[wIn];
for (var k=0; k<wIn; k++) {
ep[k] = EscalarProduct(nIn);
}
sel ==> dec.inp;
for (var j=0; j<wIn; j++) {
for (var k=0; k<nIn; k++) {
inp[k][j] ==> ep[j].in1[k];
dec.out[k] ==> ep[j].in2[k];
}
ep[j].out ==> out[j];
}
dec.success === 1;
}

View File

@@ -0,0 +1,47 @@
/*
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/>.
*/
template MultiMux1(n) {
signal input c[n][2]; // Constants
signal input s; // Selector
signal output out[n];
for (var i=0; i<n; i++) {
out[i] <== (c[i][1] - c[i][0])*s + c[i][0];
}
}
template Mux1() {
var i;
signal input c[2]; // Constants
signal input s; // Selector
signal output out;
component mux = MultiMux1(1);
for (i=0; i<2; i++) {
mux.c[0][i] <== c[i];
}
s ==> mux.s;
mux.out[0] ==> out;
}

View File

@@ -0,0 +1,62 @@
/*
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/>.
*/
template MultiMux2(n) {
signal input c[n][4]; // Constants
signal input s[2]; // Selector
signal output out[n];
signal a10[n];
signal a1[n];
signal a0[n];
signal a[n];
signal s10;
s10 <== s[1] * s[0];
for (var i=0; i<n; i++) {
a10[i] <== ( c[i][ 3]-c[i][ 2]-c[i][ 1]+c[i][ 0] ) * s10;
a1[i] <== ( c[i][ 2]-c[i][ 0] ) * s[1];
a0[i] <== ( c[i][ 1]-c[i][ 0] ) * s[0];
a[i] <== ( c[i][ 0] )
out[i] <== ( a10[i] + a1[i] + a0[i] + a[i] );
}
}
template Mux2() {
var i;
signal input c[4]; // Constants
signal input s[2]; // Selector
signal output out;
component mux = MultiMux2(1);
for (i=0; i<4; i++) {
mux.c[0][i] <== c[i];
}
for (i=0; i<2; i++) {
s[i] ==> mux.s[i];
}
mux.out[0] ==> out;
}

View File

@@ -0,0 +1,74 @@
/*
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/>.
*/
template MultiMux3(n) {
signal input c[n][8]; // Constants
signal input s[3]; // Selector
signal output out[n];
signal a210[n];
signal a21[n];
signal a20[n];
signal a2[n];
signal a10[n];
signal a1[n];
signal a0[n];
signal a[n];
// 4 constrains for the intermediary variables
signal s10;
s10 <== s[1] * s[0];
for (var i=0; i<n; i++) {
a210[i] <== ( c[i][ 7]-c[i][ 6]-c[i][ 5]+c[i][ 4] - c[i][ 3]+c[i][ 2]+c[i][ 1]-c[i][ 0] ) * s10;
a21[i] <== ( c[i][ 6]-c[i][ 4]-c[i][ 2]+c[i][ 0] ) * s[1];
a20[i] <== ( c[i][ 5]-c[i][ 4]-c[i][ 1]+c[i][ 0] ) * s[0];
a2[i] <== ( c[i][ 4]-c[i][ 0] );
a10[i] <== ( c[i][ 3]-c[i][ 2]-c[i][ 1]+c[i][ 0] ) * s10;
a1[i] <== ( c[i][ 2]-c[i][ 0] ) * s[1];
a0[i] <== ( c[i][ 1]-c[i][ 0] ) * s[0];
a[i] <== ( c[i][ 0] )
out[i] <== ( a210[i] + a21[i] + a20[i] + a2[i] ) * s[2] +
( a10[i] + a1[i] + a0[i] + a[i] );
}
}
template Mux3() {
var i;
signal input c[8]; // Constants
signal input s[3]; // Selector
signal output out;
component mux = MultiMux3(1);
for (i=0; i<8; i++) {
mux.c[0][i] <== c[i];
}
for (i=0; i<3; i++) {
s[i] ==> mux.s[i];
}
mux.out[0] ==> out;
}

View File

@@ -0,0 +1,118 @@
/*
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/>.
*/
template MultiMux4(n) {
signal input c[n][16]; // Constants
signal input s[4]; // Selector
signal output out[n];
signal a3210[n];
signal a321[n];
signal a320[n];
signal a310[n];
signal a32[n];
signal a31[n];
signal a30[n];
signal a3[n];
signal a210[n];
signal a21[n];
signal a20[n];
signal a10[n];
signal a2[n];
signal a1[n];
signal a0[n];
signal a[n];
// 4 constrains for the intermediary variables
signal s10;
s10 <== s[1] * s[0];
signal s20;
s20 <== s[2] * s[0];
signal s21;
s21 <== s[2] * s[1];
signal s210;
s210 <== s21 * s[0];
for (var i=0; i<n; i++) {
a3210[i] <== ( c[i][15]-c[i][14]-c[i][13]+c[i][12] - c[i][11]+c[i][10]+c[i][ 9]-c[i][ 8]
-c[i][ 7]+c[i][ 6]+c[i][ 5]-c[i][ 4] + c[i][ 3]-c[i][ 2]-c[i][ 1]+c[i][ 0] ) * s210;
a321[i] <== ( c[i][14]-c[i][12]-c[i][10]+c[i][ 8] - c[i][ 6]+c[i][ 4]+c[i][ 2]-c[i][ 0] ) * s21;
a320[i] <== ( c[i][13]-c[i][12]-c[i][ 9]+c[i][ 8] - c[i][ 5]+c[i][ 4]+c[i][ 1]-c[i][ 0] ) * s20;
a310[i] <== ( c[i][11]-c[i][10]-c[i][ 9]+c[i][ 8] - c[i][ 3]+c[i][ 2]+c[i][ 1]-c[i][ 0] ) * s10;
a32[i] <== ( c[i][12]-c[i][ 8]-c[i][ 4]+c[i][ 0] ) * s[2];
a31[i] <== ( c[i][10]-c[i][ 8]-c[i][ 2]+c[i][ 0] ) * s[1];
a30[i] <== ( c[i][ 9]-c[i][ 8]-c[i][ 1]+c[i][ 0] ) * s[0];
a3[i] <== ( c[i][ 8]-c[i][ 0] );
a210[i] <== ( c[i][ 7]-c[i][ 6]-c[i][ 5]+c[i][ 4] - c[i][ 3]+c[i][ 2]+c[i][ 1]-c[i][ 0] ) * s210;
a21[i] <== ( c[i][ 6]-c[i][ 4]-c[i][ 2]+c[i][ 0] ) * s21;
a20[i] <== ( c[i][ 5]-c[i][ 4]-c[i][ 1]+c[i][ 0] ) * s20;
a10[i] <== ( c[i][ 3]-c[i][ 2]-c[i][ 1]+c[i][ 0] ) * s10;
a2[i] <== ( c[i][ 4]-c[i][ 0] ) * s[2];
a1[i] <== ( c[i][ 2]-c[i][ 0] ) * s[1];
a0[i] <== ( c[i][ 1]-c[i][ 0] ) * s[0];
a[i] <== ( c[i][ 0] )
out[i] <== ( a3210[i] + a321[i] + a320[i] + a310[i] + a32[i] + a31[i] + a30[i] + a3[i] ) * s[3] +
( a210[i] + a21[i] + a20[i] + a10[i] + a2[i] + a1[i] + a0[i] + a[i] );
/*
out[i] <== ( s210 * ( c[i][15]-c[i][14]-c[i][13]+c[i][12] - c[i][11]+c[i][10]+c[i][ 9]-c[i][ 8]
-c[i][ 7]+c[i][ 6]+c[i][ 5]-c[i][ 4] + c[i][ 3]-c[i][ 2]-c[i][ 1]+c[i][ 0] ) +
s21 * ( c[i][14]-c[i][12]-c[i][10]+c[i][ 8] - c[i][ 6]+c[i][ 4]+c[i][ 2]-c[i][ 0] ) +
s20 * ( c[i][13]-c[i][12]-c[i][ 9]+c[i][ 8] - c[i][ 5]+c[i][ 4]+c[i][ 1]-c[i][ 0] ) +
s10 * ( c[i][11]-c[i][10]-c[i][ 9]+c[i][ 8] - c[i][ 3]+c[i][ 2]+c[i][ 1]-c[i][ 0] ) +
s[2] * ( c[i][12]-c[i][ 8]-c[i][ 4]+c[i][ 0] ) +
s[1] * ( c[i][10]-c[i][ 8]-c[i][ 2]+c[i][ 0] ) +
s[0] * ( c[i][ 9]-c[i][ 8]-c[i][ 1]+c[i][ 0] ) +
( c[i][ 8]-c[i][ 0] ) ) * s[3] +
( s210 * ( c[i][ 7]-c[i][ 6]-c[i][ 5]+c[i][ 4] - c[i][ 3]+c[i][ 2]+c[i][ 1]-c[i][ 0] ) +
s21 * ( c[i][ 6]-c[i][ 4]-c[i][ 2]+c[i][ 0] ) +
s20 * ( c[i][ 5]-c[i][ 4]-c[i][ 1]+c[i][ 0] ) +
s10 * ( c[i][ 3]-c[i][ 2]-c[i][ 1]+c[i][ 0] ) +
s[2] * ( c[i][ 4]-c[i][ 0] ) +
s[1] * ( c[i][ 2]-c[i][ 0] ) +
s[0] * ( c[i][ 1]-c[i][ 0] ) +
( c[i][ 0] ));
*/
}
}
template Mux4() {
var i;
signal input c[16]; // Constants
signal input s[4]; // Selector
signal output out;
component mux = MultiMux4(1);
for (i=0; i<16; i++) {
mux.c[0][i] <== c[i];
}
for (i=0; i<4; i++) {
s[i] ==> mux.s[i];
}
mux.out[0] ==> out;
}

View File

@@ -0,0 +1,255 @@
/*
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 "montgomery.circom";
include "mux3.circom";
include "babyjub.circom";
template Window4() {
signal input in[4];
signal input base[2];
signal output out[2];
signal output out8[2]; // Returns 8*Base (To be linked)
component mux = MultiMux3(2);
mux.s[0] <== in[0];
mux.s[1] <== in[1];
mux.s[2] <== in[2];
component dbl2 = MontgomeryDouble();
component adr3 = MontgomeryAdd();
component adr4 = MontgomeryAdd();
component adr5 = MontgomeryAdd();
component adr6 = MontgomeryAdd();
component adr7 = MontgomeryAdd();
component adr8 = MontgomeryAdd();
// in[0] -> 1*BASE
mux.c[0][0] <== base[0];
mux.c[1][0] <== base[1];
// in[1] -> 2*BASE
dbl2.in[0] <== base[0];
dbl2.in[1] <== base[1];
mux.c[0][1] <== dbl2.out[0];
mux.c[1][1] <== dbl2.out[1];
// in[2] -> 3*BASE
adr3.in1[0] <== base[0];
adr3.in1[1] <== base[1];
adr3.in2[0] <== dbl2.out[0];
adr3.in2[1] <== dbl2.out[1];
mux.c[0][2] <== adr3.out[0];
mux.c[1][2] <== adr3.out[1];
// in[3] -> 4*BASE
adr4.in1[0] <== base[0];
adr4.in1[1] <== base[1];
adr4.in2[0] <== adr3.out[0];
adr4.in2[1] <== adr3.out[1];
mux.c[0][3] <== adr4.out[0];
mux.c[1][3] <== adr4.out[1];
// in[4] -> 5*BASE
adr5.in1[0] <== base[0];
adr5.in1[1] <== base[1];
adr5.in2[0] <== adr4.out[0];
adr5.in2[1] <== adr4.out[1];
mux.c[0][4] <== adr5.out[0];
mux.c[1][4] <== adr5.out[1];
// in[5] -> 6*BASE
adr6.in1[0] <== base[0];
adr6.in1[1] <== base[1];
adr6.in2[0] <== adr5.out[0];
adr6.in2[1] <== adr5.out[1];
mux.c[0][5] <== adr6.out[0];
mux.c[1][5] <== adr6.out[1];
// in[6] -> 7*BASE
adr7.in1[0] <== base[0];
adr7.in1[1] <== base[1];
adr7.in2[0] <== adr6.out[0];
adr7.in2[1] <== adr6.out[1];
mux.c[0][6] <== adr7.out[0];
mux.c[1][6] <== adr7.out[1];
// in[7] -> 8*BASE
adr8.in1[0] <== base[0];
adr8.in1[1] <== base[1];
adr8.in2[0] <== adr7.out[0];
adr8.in2[1] <== adr7.out[1];
mux.c[0][7] <== adr8.out[0];
mux.c[1][7] <== adr8.out[1];
out8[0] <== adr8.out[0];
out8[1] <== adr8.out[1];
out[0] <== mux.out[0];
out[1] <== - mux.out[1]*2*in[3] + mux.out[1]; // Negate y if in[3] is one
}
template Segment(nWindows) {
signal input in[nWindows*4];
signal input base[2];
signal output out[2];
var i;
var j;
// Convert the base to montgomery
component e2m = Edwards2Montgomery();
e2m.in[0] <== base[0];
e2m.in[1] <== base[1];
component windows[nWindows];
component doublers1[nWindows-1];
component doublers2[nWindows-1];
component adders[nWindows-1];
for (i=0; i<nWindows; i++) {
windows[i] = Window4();
if (i==0) {
windows[i].base[0] <== e2m.out[0];
windows[i].base[1] <== e2m.out[1];
} else {
doublers1[i-1] = MontgomeryDouble();
doublers2[i-1] = MontgomeryDouble();
doublers1[i-1].in[0] <== windows[i-1].out8[0];
doublers1[i-1].in[1] <== windows[i-1].out8[1];
doublers2[i-1].in[0] <== doublers1[i-1].out[0];
doublers2[i-1].in[1] <== doublers1[i-1].out[1];
windows[i].base[0] <== doublers2[i-1].out[0];
windows[i].base[1] <== doublers2[i-1].out[1];
adders[i-1] = MontgomeryAdd();
if (i==1) {
adders[i-1].in1[0] <== windows[0].out[0];
adders[i-1].in1[1] <== windows[0].out[1];
} else {
adders[i-1].in1[0] <== adders[i-2].out[0];
adders[i-1].in1[1] <== adders[i-2].out[1];
}
adders[i-1].in2[0] <== windows[i].out[0];
adders[i-1].in2[1] <== windows[i].out[1];
}
for (j=0; j<4; j++) {
windows[i].in[j] <== in[4*i+j];
}
}
component m2e = Montgomery2Edwards();
if (nWindows > 1) {
m2e.in[0] <== adders[nWindows-2].out[0];
m2e.in[1] <== adders[nWindows-2].out[1];
} else {
m2e.in[0] <== windows[0].out[0];
m2e.in[1] <== windows[0].out[1];
}
out[0] <== m2e.out[0];
out[1] <== m2e.out[1];
}
template Pedersen(n) {
signal input in[n];
signal output out[2];
var BASE = [
[10457101036533406547632367118273992217979173478358440826365724437999023779287,19824078218392094440610104313265183977899662750282163392862422243483260492317],
[2671756056509184035029146175565761955751135805354291559563293617232983272177,2663205510731142763556352975002641716101654201788071096152948830924149045094],
[5802099305472655231388284418920769829666717045250560929368476121199858275951,5980429700218124965372158798884772646841287887664001482443826541541529227896],
[7107336197374528537877327281242680114152313102022415488494307685842428166594,2857869773864086953506483169737724679646433914307247183624878062391496185654],
[20265828622013100949498132415626198973119240347465898028410217039057588424236,1160461593266035632937973507065134938065359936056410650153315956301179689506],
[1487999857809287756929114517587739322941449154962237464737694709326309567994,14017256862867289575056460215526364897734808720610101650676790868051368668003],
[14618644331049802168996997831720384953259095788558646464435263343433563860015,13115243279999696210147231297848654998887864576952244320558158620692603342236],
[6814338563135591367010655964669793483652536871717891893032616415581401894627,13660303521961041205824633772157003587453809761793065294055279768121314853695],
[3571615583211663069428808372184817973703476260057504149923239576077102575715,11981351099832644138306422070127357074117642951423551606012551622164230222506],
[18597552580465440374022635246985743886550544261632147935254624835147509493269,6753322320275422086923032033899357299485124665258735666995435957890214041481]
]
var nSegments = ((n-1)\200)+1;
component segments[nSegments];
var i;
var j;
var nBits;
var nWindows;
for (i=0; i<nSegments; i++) {
nBits = (i == (nSegments-1)) ? n - (nSegments-1)*200 : 200;
nWindows = ((nBits - 1)\4)+1;
segments[i] = Segment(nWindows);
segments[i].base[0] <== BASE[i][0];
segments[i].base[1] <== BASE[i][1];
for (j = 0; j<nBits; j++) {
segments[i].in[j] <== in[i*200+j];
}
// Fill padding bits
for (j = nBits; j < nWindows*4; j++) {
segments[i].in[j] <== 0;
}
}
component adders[nSegments-1];
for (i=0; i<nSegments-1; i++) {
adders[i] = BabyAdd();
if (i==0) {
adders[i].x1 <== segments[0].out[0];
adders[i].y1 <== segments[0].out[1];
adders[i].x2 <== segments[1].out[0];
adders[i].y2 <== segments[1].out[1];
} else {
adders[i].x1 <== adders[i-1].xout;
adders[i].y1 <== adders[i-1].yout;
adders[i].x2 <== segments[i+1].out[0];
adders[i].y2 <== segments[i+1].out[1];
}
}
/*
coponent packPoint = PackPoint();
if (nSegments>1) {
packPoint.in[0] <== adders[nSegments-2].xout;
packPoint.in[1] <== adders[nSegments-2].yout;
} else {
packPoint.in[0] <== segments[0].out[0];
packPoint.in[1] <== segments[0].out[1];
}
out[0] <== packPoint.out[0];
out[1] <== packPoint.out[1];
*/
if (nSegments>1) {
out[0] <== adders[nSegments-2].xout;
out[1] <== adders[nSegments-2].yout;
} else {
out[0] <== segments[0].out[0];
out[1] <== segments[0].out[1];
}
}

View File

@@ -0,0 +1,66 @@
/*
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 "escalarmul.circom";
template Pedersen(n) {
signal input in[n];
signal output out[2];
var nexps = ((n-1) \ 250) + 1;
var nlastbits = n - (nexps-1)*250;
component escalarMuls[nexps];
var PBASE = [
[10457101036533406547632367118273992217979173478358440826365724437999023779287,19824078218392094440610104313265183977899662750282163392862422243483260492317],
[2671756056509184035029146175565761955751135805354291559563293617232983272177,2663205510731142763556352975002641716101654201788071096152948830924149045094],
[5802099305472655231388284418920769829666717045250560929368476121199858275951,5980429700218124965372158798884772646841287887664001482443826541541529227896],
[7107336197374528537877327281242680114152313102022415488494307685842428166594,2857869773864086953506483169737724679646433914307247183624878062391496185654],
[20265828622013100949498132415626198973119240347465898028410217039057588424236,1160461593266035632937973507065134938065359936056410650153315956301179689506],
[1487999857809287756929114517587739322941449154962237464737694709326309567994,14017256862867289575056460215526364897734808720610101650676790868051368668003],
[14618644331049802168996997831720384953259095788558646464435263343433563860015,13115243279999696210147231297848654998887864576952244320558158620692603342236],
[6814338563135591367010655964669793483652536871717891893032616415581401894627,13660303521961041205824633772157003587453809761793065294055279768121314853695],
[3571615583211663069428808372184817973703476260057504149923239576077102575715,11981351099832644138306422070127357074117642951423551606012551622164230222506],
[18597552580465440374022635246985743886550544261632147935254624835147509493269,6753322320275422086923032033899357299485124665258735666995435957890214041481]
];
var i;
var j;
var nexpbits;
for (i=0; i<nexps; i++) {
nexpbits = (i == nexps-1) ? nlastbits : 250;
escalarMuls[i] = EscalarMul(nexpbits, PBASE[i]);
for (j=0; j<nexpbits; j++) {
escalarMuls[i].in[j] <== in[250*i + j];
}
if (i==0) {
escalarMuls[i].inp[0] <== 0;
escalarMuls[i].inp[1] <== 1;
} else {
escalarMuls[i].inp[0] <== escalarMuls[i-1].out[0];
escalarMuls[i].inp[1] <== escalarMuls[i-1].out[1];
}
}
escalarMuls[nexps-1].out[0] ==> out[0];
escalarMuls[nexps-1].out[1] ==> out[1];
}

View File

@@ -0,0 +1,163 @@
/*
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 "bitify.circom";
include "aliascheck.circom";
include "compconstant.circom";
include "babyjub.circom";
function sqrt(n) {
if (n == 0) {
return 0;
}
// Test that have solution
var res = n ** ((-1) >> 1);
// if (res!=1) assert(false, "SQRT does not exists");
if (res!=1) return 0;
var m = 28;
var c = 19103219067921713944291392827692070036145651957329286315305642004821462161904;
var t = n ** 81540058820840996586704275553141814055101440848469862132140264610111;
var r = n ** ((81540058820840996586704275553141814055101440848469862132140264610111+1)>>1);
var sq;
var i;
var b;
var j;
while ((r != 0)&&(t != 1)) {
sq = t*t;
i = 1;
while (sq!=1) {
i++;
sq = sq*sq;
}
// b = c ^ m-i-1
b = c;
for (j=0; j< m-i-1; j ++) b = b*b;
m = i;
c = b*b;
t = t*c;
r = r*b;
}
if (r > ((-1) >> 1)) {
r = -r;
}
return r;
}
template Bits2Point() {
signal input in[256];
signal output out[2];
}
template Bits2Point_Strict() {
signal input in[256];
signal output out[2];
var i;
// Check aliasing
component aliasCheckY = AliasCheck();
for (i=0; i<254; i++) {
aliasCheckY.in[i] <== in[i];
}
in[254] === 0;
component b2nY = Bits2Num(254);
for (i=0; i<254; i++) {
b2nY.in[i] <== in[i];
}
out[1] <== b2nY.out;
var a = 168700;
var d = 168696;
var y2 = out[1] * out[1];
var x = sqrt( (1-y2)/(a - d*y2) );
if (in[255] == 1) x = -x;
out[0] <-- x;
component babyCheck = BabyCheck();
babyCheck.x <== out[0];
babyCheck.y <== out[1];
component n2bX = Num2Bits(254);
n2bX.in <== out[0];
component aliasCheckX = AliasCheck();
for (i=0; i<254; i++) {
aliasCheckX.in[i] <== n2bX.out[i];
}
component signCalc = CompConstant(10944121435919637611123202872628637544274182200208017171849102093287904247808);
for (i=0; i<254; i++) {
signCalc.in[i] <== n2bX.out[i];
}
signCalc.out === in[255];
}
template Point2Bits() {
signal input in[2];
signal output out[256];
}
template Point2Bits_Strict() {
signal input in[2];
signal output out[256];
var i;
component n2bX = Num2Bits(254);
n2bX.in <== in[0];
component n2bY = Num2Bits(254);
n2bY.in <== in[1];
component aliasCheckX = AliasCheck();
component aliasCheckY = AliasCheck();
for (i=0; i<254; i++) {
aliasCheckX.in[i] <== n2bX.out[i];
aliasCheckY.in[i] <== n2bY.out[i];
}
component signCalc = CompConstant(10944121435919637611123202872628637544274182200208017171849102093287904247808);
for (i=0; i<254; i++) {
signCalc.in[i] <== n2bX.out[i];
}
for (i=0; i<254; i++) {
out[i] <== n2bY.out[i];
}
out[254] <== 0;
out[255] <== signCalc.out;
}

View File

@@ -0,0 +1,203 @@
template Sigma() {
signal input in;
signal output out;
signal in2;
signal in4;
in2 <== in*in;
in4 <== in2*in2;
out <== in4*in;
}
template Ark(t, C) {
signal input in[t];
signal output out[t];
for (var i=0; i<t; i++) {
out[i] <== in[i] + C;
}
}
template Mix(t, M) {
signal input in[t];
signal output out[t];
var lc;
for (var i=0; i<t; i++) {
lc = 0;
for (var j=0; j<t; j++) {
lc = lc + M[i][j]*in[j];
}
out[i] <== lc;
}
}
// var nRoundsF = 8;
// var nRoundsP = 57;
// var t = 6;
template Poseidon(nInputs, t, nRoundsF, nRoundsP) {
var C = [
14397397413755236225575615486459253198602422701513067526754101844196324375522,
10405129301473404666785234951972711717481302463898292859783056520670200613128,
5179144822360023508491245509308555580251733042407187134628755730783052214509,
9132640374240188374542843306219594180154739721841249568925550236430986592615,
20360807315276763881209958738450444293273549928693737723235350358403012458514,
17933600965499023212689924809448543050840131883187652471064418452962948061619,
3636213416533737411392076250708419981662897009810345015164671602334517041153,
2008540005368330234524962342006691994500273283000229509835662097352946198608,
16018407964853379535338740313053768402596521780991140819786560130595652651567,
20653139667070586705378398435856186172195806027708437373983929336015162186471,
17887713874711369695406927657694993484804203950786446055999405564652412116765,
4852706232225925756777361208698488277369799648067343227630786518486608711772,
8969172011633935669771678412400911310465619639756845342775631896478908389850,
20570199545627577691240476121888846460936245025392381957866134167601058684375,
16442329894745639881165035015179028112772410105963688121820543219662832524136,
20060625627350485876280451423010593928172611031611836167979515653463693899374,
16637282689940520290130302519163090147511023430395200895953984829546679599107,
15599196921909732993082127725908821049411366914683565306060493533569088698214,
16894591341213863947423904025624185991098788054337051624251730868231322135455,
1197934381747032348421303489683932612752526046745577259575778515005162320212,
6172482022646932735745595886795230725225293469762393889050804649558459236626,
21004037394166516054140386756510609698837211370585899203851827276330669555417,
15262034989144652068456967541137853724140836132717012646544737680069032573006,
15017690682054366744270630371095785995296470601172793770224691982518041139766,
15159744167842240513848638419303545693472533086570469712794583342699782519832,
11178069035565459212220861899558526502477231302924961773582350246646450941231,
21154888769130549957415912997229564077486639529994598560737238811887296922114,
20162517328110570500010831422938033120419484532231241180224283481905744633719,
2777362604871784250419758188173029886707024739806641263170345377816177052018,
15732290486829619144634131656503993123618032247178179298922551820261215487562,
6024433414579583476444635447152826813568595303270846875177844482142230009826,
17677827682004946431939402157761289497221048154630238117709539216286149983245,
10716307389353583413755237303156291454109852751296156900963208377067748518748,
14925386988604173087143546225719076187055229908444910452781922028996524347508,
8940878636401797005293482068100797531020505636124892198091491586778667442523,
18911747154199663060505302806894425160044925686870165583944475880789706164410,
8821532432394939099312235292271438180996556457308429936910969094255825456935,
20632576502437623790366878538516326728436616723089049415538037018093616927643,
71447649211767888770311304010816315780740050029903404046389165015534756512,
2781996465394730190470582631099299305677291329609718650018200531245670229393,
12441376330954323535872906380510501637773629931719508864016287320488688345525,
2558302139544901035700544058046419714227464650146159803703499681139469546006,
10087036781939179132584550273563255199577525914374285705149349445480649057058,
4267692623754666261749551533667592242661271409704769363166965280715887854739,
4945579503584457514844595640661884835097077318604083061152997449742124905548,
17742335354489274412669987990603079185096280484072783973732137326144230832311,
6266270088302506215402996795500854910256503071464802875821837403486057988208,
2716062168542520412498610856550519519760063668165561277991771577403400784706,
19118392018538203167410421493487769944462015419023083813301166096764262134232,
9386595745626044000666050847309903206827901310677406022353307960932745699524,
9121640807890366356465620448383131419933298563527245687958865317869840082266,
3078975275808111706229899605611544294904276390490742680006005661017864583210,
7157404299437167354719786626667769956233708887934477609633504801472827442743,
14056248655941725362944552761799461694550787028230120190862133165195793034373,
14124396743304355958915937804966111851843703158171757752158388556919187839849,
11851254356749068692552943732920045260402277343008629727465773766468466181076,
9799099446406796696742256539758943483211846559715874347178722060519817626047,
10156146186214948683880719664738535455146137901666656566575307300522957959544,
19908645952733301583346063785055921934459499091029406575311417879963332475861,
11766105336238068471342414351862472329437473380853789942065610694000443387471,
11002137593249972174092192767251572171769044073555430468487809799220351297047,
284136377911685911941431040940403846843630064858778505937392780738953624163,
19448733709802908339787967270452055364068697565906862913410983275341804035680,
14423660424692802524250720264041003098290275890428483723270346403986712981505,
10635360132728137321700090133109897687122647659471659996419791842933639708516
];
var M = [
[
19167410339349846567561662441069598364702008768579734801591448511131028229281,
14183033936038168803360723133013092560869148726790180682363054735190196956789,
9067734253445064890734144122526450279189023719890032859456830213166173619761,
16378664841697311562845443097199265623838619398287411428110917414833007677155,
12968540216479938138647596899147650021419273189336843725176422194136033835172,
3636162562566338420490575570584278737093584021456168183289112789616069756675
],[
17034139127218860091985397764514160131253018178110701196935786874261236172431,
2799255644797227968811798608332314218966179365168250111693473252876996230317,
2482058150180648511543788012634934806465808146786082148795902594096349483974,
16563522740626180338295201738437974404892092704059676533096069531044355099628,
10468644849657689537028565510142839489302836569811003546969773105463051947124,
3328913364598498171733622353010907641674136720305714432354138807013088636408
],[
18985203040268814769637347880759846911264240088034262814847924884273017355969,
8652975463545710606098548415650457376967119951977109072274595329619335974180,
970943815872417895015626519859542525373809485973005165410533315057253476903,
19406667490568134101658669326517700199745817783746545889094238643063688871948,
17049854690034965250221386317058877242629221002521630573756355118745574274967,
4964394613021008685803675656098849539153699842663541444414978877928878266244
],[
19025623051770008118343718096455821045904242602531062247152770448380880817517,
9077319817220936628089890431129759976815127354480867310384708941479362824016,
4770370314098695913091200576539533727214143013236894216582648993741910829490,
4298564056297802123194408918029088169104276109138370115401819933600955259473,
6905514380186323693285869145872115273350947784558995755916362330070690839131,
4783343257810358393326889022942241108539824540285247795235499223017138301952
],[
16205238342129310687768799056463408647672389183328001070715567975181364448609,
8303849270045876854140023508764676765932043944545416856530551331270859502246,
20218246699596954048529384569730026273241102596326201163062133863539137060414,
1712845821388089905746651754894206522004527237615042226559791118162382909269,
13001155522144542028910638547179410124467185319212645031214919884423841839406,
16037892369576300958623292723740289861626299352695838577330319504984091062115
],[
15162889384227198851506890526431746552868519326873025085114621698588781611738,
13272957914179340594010910867091459756043436017766464331915862093201960540910,
9416416589114508529880440146952102328470363729880726115521103179442988482948,
8035240799672199706102747147502951589635001418759394863664434079699838251138,
21642389080762222565487157652540372010968704000567605990102641816691459811717,
20261355950827657195644012399234591122288573679402601053407151083849785332516
]
];
signal input inputs[nInputs];
signal output out;
component ark[nRoundsF + nRoundsP];
component sigmaF[nRoundsF][t];
component sigmaP[nRoundsP];
component mix[nRoundsF + nRoundsP];
var k;
for (var i=0; i<(nRoundsF + nRoundsP); i++) {
ark[i] = Ark(t, C[i]);
mix[i] = Mix(t, M);
for (var j=0; j<t; j++) {
if (i==0) {
if (j<nInputs) {
ark[i].in[j] <== inputs[j];
} else {
ark[i].in[j] <== 0;
}
} else {
ark[i].in[j] <== mix[i-1].out[j];
}
}
if ((i<(nRoundsF/2)) || (i>= (nRoundsP + nRoundsF/2))) {
k= i<nRoundsF/2 ? i : (i-nRoundsP);
for (var j=0; j<t; j++) {
sigmaF[k][j] = Sigma();
sigmaF[k][j].in <== ark[i].out[j];
mix[i].in[j] <== sigmaF[k][j].out;
}
} else {
k= i-nRoundsF/2;
sigmaP[k] = Sigma();
sigmaP[k].in <== ark[i].out[0];
mix[i].in[0] <== sigmaP[k].out;
for (var j=1; j<t; j++) {
mix[i].in[j] <== ark[i].out[j];
}
}
}
out <== mix[nRoundsF + nRoundsP -1].out[0];
}

View File

@@ -0,0 +1,46 @@
/*
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/>.
*/
/* Ch
000 0
001 1
010 0
011 1
100 0
101 0
110 1
111 1
out = a&b ^ (!a)&c =>
out = a*(b-c) + c
*/
template Ch(n) {
signal input a[n];
signal input b[n];
signal input c[n];
signal output out[n];
for (var k=0; k<n; k++) {
out[k] <== a[k] * (b[k]-c[k]) + c[k];
}
}

View File

@@ -0,0 +1,52 @@
/*
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/>.
*/
template H(x) {
signal output out[32];
var c = [0x6a09e667,
0xbb67ae85,
0x3c6ef372,
0xa54ff53a,
0x510e527f,
0x9b05688c,
0x1f83d9ab,
0x5be0cd19];
for (var i=0; i<32; i++) {
out[i] <== (c[x] >> i) & 1;
}
}
template K(x) {
signal output out[32];
var c = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
];
for (var i=0; i<32; i++) {
out[i] <== (c[x] >> i) & 1;
}
}

View File

@@ -0,0 +1,34 @@
/*
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 "sha256_2.jaz";
template Main() {
signal private input a;
signal private input b;
signal output out;
component sha256_2 = SHA256_2();
sha256_2.a <== a;
sha256_2.b <== a;
out <== sha256_2.out;
}
component main = Main();

View File

@@ -0,0 +1,44 @@
/*
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/>.
*/
/* Maj function for sha256
out = a&b ^ a&c ^ b&c =>
out = a*b + a*c + b*c - 2*a*b*c =>
out = a*( b + c - 2*b*c ) + b*c =>
mid = b*c
out = a*( b + c - 2*mid ) + mid
*/
template Maj(n) {
signal input a[n];
signal input b[n];
signal input c[n];
signal output out[n];
signal mid[n];
for (var k=0; k<n; k++) {
mid[k] <== b[k]*c[k];
out[k] <== a[k] * (b[k]+c[k]-2*mid[k]) + mid[k];
}
}

View File

@@ -0,0 +1,27 @@
/*
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/>.
*/
template RotR(n, r) {
signal input in[n];
signal output out[n];
for (var i=0; i<n; i++) {
out[i] <== in[ (i+r)%n ];
}
}

View File

@@ -0,0 +1,67 @@
/*
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 "sha256compression.circom";
include "../bitify.circom"
template Sha256_2() {
signal input a;
signal input b;
signal output out;
component bits2num = Bits2Num(216);
component num2bits[2];
num2bits[0] = Num2Bits(216);
num2bits[1] = Num2Bits(216);
num2bits[0].in <== a;
num2bits[1].in <== b;
component sha256compression = Sha256compression() ;
var i;
for (i=0; i<216; i++) {
sha256compression.inp[i] <== num2bits[0].out[215-i];
sha256compression.inp[i+216] <== num2bits[1].out[215-i];
}
sha256compression.inp[432] <== 1;
for (i=433; i<503; i++) {
sha256compression.inp[i] <== 0;
}
sha256compression.inp[503] <== 1;
sha256compression.inp[504] <== 1;
sha256compression.inp[505] <== 0;
sha256compression.inp[506] <== 1;
sha256compression.inp[507] <== 1;
sha256compression.inp[508] <== 0;
sha256compression.inp[509] <== 0;
sha256compression.inp[510] <== 0;
sha256compression.inp[511] <== 0;
for (i=0; i<216; i++) {
bits2num.in[i] <== sha256compression.out[255-i];
}
out <== bits2num.out;
}

View File

@@ -0,0 +1,164 @@
/*
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 "constants.circom";
include "t1.circom";
include "t2.circom";
include "../binsum.circom";
include "sigmaplus.circom";
template Sha256compression() {
signal input inp[512];
signal output out[256];
signal a[65][32];
signal b[65][32];
signal c[65][32];
signal d[65][32];
signal e[65][32];
signal f[65][32];
signal g[65][32];
signal h[65][32];
signal w[64][32];
var i;
component sigmaPlus[48];
for (i=0; i<48; i++) sigmaPlus[i] = SigmaPlus();
component ct_k[64];
for (i=0; i<64; i++) ct_k[i] = K(i);
component ha0 = H(0);
component hb0 = H(1);
component hc0 = H(2);
component hd0 = H(3);
component he0 = H(4);
component hf0 = H(5);
component hg0 = H(6);
component hh0 = H(7);
component t1[64];
for (i=0; i<64; i++) t1[i] = T1();
component t2[64];
for (i=0; i<64; i++) t2[i] = T2();
component suma[64];
for (i=0; i<64; i++) suma[i] = BinSum(32, 2);
component sume[64];
for (i=0; i<64; i++) sume[i] = BinSum(32, 2);
component fsum[8];
for (i=0; i<8; i++) fsum[i] = BinSum(32, 2);
var k;
var t;
for (t=0; t<64; t++) {
if (t<16) {
for (k=0; k<32; k++) {
w[t][k] <== inp[t*32+31-k];
}
} else {
for (k=0; k<32; k++) {
sigmaPlus[t-16].in2[k] <== w[t-2][k];
sigmaPlus[t-16].in7[k] <== w[t-7][k];
sigmaPlus[t-16].in15[k] <== w[t-15][k];
sigmaPlus[t-16].in16[k] <== w[t-16][k];
w[t][k] <== sigmaPlus[t-16].out[k];
}
}
}
for (k=0; k<32; k++ ) {
a[0][k] <== ha0.out[k]
b[0][k] <== hb0.out[k]
c[0][k] <== hc0.out[k]
d[0][k] <== hd0.out[k]
e[0][k] <== he0.out[k]
f[0][k] <== hf0.out[k]
g[0][k] <== hg0.out[k]
h[0][k] <== hh0.out[k]
}
for (t = 0; t<64; t++) {
for (k=0; k<32; k++) {
t1[t].h[k] <== h[t][k];
t1[t].e[k] <== e[t][k];
t1[t].f[k] <== f[t][k];
t1[t].g[k] <== g[t][k];
t1[t].k[k] <== ct_k[t].out[k];
t1[t].w[k] <== w[t][k];
t2[t].a[k] <== a[t][k];
t2[t].b[k] <== b[t][k];
t2[t].c[k] <== c[t][k];
}
for (k=0; k<32; k++) {
sume[t].in[0][k] <== d[t][k];
sume[t].in[1][k] <== t1[t].out[k];
suma[t].in[0][k] <== t1[t].out[k];
suma[t].in[1][k] <== t2[t].out[k];
}
for (k=0; k<32; k++) {
h[t+1][k] <== g[t][k];
g[t+1][k] <== f[t][k];
f[t+1][k] <== e[t][k];
e[t+1][k] <== sume[t].out[k];
d[t+1][k] <== c[t][k];
c[t+1][k] <== b[t][k];
b[t+1][k] <== a[t][k];
a[t+1][k] <== suma[t].out[k];
}
}
for (k=0; k<32; k++) {
fsum[0].in[0][k] <== ha0.out[k];
fsum[0].in[1][k] <== a[64][k];
fsum[1].in[0][k] <== hb0.out[k];
fsum[1].in[1][k] <== b[64][k];
fsum[2].in[0][k] <== hc0.out[k];
fsum[2].in[1][k] <== c[64][k];
fsum[3].in[0][k] <== hd0.out[k];
fsum[3].in[1][k] <== d[64][k];
fsum[4].in[0][k] <== he0.out[k];
fsum[4].in[1][k] <== e[64][k];
fsum[5].in[0][k] <== hf0.out[k];
fsum[5].in[1][k] <== f[64][k];
fsum[6].in[0][k] <== hg0.out[k];
fsum[6].in[1][k] <== g[64][k];
fsum[7].in[0][k] <== hh0.out[k];
fsum[7].in[1][k] <== h[64][k];
}
for (k=0; k<32; k++) {
out[31-k] <== fsum[0].out[k];
out[32+31-k] <== fsum[1].out[k];
out[64+31-k] <== fsum[2].out[k];
out[96+31-k] <== fsum[3].out[k];
out[128+31-k] <== fsum[4].out[k];
out[160+31-k] <== fsum[5].out[k];
out[192+31-k] <== fsum[6].out[k];
out[224+31-k] <== fsum[7].out[k];
}
}

View File

@@ -0,0 +1,32 @@
/*
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/>.
*/
template ShR(n, r) {
signal input in[n];
signal output out[n];
for (var i=0; i<n; i++) {
if (i+r >= n) {
out[i] <== 0;
} else {
out[i] <== in[ i+r ];
}
}
}

View File

@@ -0,0 +1,68 @@
/*
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 "xor3.circom";
include "rotate.circom";
include "shift.circom";
template SmallSigma(ra, rb, rc) {
signal input in[32];
signal output out[32];
component xor3 = Xor3(32);
component rota = RotR(32, ra);
component rotb = RotR(32, rb);
component shrc = ShR(32, rc);
for (var k=0; k<32; k++) {
rota.in[k] <== in[k];
rotb.in[k] <== in[k];
shrc.in[k] <== in[k];
xor3.a[k] <== rota.out[k];
xor3.b[k] <== rotb.out[k];
xor3.c[k] <== shrc.out[k];
out[k] <== xor3.out[k];
}
}
template BigSigma(ra, rb, rc) {
signal input in[32];
signal output out[32];
component xor3 = Xor3(32);
component rota = RotR(32, ra);
component rotb = RotR(32, rb);
component rotc = RotR(32, rc);
for (var k=0; k<32; k++) {
rota.in[k] <== in[k];
rotb.in[k] <== in[k];
rotc.in[k] <== in[k];
xor3.a[k] <== rota.out[k];
xor3.b[k] <== rotb.out[k];
xor3.c[k] <== rotc.out[k];
out[k] <== xor3.out[k];
}
}

View File

@@ -0,0 +1,45 @@
/*
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 "../binsum.circom"
include "sigma.circom"
template SigmaPlus() {
signal input in2[32];
signal input in7[32];
signal input in15[32];
signal input in16[32];
signal output out[32];
component sum = BinSum(32, 4);
component sigma1 = SmallSigma(17,19,10);
component sigma0 = SmallSigma(7, 18, 3);
for (var k=0; k<32; k++) {
sigma1.in[k] <== in2[k];
sigma0.in[k] <== in15[k];
sum.in[0][k] <== sigma1.out[k];
sum.in[1][k] <== in7[k];
sum.in[2][k] <== sigma0.out[k];
sum.in[3][k] <== in16[k];
out[k] <== sum.out[k];
}
}

View File

@@ -0,0 +1,52 @@
/*
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 "../binsum.circom";
include "sigma.circom";
include "ch.circom";
template T1() {
signal input h[32];
signal input e[32];
signal input f[32];
signal input g[32];
signal input k[32];
signal input w[32];
signal output out[32];
component sum = BinSum(32, 5);
component ch = Ch(32);
component bigsigma1 = BigSigma(6, 11, 25);
for (var ki=0; ki<32; ki++) {
bigsigma1.in[ki] <== e[ki];
ch.a[ki] <== e[ki];
ch.b[ki] <== f[ki];
ch.c[ki] <== g[ki]
sum.in[0][ki] <== h[ki];
sum.in[1][ki] <== bigsigma1.out[ki];
sum.in[2][ki] <== ch.out[ki];
sum.in[3][ki] <== k[ki];
sum.in[4][ki] <== w[ki];
out[ki] <== sum.out[ki];
}
}

View File

@@ -0,0 +1,47 @@
/*
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 "../binsum.circom";
include "sigma.circom";
include "maj.circom"
template T2() {
signal input a[32];
signal input b[32];
signal input c[32];
signal output out[32];
component sum = BinSum(32, 2);
component bigsigma0 = BigSigma(2, 13, 22);
component maj = Maj(32);
for (var k=0; k<32; k++) {
bigsigma0.in[k] <== a[k];
maj.a[k] <== a[k];
maj.b[k] <== b[k];
maj.c[k] <== c[k];
sum.in[0][k] <== bigsigma0.out[k];
sum.in[1][k] <== maj.out[k];
out[k] <== sum.out[k];
}
}

View File

@@ -0,0 +1,44 @@
/*
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/>.
*/
/* Xor3 function for sha256
out = a ^ b ^ c =>
out = a+b+c - 2*a*b - 2*a*c - 2*b*c + 4*a*b*c =>
out = a*( 1 - 2*b - 2*c + 4*b*c ) + b + c - 2*b*c =>
mid = b*c
out = a*( 1 - 2*b -2*c + 4*mid ) + b + c - 2 * mid
*/
template Xor3(n) {
signal input a[n];
signal input b[n];
signal input c[n];
signal output out[n];
signal mid[n];
for (var k=0; k<n; k++) {
mid[k] <== b[k]*c[k];
out[k] <== a[k] * (1 -2*b[k] -2*c[k] +4*mid[k]) + b[k] + c[k] -2*mid[k];
}
}

View File

@@ -0,0 +1,35 @@
/*
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";
template Sign() {
signal input in[254];
signal output sign;
component comp = CompConstant(10944121435919637611123202872628637544274182200208017171849102093287904247808);
var i;
for (i=0; i<254; i++) {
comp.in[i] <== in[i];
}
sign <== comp.out;
}

View File

@@ -0,0 +1,57 @@
/*
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 "../mimc.circom";
/*
Hash1 = H(1 | key | value)
*/
template SMTHash1() {
signal input key;
signal input value;
signal output out;
component h = MultiMiMC7(2, 91); // Constant
h.in[0] <== key;
h.in[1] <== value;
h.k <== 1;
out <== h.out;
}
/*
This component is used to create the 2 nodes.
Hash2 = H(Hl | Hr)
*/
template SMTHash2() {
signal input L;
signal input R;
signal output out;
component h = MultiMiMC7(2, 91); // Constant
h.in[0] <== L;
h.in[1] <== R;
h.k <== 0;
out <== h.out;
}

View File

@@ -0,0 +1,56 @@
/*
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 "../poseidon.circom";
/*
Hash1 = H(1 | key | value)
*/
template SMTHash1() {
signal input key;
signal input value;
signal output out;
component h = Poseidon(3, 6, 8, 57); // Constant
h.inputs[0] <== key;
h.inputs[1] <== value;
h.inputs[2] <== 1;
out <== h.out;
}
/*
This component is used to create the 2 nodes.
Hash2 = H(Hl | Hr)
*/
template SMTHash2() {
signal input L;
signal input R;
signal output out;
component h = Poseidon(2, 6, 8, 57); // Constant
h.inputs[0] <== L;
h.inputs[1] <== R;
out <== h.out;
}

View File

@@ -0,0 +1,100 @@
/*
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/>.
*/
/*
This component finds the level where the oldInsert is done.
The rules are:
levIns[i] == 1 if its level and all the child levels have a sibling of 0 and
the parent level has a sibling != 0. Considere that the root level always has
a parent with a sibling != 0.
┌──────────────┐
│ │
│ │───▶ levIns[0] <== (1-done[i])
│ │
└──────────────┘
done[0]
done[i-1] <== levIns[i] + done[i]
┌───────────┐ ┌──────────────┐
│ │ │ │
sibling[i-1]───▶│IsZero[i-1]│─▶│ │───▶ levIns[i] <== (1-done[i])*(1-isZero[i-1].out)
│ │ │ │
└───────────┘ └──────────────┘
done[i]
done[n-2] <== levIns[n-1]
┌───────────┐ ┌──────────────┐
│ │ │ │
sibling[n-2]───▶│IsZero[n-2]│─▶│ │────▶ levIns[n-1] <== (1-isZero[n-2].out)
│ │ │ │
└───────────┘ └──────────────┘
┌───────────┐
│ │
sibling[n-1]───▶│IsZero[n-1]│────▶ === 0
│ │
└───────────┘
*/
template SMTLevIns(nLevels) {
signal input enabled;
signal input siblings[nLevels];
signal output levIns[nLevels];
signal done[nLevels-1]; // Indicates if the insLevel has aready been detected.
component isZero[nLevels];
for (var i=0; i<nLevels; i++) {
isZero[i] = IsZero();
isZero[i].in <== siblings[i];
}
// The last level must always have a sibling of 0. If not, then it cannot be inserted.
(isZero[nLevels-1].out - 1) * enabled === 0;
levIns[nLevels-1] <== (1-isZero[nLevels-2].out);
done[nLevels-2] <== levIns[nLevels-1];
for (var i=nLevels-2; i>0; i--) {
levIns[i] <== (1-done[i])*(1-isZero[i-1].out)
done[i-1] <== levIns[i] + done[i];
}
levIns[0] <== (1-done[0]);
}

View File

@@ -0,0 +1,258 @@
/*
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/>.
*/
/***************************************************************************************************
SMTProcessor: Sparse Merkle Tree processor is a component to verify an insert/update/delete elements
into the Sparse Merkle tree.
Insert to an empty leaf
=======================
STATE OLD STATE NEW STATE
===== ========= =========
oldRoot newRoot
▲ ▲
│ │
┌───────┐ ┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓
top │Sibling├────▶┃ Hash ┃◀─┐ │Sibling├────▶┃ Hash ┃◀─┐
└───────┘ ┗━━━━━━━┛ │ └───────┘ ┗━━━━━━━┛ │
│ │
│ │
┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓ ┌───────┐
top ┌─────▶┃ Hash ┃◀──┤Sibling│ ┌─────▶┃ Hash ┃◀──┤Sibling│
│ ┗━━━━━━━┛ └───────┘ │ ┗━━━━━━━┛ └───────┘
│ │
│ │
┌───────┐ ┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓
top │Sibling├──▶┃ Hash ┃◀─────┐ │Sibling├──▶┃ Hash ┃◀─────┐
└───────┘ ┗━━━━━━━┛ │ └───────┘ ┗━━━━━━━┛ │
│ │
│ │
┌────┴────┐ ┌────┴────┐
old0 │ 0 │ │New1Leaf │
└─────────┘ └─────────┘
┏━━━━━━━┓ ┏━━━━━━━┓
na ┃ Hash ┃ ┃ Hash ┃
┗━━━━━━━┛ ┗━━━━━━━┛
┏━━━━━━━┓ ┏━━━━━━━┓
na ┃ Hash ┃ ┃ Hash ┃
┗━━━━━━━┛ ┗━━━━━━━┛
Insert to a used leaf.
=====================
STATE OLD STATE NEW STATE
===== ========= =========
oldRoot newRoot
▲ ▲
│ │
┌───────┐ ┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓
top │Sibling├────▶┃ Hash ┃◀─┐ │Sibling├────▶┃ Hash ┃◀─┐
└───────┘ ┗━━━━━━━┛ │ └───────┘ ┗━━━━━━━┛ │
│ │
│ │
┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓ ┌───────┐
top ┌─────▶┃ Hash ┃◀──┤Sibling│ ┌─────▶┃ Hash ┃◀──┤Sibling│
│ ┗━━━━━━━┛ └───────┘ │ ┗━━━━━━━┛ └───────┘
│ │
│ │
┌───────┐ ┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓
top │Sibling├──▶┃ Hash ┃◀─────┐ │Sibling├──▶┃ Hash ┃◀─────┐
└───────┘ ┗━━━━━━━┛ │ └───────┘ ┗━━━━━━━┛ │
│ │
│ │
┌────┴────┐ ┏━━━┻━━━┓ ┌───────┐
bot │Old1Leaf │ ┌─────▶┃ Hash ┃◀──┼─ 0 │
└─────────┘ │ ┗━━━━━━━┛ └───────┘
┏━━━━━━━┓ ┌───────┐ ┏━━━┻━━━┓
bot ┃ Hash ┃ │ 0 ─┼──▶┃ Hash ┃◀─────┐
┗━━━━━━━┛ └───────┘ ┗━━━━━━━┛ │
┏━━━━━━━┓ ┏━━━┻━━━┓ ┌───────┐
bot ┃ Hash ┃ ┌─────▶┃ Hash ┃◀──│ 0 │
┗━━━━━━━┛ │ ┗━━━━━━━┛ └───────┘
┏━━━━━━━┓ ┌─────────┐ ┏━━━┻━━━┓ ┌─────────┐
new1 ┃ Hash ┃ │Old1Leaf ├──▶┃ Hash ┃◀──│New1Leaf │
┗━━━━━━━┛ └─────────┘ ┗━━━━━━━┛ └─────────┘
┏━━━━━━━┓ ┏━━━━━━━┓
na ┃ Hash ┃ ┃ Hash ┃
┗━━━━━━━┛ ┗━━━━━━━┛
┏━━━━━━━┓ ┏━━━━━━━┓
na ┃ Hash ┃ ┃ Hash ┃
┗━━━━━━━┛ ┗━━━━━━━┛
Fnction
fnc[0] fnc[1]
0 0 NOP
0 1 UPDATE
1 0 INSERT
1 1 DELETE
***************************************************************************************************/
include "../gates.circom";
include "../bitify.circom";
include "../comparators.circom";
include "../switcher.circom";
include "smtlevins.circom";
include "smtprocessorlevel.circom";
include "smtprocessorsm.circom";
include "smthash_poseidon.circom";
template SMTProcessor(nLevels) {
signal input oldRoot;
signal output newRoot;
signal input siblings[nLevels];
signal input oldKey;
signal input oldValue;
signal input isOld0;
signal input newKey;
signal input newValue;
signal input fnc[2];
signal enabled;
enabled <== fnc[0] + fnc[1] - fnc[0]*fnc[1]
component hash1Old = SMTHash1();
hash1Old.key <== oldKey;
hash1Old.value <== oldValue;
component hash1New = SMTHash1();
hash1New.key <== newKey;
hash1New.value <== newValue;
component n2bOld = Num2Bits_strict();
component n2bNew = Num2Bits_strict();
n2bOld.in <== oldKey;
n2bNew.in <== newKey;
component smtLevIns = SMTLevIns(nLevels);
for (var i=0; i<nLevels; i++) smtLevIns.siblings[i] <== siblings[i];
smtLevIns.enabled <== enabled;
component xors[nLevels];
for (var i=0; i<nLevels; i++) {
xors[i] = XOR();
xors[i].a <== n2bOld.out[i];
xors[i].b <== n2bNew.out[i];
}
component sm[nLevels];
for (var i=0; i<nLevels; i++) {
sm[i] = SMTProcessorSM();
if (i==0) {
sm[i].prev_top <== enabled;
sm[i].prev_old0 <== 0;
sm[i].prev_bot <== 0;
sm[i].prev_new1 <== 0;
sm[i].prev_na <== 1-enabled;
sm[i].prev_upd <== 0;
} else {
sm[i].prev_top <== sm[i-1].st_top;
sm[i].prev_old0 <== sm[i-1].st_old0;
sm[i].prev_bot <== sm[i-1].st_bot;
sm[i].prev_new1 <== sm[i-1].st_new1;
sm[i].prev_na <== sm[i-1].st_na;
sm[i].prev_upd <== sm[i-1].st_upd;
}
sm[i].is0 <== isOld0;
sm[i].xor <== xors[i].out;
sm[i].fnc[0] <== fnc[0];
sm[i].fnc[1] <== fnc[1];
sm[i].levIns <== smtLevIns.levIns[i];
}
sm[nLevels-1].st_na + sm[nLevels-1].st_new1 + sm[nLevels-1].st_old0 +sm[nLevels-1].st_upd === 1;
component levels[nLevels];
for (var i=nLevels-1; i != -1; i--) {
levels[i] = SMTProcessorLevel();
levels[i].st_top <== sm[i].st_top;
levels[i].st_old0 <== sm[i].st_old0;
levels[i].st_bot <== sm[i].st_bot;
levels[i].st_new1 <== sm[i].st_new1;
levels[i].st_na <== sm[i].st_na;
levels[i].st_upd <== sm[i].st_upd;
levels[i].sibling <== siblings[i];
levels[i].old1leaf <== hash1Old.out;
levels[i].new1leaf <== hash1New.out;
levels[i].newlrbit <== n2bNew.out[i];
if (i==nLevels-1) {
levels[i].oldChild <== 0;
levels[i].newChild <== 0;
} else {
levels[i].oldChild <== levels[i+1].oldRoot;
levels[i].newChild <== levels[i+1].newRoot;
}
}
component topSwitcher = Switcher();
topSwitcher.sel <== fnc[0]*fnc[1];
topSwitcher.L <== levels[0].oldRoot;
topSwitcher.R <== levels[0].newRoot;
component checkOldInput = ForceEqualIfEnabled();
checkOldInput.enabled <== enabled;
checkOldInput.in[0] <== oldRoot;
checkOldInput.in[1] <== topSwitcher.outL;
newRoot <== enabled * (topSwitcher.outR - oldRoot) + oldRoot;
// topSwitcher.outL === oldRoot*enabled;
// topSwitcher.outR === newRoot*enabled;
// Ckeck keys are equal if updating
component areKeyEquals = IsEqual();
areKeyEquals.in[0] <== oldKey;
areKeyEquals.in[1] <== newKey;
component keysOk = MultiAND(3);
keysOk.in[0] <== 1-fnc[0];
keysOk.in[1] <== fnc[1];
keysOk.in[2] <== 1-areKeyEquals.out;
keysOk.out === 0;
}

View File

@@ -0,0 +1,94 @@
/*
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/>.
*/
/******
SMTProcessorLevel
This circuit has 2 hash
Outputs according to the state.
State oldRoot newRoot
===== ======= =======
top H'(oldChild, sibling) H'(newChild, sibling)
old0 0 new1leaf
bot old1leaf H'(newChild, 0)
new1 old1leaf H'(new1leaf, old1leaf)
na 0 0
upd old1leaf new1leaf
H' is the Hash function with the inputs shifted acordingly.
*****/
template SMTProcessorLevel() {
signal input st_top;
signal input st_old0;
signal input st_bot;
signal input st_new1;
signal input st_na;
signal input st_upd;
signal output oldRoot;
signal output newRoot;
signal input sibling;
signal input old1leaf;
signal input new1leaf;
signal input newlrbit;
signal input oldChild;
signal input newChild;
signal aux[4];
component oldProofHash = SMTHash2();
component newProofHash = SMTHash2();
component oldSwitcher = Switcher();
component newSwitcher = Switcher();
// Old side
oldSwitcher.L <== oldChild;
oldSwitcher.R <== sibling;
oldSwitcher.sel <== newlrbit;
oldProofHash.L <== oldSwitcher.outL;
oldProofHash.R <== oldSwitcher.outR;
aux[0] <== old1leaf * (st_bot + st_new1 + st_upd);
oldRoot <== aux[0] + oldProofHash.out * st_top;
// New side
aux[1] <== newChild * ( st_top + st_bot);
newSwitcher.L <== aux[1] + new1leaf*st_new1;
aux[2] <== sibling*st_top;
newSwitcher.R <== aux[2] + old1leaf*st_new1;
newSwitcher.sel <== newlrbit;
newProofHash.L <== newSwitcher.outL;
newProofHash.R <== newSwitcher.outR;
aux[3] <== newProofHash.out * (st_top + st_bot + st_new1);
newRoot <== aux[3] + new1leaf * (st_old0 + st_upd);
}

View File

@@ -0,0 +1,164 @@
/*
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/>.
*/
/***************************************************************************************************
Each level on a SMTProcessor has a state.
The state of the level depends on the state of te botom level and on `xor` and
`is0` signals.
`isOldLev` 1 when is the level where oldLeaf is.
`xor` signal is 0 if the index bit at the current level is the same in the old
and the new index, and 1 if it is different.
`is0` signal, is 1 if we are inserting/deleting in an empty leaf and 0 if we
are inserting/deleting in a leaf that contains an element.
The states are:
top: While the index bits of the old and new insex in the top level is the same, whe are in the top state.
old0: When the we reach insert level, we go to old0 state
if `is0`=1.
btn: Once in insert level and `is0` =0 we go to btn or new1 level if xor=1
new1: This level is reached when xor=1. Here is where we insert/delete the hash of the
old and the new trees with just one element.
na: Not appliable. After processing it, we go to the na level.
Fnction
fnc[0] fnc[1]
0 0 NOP
0 1 UPDATE
1 0 INSERT
1 1 DELETE
###########
# #
┌────────────────────────────▶# upd #─────────────────────┐
│ ## ## │
│ ######### │
levIns=1 │ │
fnc[0]=0 │ │ any
│ │
│ │
│ │
│ ########### │
│ levIns=1 # # │
levIns=0 │ is0=1 ┌────────────▶# old0 #────────┐ │ any
┌─────┐ │ fnc[0]=1│ ## ## │ │ ┌──────┐
│ │ │ │ ######### │ any │ │ │
│ ▼ │ │ │ ▼ ▼ │
│ ########### │ │ ########### │
│ # # ────────────┘ └────────▶# #│
└──# top # # na #
## ## ───────────────────┐ levIns=1 ┌──▶## ##
######### │ is0=0 │ #########
│ │ fnc[0]=1 │
│ │ xor=1 ########### │ any
│ └──────────────────▶# # │
│ # new1 #──┘
│ ## ##
└────────────────────────────────┐ #########
levIns=1 │ ▲
is0=0 │ ┌─────┘
fnc[0]=1 │ ###########│ xor=1
xor=0 │ # #
▼# btn #
## ##
#########◀───────┐
│ │
│ │
└────────────┘
xor=0
***************************************************************************************************/
template SMTProcessorSM() {
signal input xor;
signal input is0;
signal input levIns;
signal input fnc[2];
signal input prev_top;
signal input prev_old0;
signal input prev_bot;
signal input prev_new1;
signal input prev_na;
signal input prev_upd;
signal output st_top;
signal output st_old0;
signal output st_bot;
signal output st_new1;
signal output st_na;
signal output st_upd;
signal aux1;
signal aux2;
aux1 <== prev_top * levIns;
aux2 <== aux1*fnc[0]; // prev_top * levIns * fnc[0]
// st_top = prev_top*(1-levIns)
// = + prev_top
// - prev_top * levIns = aux1
st_top <== prev_top - aux1;
// st_old0 = prev_top * levIns * is0 * fnc[0]
// = + prev_top * levIns * is0 * fnc[0] = aux2 * is0
st_old0 <== aux2 * is0; // prev_top * levIns * is0 * fnc[0]
// st_new1 = prev_top * levIns * (1-is0)*fnc[0] * xor + prev_bot*xor =
// = + prev_top * levIns * fnc[0] * xor = aux2 * xor
// - prev_top * levIns * is0 * fnc[0] * xor = st_old0 * xor
// + prev_bot * xor = prev_bot * xor
st_new1 <== (aux2 - st_old0 + prev_bot)*xor;
// st_bot = prev_top * levIns * (1-is0)*fnc[0] * (1-xor) + prev_bot*(1-xor);
// = + prev_top * levIns * fnc[0]
// - prev_top * levIns * is0 * fnc[0]
// - prev_top * levIns * fnc[0] * xor
// + prev_top * levIns * is0 * fnc[0] * xor
// + prev_bot
// - prev_bot * xor
st_bot <== (1-xor) * (aux2 - st_old0 + prev_bot)
// st_upd = prev_top * (1-fnc[0]) *levIns;
// = + prev_top * levIns
// - prev_top * levIns * fnc[0]
st_upd <== aux1 - aux2
// st_na = prev_new1 + prev_old0 + prev_na + prev_upd;
// = + prev_new1
// + prev_old0
// + prev_na
// + prev_upd
st_na <== prev_new1 + prev_old0 + prev_na + prev_upd;
}

View File

@@ -0,0 +1,135 @@
/*
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/>.
*/
/*
SMTVerifier is a component to verify inclusion/exclusion of an element in the tree
fnc: 0 -> VERIFY INCLUSION
1 -> VERIFY NOT INCLUSION
*/
include "../gates.circom";
include "../bitify.circom";
include "../comparators.circom";
include "../switcher.circom";
include "smtlevins.circom";
include "smtverifierlevel.circom";
include "smtverifiersm.circom";
include "smthash_poseidon.circom";
template SMTVerifier(nLevels) {
signal input enabled;
signal input root;
signal input siblings[nLevels];
signal input oldKey;
signal input oldValue;
signal input isOld0;
signal input key;
signal input value;
signal input fnc;
component hash1Old = SMTHash1();
hash1Old.key <== oldKey;
hash1Old.value <== oldValue;
component hash1New = SMTHash1();
hash1New.key <== key;
hash1New.value <== value;
component n2bOld = Num2Bits_strict();
component n2bNew = Num2Bits_strict();
n2bOld.in <== oldKey;
n2bNew.in <== key;
component smtLevIns = SMTLevIns(nLevels);
for (var i=0; i<nLevels; i++) smtLevIns.siblings[i] <== siblings[i];
smtLevIns.enabled <== enabled;
component sm[nLevels];
for (var i=0; i<nLevels; i++) {
sm[i] = SMTVerifierSM();
if (i==0) {
sm[i].prev_top <== enabled;
sm[i].prev_i0 <== 0;
sm[i].prev_inew <== 0;
sm[i].prev_iold <== 0;
sm[i].prev_na <== 1-enabled;
} else {
sm[i].prev_top <== sm[i-1].st_top;
sm[i].prev_i0 <== sm[i-1].st_i0;
sm[i].prev_inew <== sm[i-1].st_inew;
sm[i].prev_iold <== sm[i-1].st_iold;
sm[i].prev_na <== sm[i-1].st_na;
}
sm[i].is0 <== isOld0;
sm[i].fnc <== fnc;
sm[i].levIns <== smtLevIns.levIns[i];
}
sm[nLevels-1].st_na + sm[nLevels-1].st_iold + sm[nLevels-1].st_inew + sm[nLevels-1].st_i0 === 1;
component levels[nLevels];
for (var i=nLevels-1; i != -1; i--) {
levels[i] = SMTVerifierLevel();
levels[i].st_top <== sm[i].st_top;
levels[i].st_i0 <== sm[i].st_i0;
levels[i].st_inew <== sm[i].st_inew;
levels[i].st_iold <== sm[i].st_iold;
levels[i].st_na <== sm[i].st_na;
levels[i].sibling <== siblings[i];
levels[i].old1leaf <== hash1Old.out;
levels[i].new1leaf <== hash1New.out;
levels[i].lrbit <== n2bNew.out[i];
if (i==nLevels-1) {
levels[i].child <== 0;
} else {
levels[i].child <== levels[i+1].root;
}
}
// Check that if checking for non inclussuin and isOld0==0 then key!=old
component areKeyEquals = IsEqual();
areKeyEquals.in[0] <== oldKey;
areKeyEquals.in[1] <== key;
component keysOk = MultiAND(4);
keysOk.in[0] <== fnc;
keysOk.in[1] <== 1-isOld0;
keysOk.in[2] <== areKeyEquals.out;
keysOk.in[3] <== enabled;
keysOk.out === 0;
// Check the root
component checkRoot = ForceEqualIfEnabled();
checkRoot.enabled <== enabled;
checkRoot.in[0] <== levels[0].root;
checkRoot.in[1] <== root;
// levels[0].root === root;
}

View File

@@ -0,0 +1,71 @@
/*
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/>.
*/
/******
SMTVerifierLevel
This circuit has 1 hash
Outputs according to the state.
State root
===== =======
top H'(child, sibling)
i0 0
iold old1leaf
inew new1leaf
na 0
H' is the Hash function with the inputs shifted acordingly.
*****/
template SMTVerifierLevel() {
signal input st_top;
signal input st_i0;
signal input st_iold;
signal input st_inew;
signal input st_na;
signal output root;
signal input sibling;
signal input old1leaf;
signal input new1leaf;
signal input lrbit;
signal input child;
signal aux[2];
component proofHash = SMTHash2();
component switcher = Switcher();
switcher.L <== child;
switcher.R <== sibling;
switcher.sel <== lrbit;
proofHash.L <== switcher.outL;
proofHash.R <== switcher.outR;
aux[0] <== proofHash.out * st_top;
aux[1] <== old1leaf*st_iold;
root <== aux[0] + aux[1] + new1leaf*st_inew;
}

View File

@@ -0,0 +1,105 @@
/*
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/>.
*/
/*
Each level in the SMTVerifier has a state.
This is the state machine.
The signals are
levIns: 1 if we are in the level where the insertion should happen
xor: 1 if the bitKey of the old and new keys are different in this level
is0: Input that indicates that the oldKey is 0
fnc: 0 -> VERIFY INCLUSION
1 -> VERIFY NOT INCLUSION
err state is not a state itself. It's a lack of state.
The end of the last level will have to be `na`
levIns=0 any
┌────┐ ┌────┐
│ │ │ │
│ ▼ levIns=1 ▼ │
│ ########### is0=1 ########### ########### │
│ # # fnc=1 # # any # # │
└──# top # ─────────────────────▶# i0 #───────────────▶# na #──┘
## ## ──────────┐ ## ## ┌───────▶## ##
########─────────────┐│ ######### │┌────────▶#########
││ levIns=1 ││
││ is0=0 ########### ││
││ fnc=1 # # any│
│└──────────▶ # iold #────────┘│
│ ## ## │
│ ######### │
│ │
│ levIns=1 ########### │
│ fnc=0 # # any
└────────────▶# inew #─────────┘
## ##
#########
*/
template SMTVerifierSM() {
signal input is0;
signal input levIns;
signal input fnc;
signal input prev_top;
signal input prev_i0;
signal input prev_iold;
signal input prev_inew;
signal input prev_na;
signal output st_top;
signal output st_i0;
signal output st_iold;
signal output st_inew;
signal output st_na;
signal prev_top_lev_ins;
signal prev_top_lev_ins_fnc;
prev_top_lev_ins <== prev_top * levIns;
prev_top_lev_ins_fnc <== prev_top_lev_ins*fnc; // prev_top * levIns * fnc
// st_top = prev_top * (1-levIns)
// = + prev_top
// - prev_top * levIns
st_top <== prev_top - prev_top_lev_ins;
// st_inew = prev_top * levIns * (1-fnc)
// = + prev_top * levIns
// - prev_top * levIns * fnc
st_inew <== prev_top_lev_ins - prev_top_lev_ins_fnc;
// st_iold = prev_top * levIns * (1-is0)*fnc
// = + prev_top * levIns * fnc
// - prev_top * levIns * fnc * is0
st_iold <== prev_top_lev_ins_fnc * (1 - is0);
// st_i0 = prev_top * levIns * is0
// = + prev_top * levIns * is0
st_i0 <== prev_top_lev_ins * is0;
st_na <== prev_na + prev_inew + prev_iold + prev_i0;
}

View File

@@ -0,0 +1,40 @@
/*
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/>.
*/
/*
Assume sel is binary.
If sel == 0 then outL = L and outR=R
If sel == 1 then outL = R and outR=L
*/
template Switcher() {
signal input sel;
signal input L;
signal input R;
signal output outL;
signal output outR;
signal aux;
aux <== (R-L)*sel; // We create aux in order to have only one multiplication
outL <== aux + L;
outR <== -aux + R;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,6 @@
exports.smt = require("./src/smt");
exports.eddsa = require("./src/eddsa");
exports.mimc7 = require("./src/mimc7");
exports.mimcsponge = require("./src/mimcsponge");
exports.babyJub = require("./src/babyjub");
exports.pedersenHash = require("./src/pedersenHash");

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
{
"name": "circomlib",
"version": "0.0.12",
"description": "Basic circuits library for Circom",
"main": "index.js",
"directories": {
"test": "test"
},
"scripts": {
"test": "mocha --max-old-space-size=4000"
},
"keywords": [
"pedersen",
"hash",
"ethereum",
"circuit",
"circom",
"zksnark"
],
"repository": {
"type": "git",
"url": "https://github.com/iden3/circomlib.git"
},
"author": "0Kims",
"license": "GPL-3.0",
"dependencies": {
"blake-hash": "^1.1.0",
"blake2b": "^2.1.3",
"snarkjs": "0.1.11",
"typedarray-to-buffer": "^3.1.5",
"web3": "^1.0.0-beta.55"
},
"devDependencies": {
"circom": "0.0.28",
"eslint-plugin-mocha": "^5.2.0",
"ganache-cli": "^6.4.4",
"mocha": "^5.2.0"
}
}

View File

@@ -0,0 +1,109 @@
const bn128 = require("snarkjs").bn128;
const bigInt = require("snarkjs").bigInt;
exports.addPoint = addPoint;
exports.mulPointEscalar = mulPointEscalar;
exports.inCurve = inCurve;
exports.inSubgroup = inSubgroup;
exports.packPoint = packPoint;
exports.unpackPoint = unpackPoint;
exports.Generator = [
bigInt("995203441582195749578291179787384436505546430278305826713579947235728471134"),
bigInt("5472060717959818805561601436314318772137091100104008585924551046643952123905")
];
exports.Base8 = [
bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")
];
exports.order = bigInt("21888242871839275222246405745257275088614511777268538073601725287587578984328");
exports.subOrder = exports.order.shr(3);
exports.p = bn128.r;
exports.A = bigInt("168700");
exports.D = bigInt("168696");
function addPoint(a,b) {
const q = bn128.r;
const res = [];
/* does the equivalent of:
res[0] = bigInt((a[0]*b[1] + b[0]*a[1]) * bigInt(bigInt("1") + d*a[0]*b[0]*a[1]*b[1]).inverse(q)).affine(q);
res[1] = bigInt((a[1]*b[1] - cta*a[0]*b[0]) * bigInt(bigInt("1") - d*a[0]*b[0]*a[1]*b[1]).inverse(q)).affine(q);
*/
res[0] = bigInt((bigInt(a[0]).mul(b[1]).add(bigInt(b[0]).mul(a[1]))).mul(bigInt(bigInt("1").add(exports.D.mul(a[0]).mul(b[0]).mul(a[1]).mul(b[1]))).inverse(q))).affine(q);
res[1] = bigInt((bigInt(a[1]).mul(b[1]).sub(exports.A.mul(a[0]).mul(b[0]))).mul(bigInt(bigInt("1").sub(exports.D.mul(a[0]).mul(b[0]).mul(a[1]).mul(b[1]))).inverse(q))).affine(q);
return res;
}
function mulPointEscalar(base, e) {
let res = [bigInt("0"),bigInt("1")];
let rem = bigInt(e);
let exp = base;
while (! rem.isZero()) {
if (rem.isOdd()) {
res = addPoint(res, exp);
}
exp = addPoint(exp, exp);
rem = rem.shr(1);
}
return res;
}
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)));
}
function inCurve(P) {
const F = bn128.Fr;
const x2 = F.square(P[0]);
const y2 = F.square(P[1]);
if (!F.equals(
F.add(F.mul(exports.A, x2), y2),
F.add(F.one, F.mul(F.mul(x2, y2), exports.D)))) return false;
return true;
}
function packPoint(P) {
const buff = bigInt.leInt2Buff(P[1], 32);
if (P[0].greater(exports.p.shr(1))) {
buff[31] = buff[31] | 0x80;
}
return buff;
}
function unpackPoint(_buff) {
const F = bn128.Fr;
const buff = Buffer.from(_buff);
let sign = false;
const P = new Array(2);
if (buff[31] & 0x80) {
sign = true;
buff[31] = buff[31] & 0x7F;
}
P[1] = bigInt.leBuff2int(buff);
if (P[1].greaterOrEquals(exports.p)) return null;
const y2 = F.square(P[1]);
let x = F.sqrt(F.div(
F.sub(F.one, y2),
F.sub(exports.A, F.mul(exports.D, y2))));
if (x == null) return null;
if (sign) x = F.neg(x);
P[0] = F.affine(x);
return P;
}

View File

@@ -0,0 +1,223 @@
const createBlakeHash = require("blake-hash");
const bigInt = require("snarkjs").bigInt;
const babyJub = require("./babyjub");
const pedersenHash = require("./pedersenHash").hash;
const mimc7 = require("./mimc7");
const poseidon = require("./poseidon.js");
const mimcsponge = require("./mimcsponge");
exports.prv2pub= prv2pub;
exports.sign = sign;
exports.signMiMC = signMiMC;
exports.signPoseidon = signPoseidon;
exports.signMiMCSponge = signMiMCSponge;
exports.verify = verify;
exports.verifyMiMC = verifyMiMC;
exports.verifyPoseidon = verifyPoseidon;
exports.verifyMiMCSponge = verifyMiMCSponge;
exports.packSignature = packSignature;
exports.unpackSignature = unpackSignature;
exports.pruneBuffer = pruneBuffer;
function pruneBuffer(_buff) {
const buff = Buffer.from(_buff);
buff[0] = buff[0] & 0xF8;
buff[31] = buff[31] & 0x7F;
buff[31] = buff[31] | 0x40;
return buff;
}
function prv2pub(prv) {
const sBuff = pruneBuffer(createBlakeHash("blake512").update(prv).digest().slice(0,32));
let s = bigInt.leBuff2int(sBuff);
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
return A;
}
function sign(prv, msg) {
const h1 = createBlakeHash("blake512").update(prv).digest();
const sBuff = pruneBuffer(h1.slice(0,32));
const s = bigInt.leBuff2int(sBuff);
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msg])).digest();
let r = bigInt.leBuff2int(rBuff);
r = r.mod(babyJub.subOrder);
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 = bigInt.leBuff2int(hmBuff);
const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
return {
R8: R8,
S: S
};
}
function signMiMC(prv, msg) {
const h1 = createBlakeHash("blake512").update(prv).digest();
const sBuff = pruneBuffer(h1.slice(0,32));
const s = bigInt.leBuff2int(sBuff);
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
const msgBuff = bigInt.leInt2Buff(msg, 32);
const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
let r = bigInt.leBuff2int(rBuff);
r = r.mod(babyJub.subOrder);
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.mul(s)).mod(babyJub.subOrder);
return {
R8: R8,
S: S
};
}
function signMiMCSponge(prv, msg) {
const h1 = createBlakeHash("blake512").update(prv).digest();
const sBuff = pruneBuffer(h1.slice(0,32));
const s = bigInt.leBuff2int(sBuff);
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
const msgBuff = bigInt.leInt2Buff(msg, 32);
const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
let r = bigInt.leBuff2int(rBuff);
r = r.mod(babyJub.subOrder);
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.mul(s)).mod(babyJub.subOrder);
return {
R8: R8,
S: S
};
}
function signPoseidon(prv, msg) {
const h1 = createBlakeHash("blake512").update(prv).digest();
const sBuff = pruneBuffer(h1.slice(0,32));
const s = bigInt.leBuff2int(sBuff);
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
const msgBuff = bigInt.leInt2Buff(msg, 32);
const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
let r = bigInt.leBuff2int(rBuff);
r = r.mod(babyJub.subOrder);
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.mul(s)).mod(babyJub.subOrder);
return {
R8: R8,
S: S
};
}
function verify(msg, sig, A) {
// Check parameters
if (typeof sig != "object") return false;
if (!Array.isArray(sig.R8)) return false;
if (sig.R8.length!= 2) return false;
if (!babyJub.inCurve(sig.R8)) return false;
if (!Array.isArray(A)) return false;
if (A.length!= 2) return false;
if (!babyJub.inCurve(A)) return false;
if (sig.S>= babyJub.subOrder) return false;
const R8p = babyJub.packPoint(sig.R8);
const Ap = babyJub.packPoint(A);
const hmBuff = pedersenHash(Buffer.concat([R8p, Ap, msg]));
const hm = bigInt.leBuff2int(hmBuff);
const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
Pright = babyJub.addPoint(sig.R8, Pright);
if (!Pleft[0].equals(Pright[0])) return false;
if (!Pleft[1].equals(Pright[1])) return false;
return true;
}
function verifyMiMC(msg, sig, A) {
// Check parameters
if (typeof sig != "object") return false;
if (!Array.isArray(sig.R8)) return false;
if (sig.R8.length!= 2) return false;
if (!babyJub.inCurve(sig.R8)) return false;
if (!Array.isArray(A)) return false;
if (A.length!= 2) return false;
if (!babyJub.inCurve(A)) return false;
if (sig.S>= babyJub.subOrder) return false;
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.mul(bigInt("8")));
Pright = babyJub.addPoint(sig.R8, Pright);
if (!Pleft[0].equals(Pright[0])) return false;
if (!Pleft[1].equals(Pright[1])) return false;
return true;
}
function verifyPoseidon(msg, sig, A) {
// Check parameters
if (typeof sig != "object") return false;
if (!Array.isArray(sig.R8)) return false;
if (sig.R8.length!= 2) return false;
if (!babyJub.inCurve(sig.R8)) return false;
if (!Array.isArray(A)) return false;
if (A.length!= 2) return false;
if (!babyJub.inCurve(A)) return false;
if (sig.S>= babyJub.subOrder) return false;
const hash = poseidon.createHash(6, 8, 57);
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.mul(bigInt("8")));
Pright = babyJub.addPoint(sig.R8, Pright);
if (!Pleft[0].equals(Pright[0])) return false;
if (!Pleft[1].equals(Pright[1])) return false;
return true;
}
function verifyMiMCSponge(msg, sig, A) {
// Check parameters
if (typeof sig != "object") return false;
if (!Array.isArray(sig.R8)) return false;
if (sig.R8.length!= 2) return false;
if (!babyJub.inCurve(sig.R8)) return false;
if (!Array.isArray(A)) return false;
if (A.length!= 2) return false;
if (!babyJub.inCurve(A)) return false;
if (sig.S>= babyJub.subOrder) return false;
const hm = mimcsponge.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.mul(bigInt("8")));
Pright = babyJub.addPoint(sig.R8, Pright);
if (!Pleft[0].equals(Pright[0])) return false;
if (!Pleft[1].equals(Pright[1])) return false;
return true;
}
function packSignature(sig) {
const R8p = babyJub.packPoint(sig.R8);
const Sp = bigInt.leInt2Buff(sig.S, 32);
return Buffer.concat([R8p, Sp]);
}
function unpackSignature(sigBuff) {
return {
R8: babyJub.unpackPoint(sigBuff.slice(0,32)),
S: bigInt.leBuff2int(sigBuff.slice(32,64))
};
}

View File

@@ -0,0 +1,197 @@
// Copyright (c) 2018 Jordi Baylina
// License: LGPL-3.0+
//
const Web3Utils = require("web3-utils");
class Contract {
constructor() {
this.code = [];
this.labels = {};
this.pendingLabels = {};
}
createTxData() {
let C;
// Check all labels are defined
const pendingLabels = Object.keys(this.pendingLabels);
if (pendingLabels.length>0) {
throw new Error("Lables not defined: "+ pendingLabels.join(", "));
}
let setLoaderLength = 0;
let genLoadedLength = -1;
while (genLoadedLength!=setLoaderLength) {
setLoaderLength = genLoadedLength;
C = new module.exports();
C.codesize();
C.push(setLoaderLength);
C.push(0);
C.codecopy();
C.push(this.code.length);
C.push(0);
C.return();
genLoadedLength = C.code.length;
}
return Web3Utils.bytesToHex(C.code.concat(this.code));
}
stop() { this.code.push(0x00); }
add() { this.code.push(0x01); }
mul() { this.code.push(0x02); }
sub() { this.code.push(0x03); }
div() { this.code.push(0x04); }
sdiv() { this.code.push(0x05); }
mod() { this.code.push(0x06); }
smod() { this.code.push(0x07); }
addmod() { this.code.push(0x08); }
mulmod() { this.code.push(0x09); }
exp() { this.code.push(0x0a); }
signextend() { this.code.push(0x0b); }
lt() { this.code.push(0x10); }
gt() { this.code.push(0x11); }
slt() { this.code.push(0x12); }
sgt() { this.code.push(0x13); }
eq() { this.code.push(0x14); }
iszero() { this.code.push(0x15); }
and() { this.code.push(0x16); }
or() { this.code.push(0x17); }
shor() { this.code.push(0x18); }
not() { this.code.push(0x19); }
byte() { this.code.push(0x1a); }
keccak() { this.code.push(0x20); }
sha3() { this.code.push(0x20); } // alias
address() { this.code.push(0x30); }
balance() { this.code.push(0x31); }
origin() { this.code.push(0x32); }
caller() { this.code.push(0x33); }
callvalue() { this.code.push(0x34); }
calldataload() { this.code.push(0x35); }
calldatasize() { this.code.push(0x36); }
calldatacopy() { this.code.push(0x37); }
codesize() { this.code.push(0x38); }
codecopy() { this.code.push(0x39); }
gasprice() { this.code.push(0x3a); }
extcodesize() { this.code.push(0x3b); }
extcodecopy() { this.code.push(0x3c); }
returndatasize() { this.code.push(0x3d); }
returndatacopy() { this.code.push(0x3e); }
blockhash() { this.code.push(0x40); }
coinbase() { this.code.push(0x41); }
timestamp() { this.code.push(0x42); }
number() { this.code.push(0x43); }
difficulty() { this.code.push(0x44); }
gaslimit() { this.code.push(0x45); }
pop() { this.code.push(0x50); }
mload() { this.code.push(0x51); }
mstore() { this.code.push(0x52); }
mstore8() { this.code.push(0x53); }
sload() { this.code.push(0x54); }
sstore() { this.code.push(0x55); }
_pushLabel(label) {
if (typeof this.labels[label] != "undefined") {
this.push(this.labels[label]);
} else {
this.pendingLabels[label] = this.pendingLabels[label] || [];
this.pendingLabels[label].push(this.code.length);
this.push("0x000000");
}
}
_fillLabel(label) {
if (!this.pendingLabels[label]) return;
let dst = this.labels[label];
const dst3 = [dst >> 16, (dst >> 8) & 0xFF, dst & 0xFF];
this.pendingLabels[label].forEach((p) => {
for (let i=0; i<3; i++) {
this.code[p+i+1] = dst3[i];
}
});
delete this.pendingLabels[label];
}
jmp(label) {
if (typeof label !== "undefined") {
this._pushLabel(label);
}
this.code.push(0x56);
}
jmpi(label) {
if (typeof label !== "undefined") {
this._pushLabel(label);
}
this.code.push(0x57);
}
pc() { this.code.push(0x58); }
msize() { this.code.push(0x59); }
gas() { this.code.push(0x5a); }
label(name) {
if (typeof this.labels[name] != "undefined") {
throw new Error("Label already defined");
}
this.labels[name] = this.code.length;
this.code.push(0x5b);
this._fillLabel(name);
}
push(data) {
const d = Web3Utils.hexToBytes(Web3Utils.toHex(data));
if (d.length == 0 || d.length > 32) {
throw new Error("Assertion failed");
}
this.code = this.code.concat([0x5F + d.length], d);
}
dup(n) {
if (n < 0 || n >= 16) {
throw new Error("Assertion failed");
}
this.code.push(0x80 + n);
}
swap(n) {
if (n < 1 || n > 16) {
throw new Error("Assertion failed");
}
this.code.push(0x8f + n);
}
log0() { this.code.push(0xa0); }
log1() { this.code.push(0xa1); }
log2() { this.code.push(0xa2); }
log3() { this.code.push(0xa3); }
log4() { this.code.push(0xa4); }
create() { this.code.push(0xf0); }
call() { this.code.push(0xf1); }
callcode() { this.code.push(0xf2); }
return() { this.code.push(0xf3); }
delegatecall() { this.code.push(0xf4); }
staticcall() { this.code.push(0xfa); }
revert() { this.code.push(0xfd); }
invalid() { this.code.push(0xfe); }
selfdestruct() { this.code.push(0xff); }
}
module.exports = Contract;

View File

@@ -0,0 +1,583 @@
// Copyright (c) 2018 Jordi Baylina
// License: LGPL-3.0+
//
const Contract = require("./evmasm");
const G2 = require("snarkjs").bn128.G2;
const bigInt = require("snarkjs").bigInt;
function toHex256(a) {
let S = a.toString(16);
while (S.length < 64) S="0"+S;
return "0x" + S;
}
function createCode(P, w) {
const C = new Contract();
const NPOINTS = 1 << (w-1);
const VAR_POS = C.allocMem(32);
const VAR_POINTS = C.allocMem( (NPOINTS)*4*32);
const savedP = C.allocMem(32);
const savedZ3 = C.allocMem(32);
// Check selector
C.push("0x0100000000000000000000000000000000000000000000000000000000");
C.push(0);
C.calldataload();
C.div();
C.push("b65c7c74"); // mulexp(uint256)
C.eq();
C.jmpi("start");
C.invalid();
C.label("start");
storeVals();
C.push( Math.floor(255/w)*w ); // pos := 255
C.push(VAR_POS);
C.mstore();
C.push("21888242871839275222246405745257275088696311157297823662689037894645226208583");
C.push(0);
C.push(0);
C.push(0);
C.push(0);
C.push(0);
C.push(0);
C.label("begin_loop"); // ACC_X ACC_Y ACC_Z q
C.internalCall("double");
// g = (e>>pos)&MASK
C.push(4);
C.calldataload(); // e ACC_X ACC_Y ACC_Z q
C.push(VAR_POS);
C.mload(); // pos e ACC_X ACC_Y ACC_Z q
C.shr();
C.push(NPOINTS-1);
C.and(); // g ACC_X ACC_Y ACC_Z q
C.internalCall("add"); // acc_x acc_y acc_z
C.push(VAR_POS);
C.mload(); // pos acc_x acc_y acc_z
C.dup(0); // pos pos acc_x acc_y acc_z
C.push(0); // 0 pos pos acc_x acc_y acc_z
C.eq(); // eq pos acc_x acc_y acc_z
C.jmpi("after_loop"); // pos acc_x acc_y acc_z
C.push(w); // 5 pos acc_x acc_y acc_z
C.sub(); // pos acc_x acc_y acc_z
C.push(VAR_POS);
C.mstore(); // acc_x acc_y acc_z
C.jmp("begin_loop");
C.label("after_loop"); // pos acc_x acc_y acc_z
C.pop(); // acc_x acc_y acc_z
C.internalCall("affine"); // acc_x acc_y
C.push(0);
C.mstore();
C.push(20);
C.mstore();
C.push(40);
C.mstore();
C.push(60);
C.mstore();
C.push("0x80");
C.push("0x00");
C.return();
double();
addPoint();
affine();
return C.createTxData();
function add(a,b,q) {
C.dup(q);
C.dup(a+1 + 1);
C.dup(b+1 + 2);
C.addmod();
C.dup(q + 1);
C.dup(a + 2);
C.dup(b + 3);
C.addmod();
}
function sub(a,b,q) {
C.dup(q); // q
C.dup(a+1 + 1); // ai q
C.dub(q + 2); // q ai q
C.dup(b+1 + 3); // bi q ai q
C.sub(); // -bi ai q
C.addmod(); // ci
C.dup(q + 1); // q ci
C.dup(a + 2); // ar q ci
C.dup(q + 3); // q ar q ci
C.dup(b + 4); // br q ar q ci
C.sub(); // -br ar q ci
C.addmod(); // cr ci
}
function mul(a, b, q) {
C.dup(q); // q
C.dup(q + 1); // q q
C.dup(a + 2); // ar q q
C.dup(b+1 + 3); // bi ar q q
C.mulmod(); // ci1 q
C.dup(q + 2); // q ci1 q
C.dup(a+1 + 3); // ai q ci1 q
C.dup(b + 4); // ar ai q ci1 q
C.mulmod(); // ci2 ci1 q
C.addmod(); // ci
C.dup(q + 1); // q ci
C.dup(q + 2); // q q ci
C.dup(q + 3); // q q q ci
C.dup(a+1 + 4); // ai q q ci
C.dup(b+1 + 5); // bi ai q q ci
C.mulmod(); // cr2 q q ci
C.sub(); // -cr2 q ci
C.dup(q + 3); // q -cr2 q ci
C.dup(a + 4); // ar q -cr2 q ci
C.dup(b + 5); // br ar q -cr2 q ci
C.mulmod(); // cr1 -cr2 q ci
C.addmod(); // cr ci
}
function square(a, q) {
C.dup(q); // q
C.dup(q + 1); // q q
C.dup(a + 2); // ar q q
C.dup(a+1 + 3); // ai ar q q
C.mulmod(); // arai q
C.dup(0); // arai arai q
C.addmod(); // ci
C.dup(q + 1); // q ci
C.dup(q + 2); // q q ci
C.dup(q + 3); // q q q ci
C.dup(a+1 + 4); // ai q q ci
C.dup(a+1 + 5); // ai ai q q ci
C.mulmod(); // cr2 q q ci
C.sub(); // -cr2 q ci
C.dup(q + 3); // q -cr2 q ci
C.dup(a + 4); // ar q -cr2 q ci
C.dup(a + 5); // br ar q -cr2 q ci
C.mulmod(); // cr1 -cr2 q ci
C.addmod(); // cr ci
}
function add1(a, q) {
C.dup(a+1); // im
C.dup(1 + q); // q
C.dup(2 + a); // re q im
C.push(1); // 1 re q im
C.addmod();
}
function cmp(a, b) {
C.dup(a);
C.dup(b);
C.eq();
C.dup(a+1);
C.dup(a+1);
C.and();
}
function rm(a) {
if (a>0) C.swap(a);
C.pop();
if (a>0) C.swap(a);
C.pop();
}
function double() {
C.label("double"); // xR, xI, yR, yI, zR zI, q
C.dup(4);
C.iszero();
C.dup(6);
C.iszero();
C.and();
C.jumpi("enddouble"); // X Y Z q
// Z3 = 2*Y*Z // Remove Z
mul(2, 4, 6); // yz X Y Z q
rm(6); // X Y yz q
add(4, 4, 6); // 2yz X Y yz q
rm(6); // X Y Z3 q
// A = X^2
square(0,6); // A X Y Z3 q
// B = Y^2 // Remove Y
square(4,8); // B A X Y Z3 q
rm(6); // A X B Z3 q
// C = B^2
square(4,8); // C A X B Z3 q
// D = (X+B)^2-A-C // Remove X, Remove B
add(4,6, 10); // X+B C A X B Z3 q
rm(6); // C A X+B B Z3 q
rm(6); // A X+B C Z3 q
square(2,8); // (X+B)^2 A X+B C Z3 q
rm(4); // A (X+B)^2 C Z3 q
sub(2, 0, 8); // (X+B)^2-A A (X+B)^2 C Z3 q
rm(4); // A (X+B)^2-A C Z3 q
sub(2, 4, 8); // (X+B)^2-A-C A (X+B)^2-A C Z3 q
rm(4); // A D C Z3 q
// D = D+D
add(2,2, 8); // D+D A D C Z3 q
rm(4); // A D C Z3 q
// E=A+A+A
add(0, 0, 8); // 2A A D C Z3 q
add(0, 2, 10); // 3A 2A A D C Z3 q
rm(4); // 2A 3A D C Z3 q
rm(0); // E D C Z3 q
// F=E^2
square(0, 8); // F E D C Z3 q
// X3= F - 2*D // Remove F
add(4, 4, 10); // 2D F E D C Z3 q
sub(2, 0, 12); // F-2D 2D F E D C Z3 q
rm(4); // 2D X3 E D C Z3 q
rm(0); // X3 E D C Z3 q
// Y3 = E * (D - X3) - 8 * C // Remove D C E
sub(4, 0, 10); // D-X3 X3 E D C Z3 q
rm(6); // X3 E D-X3 C Z3 q
mul(2, 4, 10); // E*(D-X3) X3 E D-X3 C Z3 q
rm(6); // X3 E E*(D-X3) C Z3 q
rm(2); // X3 E*(D-X3) C Z3 q
add(4, 4, 8); // 2C X3 E*(D-X3) C Z3 q
rm(6); // X3 E*(D-X3) 2C Z3 q
add(4, 4, 8); // 4C X3 E*(D-X3) 2C Z3 q
rm(6); // X3 E*(D-X3) 4C Z3 q
add(4, 4, 8); // 8C X3 E*(D-X3) 4C Z3 q
rm(6); // X3 E*(D-X3) 8C Z3 q
sub(2, 4, 8); // E*(D-X3)-8C X3 E*(D-X3) 8C Z3 q
rm(6); // X3 E*(D-X3) Y3 Z3 q
rm(2); // X3 Y3 Z3 q
C.label("enddouble");
C.returnCall();
}
function addPoint() { // p, xR, xI, yR, yI, zR zI, q
C.dup(0); // p p X2 Y2 Z2 q
C.push(savedP);
C.mstore();
C.iszero(); // X2 Y2 Z2 q
C.jumpi("endpadd");
C.dup(4);
C.iszero();
C.dup(6);
C.iszero();
C.and();
C.jumpi("returnP"); // X2 Y2 Z2 q
// lastZ3 = (Z2+1)^2 - Z2^2
add1(4, 6); // Z2+1 X2 Y2 Z2 q
square(0, 8); // (Z2+1)^2 Z2+1 X2 Y2 Z2 q
rm(2); // (Z2+1)^2 X2 Y2 Z2 q
square(6, 8); // Z2^2 (Z2+1)^2 X2 Y2 Z2 q
sub(2, 0, 10); // (Z2+1)^2-Z2^2 Z2^2 (Z2+1)^2 X2 Y2 Z2 q
saveZ3(); // Z2^2 (Z2+1)^2 X2 Y2 Z2 q
rm(2); // Z2^2 X2 Y2 Z2 q
// U2 = X2
// S2 = Y2 // Z2^2 U2 S2 Z2 q
// U1 = X1 * Z2^2
loadX(); // X1 Z2^2 U2 S2 Z2 q
mul(0, 2, 10); // X1*Z2^2 X1 Z2^2 U2 S2 Z2 q
rm(2); // X1*Z2^2 Z2^2 U2 S2 Z2 q
mul(2, 8, 10); // Z2^3 U1 Z2^2 U2 S2 Z2 q
rm(4); // U1 Z2^3 U2 S2 Z2 q
rm(8); // Z2^3 U2 S2 U1 q
// S1 = Y1 * Z1^3
loadY(); // Y1 Z2^3 U2 S2 U1 q
mul(0, 2, 10); // S1 Y1 Z2^3 U2 S2 U1 q
rm(4); // Y1 S1 U2 S2 U1 q
rm(0); // S1 U2 S2 U1 q
cmp(0, 4); // c1 S1 U2 S2 U1 q
cmp(3, 7); // c2 c1 S1 U2 S2 U1 q
C.and(); // c2&c1 S1 U2 S2 U1 q
C.jumpi("double1"); // S1 U2 S2 U1 q
// Returns the double
// H = U2-U1 // Remove U2
C.sub(4, 8, 10); // H S1 U2 S2 U1 q
rm(4); // S1 H S2 U1 q
// // r = 2 * (S2-S1) // Remove S2
C.sub(4, 4, 8); // S1-S2 S1 H S2 U1 q
rm(6); // S1 H S1-S2 U1 q
C.add(4, 4, 8); // 2*(S1-S2) S1 H S1-S2 U1 q
rm(6); // S1 H r U1 q
// I = (2 * H)^2
C.add(2, 2, 8); // 2*H S1 H r U1 q
C.square(0, 10); // (2*H)^2 2*H S1 H r U1 q
rm(2); // I S1 H r U1 q
// V = U1 * I
mul(8, 0, 10); // V I S1 H r U1 q
rm(10); // I S1 H r V q
// J = H * I // Remove I
mul(4, 0, 10); // J I S1 H r V q
rm(2); // J S1 H r V q
// X3 = r^2 - J - 2 * V
// S1J2 = (S1*J)*2 // Remove S1
mul(2, 0, 10); // S1*J J S1 H r V q
rm(4); // J S1*J H r V q
add(2,2, 10); // (S1*J)*2 J S1*J H r V q
rm(4); // J S1J2 H r V q
// X3 = r^2 - J - 2 * V
square(6, 10); // r^2 J S1J2 H r V q
sub(0, 2, 12); // r^2-J r^2 J S1J2 H r V q
rm(2); // r^2-J J S1J2 H r V q
rm(2); // r^2-J S1J2 H r V q
add(8, 8, 10); // 2*V r^2-J S1J2 H r V q
sub(2, 0, 12); // r^2-J-2*V 2*V r^2-J S1J2 H r V q
rm(4); // 2*V X3 S1J2 H r V q
rm(0); // X3 S1J2 H r V q
// Y3 = r * (V-X3)-S1J2
sub(8, 0, 10); // V-X3 X3 S1J2 H r V q
rm(10); // X3 S1J2 H r V-X3 q
mul(6, 8, 10); // r*(V-X3) X3 S1J2 H r V-X3 q
rm(8); // X3 S1J2 H r*(V-X3) V-X3 q
rm(8); // S1J2 H r*(V-X3) X3 q
sub(4, 0, 8); // Y3 S1J2 H r*(V-X3) X3 q
rm(6); // S1J2 H Y3 X3 q
rm(0); // H Y3 X3 q
// Z3 = lastZ * H
loadZ3(); // lastZ3 H Y3 X3 q
mul(0, 2, 8); // Z3 lastZ3 H Y3 X3 q
rm(4); // lastZ3 Z3 Y3 X3 q
rm(0); // Z3 Y3 X3 q
C.swap(1);
C.swap(5);
C.swap(1);
C.swap(4); // X3 Y3 Z3 q
// returns the point in memory
C.label("returnP"); // X Y Z q
rm(0);
rm(0);
rm(0);
C.push(0);
C.push(1);
loadX();
loadY();
C.jump("endpadd");
C.label("double1"); // S1 U2 S2 U1 q
rm(0);
rm(0);
rm(0);
rm(0);
C.push(0);
C.push(1);
loadX();
loadY();
C.jump("double");
C.label("endpadd");
C.returnCall();
function loadX() {
C.push(savedP);
C.mload(); // p
C.push(32);
C.mul(); // P*32
C.push(VAR_POINTS+32);
C.add(); // P*32+32
C.dup(); // P*32+32 P*32+32
C.mload(); // im P*32+32
C.swap(1); // P*32+32 im
C.push(0x20); // 32 P*32+32 im
C.sub(); // P*32 im
C.mload(); // re im
}
function loadY() {
C.push(savedP);
C.mload(); // p
C.push(32);
C.mul(); // P*32
C.push(VAR_POINTS+32*3);
C.add(); // P*32+32
C.dup(); // P*32+32 P*32+32
C.mload(); // im P*32+32
C.swap(1); // P*32+32 im
C.push(0x20); // 32 P*32+32 im
C.sub(); // P*32 im
C.mload(); // re im
}
function loadZ3() {
C.push(savedZ3+32);
C.mload(); // p
C.push(savedZ3);
C.mload();
}
function saveZ3() {
C.push(savedZ3);
C.mstore();
C.push(savedZ3+32);
C.mstore();
}
}
function affine() { // X Y Z q
// If Z2=0 return 0
C.label("affine");
C.dup(4);
C.dup(5 + 1);
C.or();
C.jumpi("notZero"); // X Y Z q
rm(0);
rm(0);
C.push(0);
C.push(0);
C.jmp("endAffine");
C.label("notZero");
inverse2(4,6); // Z_inv X Y Z q
square(2, 8); // Z2_inv Z_inv X Y Z q
mul(0, 2, 10); // Z3_inv Z2_inv Z_inv X Y Z q
rm(4); // Z2_inv Z3_inv X Y Z q
C.push(1);
C.push(0); // 1 Z2_inv Z3_inv X Y Z q
rm(10); // Z2_inv Z3_inv X Y 1 q
mul(2, 6, 10); // YI Z2_inv Z3_inv X Y 1 q
rm(8); // Z2_inv Z3_inv X YI 1 q
mul(0, 4, 10); // XI Z2_inv Z3_inv X YI 1 q
rm(6); // Z2_inv Z3_inv XI YI 1 q
rm(0); // Z3_inv XI YI 1 q
rm(0); // XI YI 1 q
C.label("endAffine");
C.returnCall();
}
function inverse2(a, q) {
C.dup(q); // q
C.dup(q + 1); // q q
C.push(2); // 2 q q
C.sub(); // q-2 q
C.dup(q + 2); // q q-2 q
C.dup(q + 3); // q q q-2 q
C.dup(a + 4); // ar q q q-2 q
C.dup(a + 5); // ar ar q q q-2 q
C.mulmod(); // t0 q q-2 q
C.dup(q + 4); // q t0 q q-2 q
C.dup(a+1 + 5); // ai q t0 q q-2 q
C.dup(a+1 + 6); // ai ai q t0 q q-2 q
C.mulmod(); // t1 t0 q q-2 q
C.addmod(); // t2 q-2 q
C.expmod(); // t3
C.dup(q + 1); // q t3
C.dup(q + 2); // q q t3
C.dup(q + 3); // q q q t3
C.dup(1); // t3 q q q t3
C.sub(); // -t3 q q t3
C.dup(a+1 + 3); // ai -t3 q q t3
C.mulmod(); // ii q t3
C.swap(2); // t3 q ii
C.dup(a + 3); // ar t3 q ii
C.mulmod(); // ir ii
}
function storeVals() {
C.push(VAR_POINTS); // p
for (let i=0; i<NPOINTS; i++) {
const MP = G2.affine(G2.mulScalar(P, bigInt(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
C.dup(1); // p MP[0][0] p
C.mstore(); // p
C.push(32); // 32 p
C.add(); // p+32
}
}
}
}
}
module.exports.abi = [
{
"constant": true,
"inputs": [
{
"name": "escalar",
"type": "uint256"
}
],
"name": "mulexp",
"outputs": [
{
"name": "",
"type": "uint256"
},
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "pure",
"type": "function"
}
];
module.exports.createCode = createCode;

View File

@@ -0,0 +1,64 @@
const bn128 = require("snarkjs").bn128;
const bigInt = require("snarkjs").bigInt;
const Web3Utils = require("web3-utils");
const F = bn128.Fr;
const SEED = "mimc";
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 iv = cn.mod(F.q);
return iv;
};
exports.getConstants = (seed, nRounds) => {
if (typeof seed === "undefined") seed = SEED;
if (typeof nRounds === "undefined") nRounds = NROUNDS;
const cts = new Array(nRounds);
let c = Web3Utils.keccak256(SEED);
for (let i=1; i<nRounds; i++) {
c = Web3Utils.keccak256(c);
const n1 = Web3Utils.toBN(c).mod(Web3Utils.toBN(F.q.toString()));
const c2 = Web3Utils.padLeft(Web3Utils.toHex(n1), 64);
cts[i] = bigInt(Web3Utils.toBN(c2).toString());
}
cts[0] = bigInt(0);
return cts;
};
const cts = exports.getConstants(SEED, 91);
exports.hash = (_x_in, _k) =>{
const x_in = bigInt(_x_in);
const k = bigInt(_k);
let r;
for (let i=0; i<NROUNDS; i++) {
const c = cts[i];
const t = (i==0) ? F.add(x_in, k) : F.add(F.add(r, k), c);
r = F.exp(t, 7);
}
return F.affine(F.add(r, k));
};
exports.multiHash = (arr, key) => {
let r;
if (typeof(key) === "undefined") {
r = F.zero;
} else {
r = key;
}
for (let i=0; i<arr.length; i++) {
r = F.add(
F.add(
r,
arr[i]
),
exports.hash(bigInt(arr[i]), r)
);
}
return F.affine(r);
};

View File

@@ -0,0 +1,114 @@
// Copyright (c) 2018 Jordi Baylina
// License: LGPL-3.0+
//
const Web3Utils = require("web3-utils");
const Contract = require("./evmasm");
function createCode(seed, n) {
let ci = Web3Utils.keccak256(seed);
const C = new Contract();
C.push(0x44);
C.push("0x00");
C.push("0x00");
C.calldatacopy();
C.push("0x0100000000000000000000000000000000000000000000000000000000");
C.push("0x00");
C.mload();
C.div();
C.push("0xd15ca109"); // MiMCpe7(uint256,uint256)
// C.push("0x8c42199e"); // MiMCpe7(uint256,uint256,uint256)
C.eq();
C.jmpi("start");
C.invalid();
C.label("start");
C.push("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"); // q
C.push("0x24");
C.mload(); // k q
C.dup(1); // q k q
C.dup(0); // q q k q
C.push("0x04");
C.mload(); // x q q k q
C.dup(3); // k x q q k q
C.addmod(); // t=x+k q k q
C.dup(1); // q t q k q
C.dup(0); // q q t q k q
C.dup(2); // t q q t q k q
C.dup(0); // t t q q t q k q
C.mulmod(); // a=t^2 q t q k q
C.dup(1); // q a q t q k q
C.dup(1); // a q a q t q k q
C.dup(0); // a a q a q t q k q
C.mulmod(); // b=t^4 a q t q k q
C.mulmod(); // c=t^6 t q k q
C.mulmod(); // r=t^7 k q
for (let i=0; i<n-1; i++) {
ci = Web3Utils.keccak256(ci);
C.dup(2); // q r k q
C.dup(0); // q q r k q
C.dup(0); // q q q r k q
C.swap(3); // r q q q k q
C.push(ci); // c r q q k q
C.addmod(); // s=c+r q q k q
C.dup(3); // k s q q k q
C.addmod(); // t=s+k q k q
C.dup(1); // q t q k q
C.dup(0); // q q t q k q
C.dup(2); // t q q t q k q
C.dup(0); // t t q q t q k q
C.mulmod(); // a=t^2 q t q k q
C.dup(1); // q a q t q k q
C.dup(1); // a q a q t q k q
C.dup(0); // a a q a q t q k q
C.mulmod(); // b=t^4 a q t q k q
C.mulmod(); // c=t^6 t q k q
C.mulmod(); // r=t^7 k q
}
C.addmod(); // res=t^7+k
C.push("0x00");
C.mstore(); // Save it to pos 0;
C.push("0x20");
C.push("0x00");
C.return();
return C.createTxData();
}
module.exports.abi = [
{
"constant": true,
"inputs": [
{
"name": "in_x",
"type": "uint256"
},
{
"name": "in_k",
"type": "uint256"
}
],
"name": "MiMCpe7",
"outputs": [
{
"name": "out_x",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "pure",
"type": "function"
}
];
module.exports.createCode = createCode;

View File

@@ -0,0 +1,3 @@
const mimc7 = require("./mimc7.js");
console.log("IV: "+mimc7.getIV().toString());

View File

@@ -0,0 +1,13 @@
const mimc7 = require("./mimc7.js");
const nRounds = 91;
let S = "[\n";
const cts = mimc7.getConstants();
for (let i=0; i<nRounds; i++) {
S = S + cts[i].toString();
if (i<nRounds-1) S = S + ",";
S=S+"\n";
}
S = S + "]\n";
console.log(S);

View File

@@ -0,0 +1,13 @@
const mimcGenContract = require("./mimc_gencontract");
const SEED = "mimc";
let nRounds;
if (typeof process.argv[2] != "undefined") {
nRounds = parseInt(process.argv[2]);
} else {
nRounds = 91;
}
console.log(mimcGenContract.createCode(SEED, nRounds));

View File

@@ -0,0 +1,86 @@
const bn128 = require("snarkjs").bn128;
const bigInt = require("snarkjs").bigInt;
const Web3Utils = require("web3-utils");
const F = bn128.Fr;
const SEED = "mimcsponge";
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 iv = cn.mod(F.q);
return iv;
};
exports.getConstants = (seed, nRounds) => {
if (typeof seed === "undefined") seed = SEED;
if (typeof nRounds === "undefined") nRounds = NROUNDS;
const cts = new Array(nRounds);
let c = Web3Utils.keccak256(SEED);
for (let i=1; i<nRounds; i++) {
c = Web3Utils.keccak256(c);
const n1 = Web3Utils.toBN(c).mod(Web3Utils.toBN(F.q.toString()));
const c2 = Web3Utils.padLeft(Web3Utils.toHex(n1), 64);
cts[i] = bigInt(Web3Utils.toBN(c2).toString());
}
cts[0] = bigInt(0);
cts[cts.length - 1] = bigInt(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);
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);
if (i < (NROUNDS - 1)) {
xR = xL;
xL = F.add(xR_tmp, F.exp(t, 5));
} else {
xR = F.add(xR_tmp, F.exp(t, 5));
}
}
return {
xL: F.affine(xL),
xR: F.affine(xR),
};
};
exports.multiHash = (arr, key, numOutputs) => {
if (typeof(numOutputs) === "undefined") {
numOutputs = 1;
}
if (typeof(key) === "undefined") {
key = F.zero;
}
let R = F.zero;
let C = F.zero;
for (let i=0; i<arr.length; i++) {
R = F.add(R, bigInt(arr[i]));
const S = exports.hash(R, C, key);
R = S.xL;
C = S.xR;
}
let outputs = [R];
for (let i=1; i < numOutputs; i++) {
const S = exports.hash(R, C, key);
R = S.xL;
C = S.xR;
outputs.push(R);
}
if (numOutputs == 1) {
return F.affine(outputs[0]);
} else {
return outputs.map(x => F.affine(x));
}
};

View File

@@ -0,0 +1,128 @@
// Copyright (c) 2018 Jordi Baylina
// License: LGPL-3.0+
//
const Web3Utils = require("web3-utils");
const Contract = require("./evmasm");
function createCode(seed, n) {
let ci = Web3Utils.keccak256(seed);
const C = new Contract();
C.push(0x64);
C.push("0x00");
C.push("0x00");
C.calldatacopy();
C.push("0x0100000000000000000000000000000000000000000000000000000000");
C.push("0x00");
C.mload();
C.div();
C.push("0x3f1a1187"); // MiMCSponge(uint256,uint256,uint256)
C.eq();
C.jmpi("start");
C.invalid();
C.label("start");
C.push("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"); // q
C.push("0x44");
C.mload(); // k q
C.push("0x04");
C.mload(); // xL k q
C.dup(2); // q xL k q
C.push("0x24");
C.mload(); // xR q xL k q
C.dup(1); // q xR q xL k q
C.dup(0); // q q xR q xL k q
C.dup(4); // xL q q xR q xL k q
C.dup(6); // k xL q q xR q xL k q
C.addmod(); // t=k+xL q xR q xL k q
C.dup(1); // q t q xR q xL k q
C.dup(0); // q q t q xR q xL k q
C.dup(2); // t q q t q xR q xL k q
C.dup(0); // t t q q t q xR q xL k q
C.mulmod(); // b=t^2 q t q xR q xL k q
C.dup(0); // b b q t q xR q xL k q
C.mulmod(); // c=t^4 t q xR q xL k q
C.mulmod(); // d=t^5 xR q xL k q
C.addmod(); // e=t^5+xR xL k q (for next round: xL xR k q)
for (let i=0; i<n-1; i++) {
if (i < n-2) {
ci = Web3Utils.keccak256(ci);
} else {
ci = "0x00";
}
C.swap(1); // xR xL k q
C.dup(3); // q xR xL k q
C.dup(3); // k q xR xL k q
C.dup(1); // q k q xR xL k q
C.dup(4); // xL q k q xR xL k q
C.push(ci); // ci xL q k q xR xL k q
C.addmod(); // a=ci+xL k q xR xL k q
C.addmod(); // t=a+k xR xL k q
C.dup(4); // q t xR xL k q
C.swap(1); // t q xR xL k q
C.dup(1); // q t q xR xL k q
C.dup(0); // q q t q xR xL k q
C.dup(2); // t q q t q xR xL k q
C.dup(0); // t t q q t q xR xL k q
C.mulmod(); // b=t^2 q t q xR xL k q
C.dup(0); // b b q t q xR xL k q
C.mulmod(); // c=t^4 t q xR xL k q
C.mulmod(); // d=t^5 xR xL k q
C.dup(4); // q d xR xL k q
C.swap(2); // xR d q xL k q
C.addmod(); // e=t^5+xR xL k q (for next round: xL xR k q)
}
C.push("0x20");
C.mstore(); // Save it to pos 0;
C.push("0x00");
C.mstore(); // Save it to pos 1;
C.push("0x40");
C.push("0x00");
C.return();
return C.createTxData();
}
module.exports.abi = [
{
"constant": true,
"inputs": [
{
"name": "xL_in",
"type": "uint256"
},
{
"name": "xR_in",
"type": "uint256"
},
{
"name": "k",
"type": "uint256"
}
],
"name": "MiMCSponge",
"outputs": [
{
"name": "xL",
"type": "uint256"
},
{
"name": "xR",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "pure",
"type": "function"
}
];
module.exports.createCode = createCode;

View File

@@ -0,0 +1,13 @@
const mimcsponge = require("./mimcsponge.js");
const nRounds = 220;
let S = "[\n";
const cts = mimcsponge.getConstants();
for (let i=0; i<nRounds; i++) {
S = S + cts[i].toString();
if (i<nRounds-1) S = S + ",";
S=S+"\n";
}
S = S + "]\n";
console.log(S);

View File

@@ -0,0 +1,13 @@
const mimcGenContract = require("./mimcsponge_gencontract");
const SEED = "mimcsponge";
let nRounds;
if (typeof process.argv[2] != "undefined") {
nRounds = parseInt(process.argv[2]);
} else {
nRounds = 220;
}
console.log(mimcGenContract.createCode(SEED, nRounds));

View File

@@ -0,0 +1,111 @@
const bn128 = require("snarkjs").bn128;
const bigInt = require("snarkjs").bigInt;
const babyJub = require("./babyjub");
const createBlakeHash = require("blake-hash");
const GENPOINT_PREFIX = "PedersenGenerator";
const windowSize = 4;
const nWindowsPerSegment = 50;
exports.hash = pedersenHash;
exports.getBasePoint = getBasePoint;
function pedersenHash(msg) {
const bitsPerSegment = windowSize*nWindowsPerSegment;
const bits = buffer2bits(msg);
const nSegments = Math.floor((bits.length - 1)/(windowSize*nWindowsPerSegment)) +1;
let accP = [bigInt.zero,bigInt.one];
for (let s=0; s<nSegments; s++) {
let nWindows;
if (s == nSegments-1) {
nWindows = Math.floor(((bits.length - (nSegments - 1)*bitsPerSegment) - 1) / windowSize) +1;
} else {
nWindows = nWindowsPerSegment;
}
let escalar = bigInt.zero;
let exp = bigInt.one;
for (let w=0; w<nWindows; w++) {
let o = s*bitsPerSegment + w*windowSize;
let acc = bigInt.one;
for (let b=0; ((b<windowSize-1)&&(o<bits.length)) ; b++) {
if (bits[o]) {
acc = acc.add( bigInt.one.shl(b) );
}
o++;
}
if (o<bits.length) {
if (bits[o]) {
acc = acc.neg();
}
o++;
}
escalar = escalar.add(acc.mul(exp));
exp = exp.shl(windowSize+1);
}
if (escalar.lesser(bigInt.zero)) {
escalar = babyJub.subOrder.add(escalar);
}
accP = babyJub.addPoint(accP, babyJub.mulPointEscalar(getBasePoint(s), escalar));
}
return babyJub.packPoint(accP);
}
let bases = [];
function getBasePoint(pointIdx) {
if (pointIdx<bases.length) return bases[pointIdx];
let p= null;
let tryIdx = 0;
while (p==null) {
const S = GENPOINT_PREFIX + "_" + padLeftZeros(pointIdx, 32) + "_" + padLeftZeros(tryIdx, 32);
const h = createBlakeHash("blake256").update(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++;
}
const p8 = babyJub.mulPointEscalar(p, 8);
if (!babyJub.inSubgroup(p8)) {
throw new Error("Point not in curve");
}
bases[pointIdx] = p8;
return p8;
}
function padLeftZeros(idx, n) {
let sidx = "" + idx;
while (sidx.length<n) sidx = "0"+sidx;
return sidx;
}
/*
Input a buffer
Returns an array of booleans. 0 is LSB of first byte and so on.
*/
function buffer2bits(buff) {
const res = new Array(buff.length*8);
for (let i=0; i<buff.length; i++) {
const b = buff[i];
res[i*8] = b & 0x01;
res[i*8+1] = b & 0x02;
res[i*8+2] = b & 0x04;
res[i*8+3] = b & 0x08;
res[i*8+4] = b & 0x10;
res[i*8+5] = b & 0x20;
res[i*8+6] = b & 0x40;
res[i*8+7] = b & 0x80;
}
return res;
}

View File

@@ -0,0 +1,13 @@
const pedersenHash = require("./pedersenHash.js");
let nBases;
if (typeof process.argv[2] != "undefined") {
nBases = parseInt(process.argv[2]);
} else {
nBases = 5;
}
for (let i=0; i < nBases; i++) {
const p = pedersenHash.getBasePoint(i);
console.log(`[${p[0]},${p[1]}]`);
}

View File

@@ -0,0 +1,116 @@
const bn128 = require("snarkjs").bn128;
const bigInt = require("snarkjs").bigInt;
const blake2b = require('blake2b');
const assert = require("assert");
const F = bn128.Fr;
const SEED = "poseidon";
const NROUNDSF = 8;
const NROUNDSP = 57;
const T = 6;
function getPseudoRandom(seed, n) {
const res = [];
let input = Buffer.from(seed);
let h = blake2b(32).update(input).digest()
while (res.length<n) {
const n = F.affine(bigInt.leBuff2int(h));
res.push(n);
h = blake2b(32).update(h).digest()
}
return res;
}
function allDifferent(v) {
for (let i=0; i<v.length; i++) {
if (v[i].isZero()) return false;
for (let j=i+1; j<v.length; j++) {
if (v[i].equals(v[j])) return false;
}
}
return true;
}
exports.getMatrix = (t, seed, nRounds) => {
if (typeof seed === "undefined") seed = SEED;
if (typeof nRounds === "undefined") nRounds = NROUNDSF + NROUNDSP;
if (typeof t === "undefined") t = T;
let nonce = "0000";
let cmatrix = getPseudoRandom(seed+"_matrix_"+nonce, t*2);
while (!allDifferent(cmatrix)) {
nonce = (Number(nonce)+1)+"";
while(nonce.length<4) nonce = "0"+nonce;
cmatrix = getPseudoRandom(seed+"_matrix_"+nonce, t*2);
}
const M = new Array(t);
for (let i=0; i<t; i++) {
M[i] = new Array(t);
for (let j=0; j<t; j++) {
M[i][j] = F.affine(F.inverse(F.sub(cmatrix[i], cmatrix[t+j])));
}
}
return M;
};
exports.getConstants = (t, seed, nRounds) => {
if (typeof seed === "undefined") seed = SEED;
if (typeof nRounds === "undefined") nRounds = NROUNDSF + NROUNDSP;
if (typeof t === "undefined") t = T;
const cts = getPseudoRandom(seed+"_constants", nRounds);
return cts;
};
function ark(state, c) {
for (let j=0; j<state.length; j++ ) {
state[j] = F.add(state[j], c);
}
}
function sigma(a) {
return F.mul(a, F.square(F.square(a,a)));
}
function mix(state, M) {
const newState = new Array(state.length);
for (let i=0; i<state.length; i++) {
newState[i] = F.zero;
for (let j=0; j<state.length; j++) {
newState[i] = F.add(newState[i], F.mul(M[i][j], state[j]) );
}
}
for (let i=0; i<state.length; i++) state[i] = newState[i];
}
exports.createHash = (t, nRoundsF, nRoundsP, seed) => {
if (typeof seed === "undefined") seed = SEED;
if (typeof nRoundsF === "undefined") nRoundsF = NROUNDSF;
if (typeof nRoundsP === "undefined") nRoundsP = NROUNDSP;
if (typeof t === "undefined") t = T;
assert(nRoundsF % 2 == 0);
const C = exports.getConstants(t, seed, nRoundsF + nRoundsP);
const M = exports.getMatrix(t, seed, nRoundsF + nRoundsP);
return function(inputs) {
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=inputs.length; i<t; i++) state[i] = F.zero;
for (let i=0; i< nRoundsF + nRoundsP; i++) {
ark(state, C[i]);
if ((i<nRoundsF/2) || (i >= nRoundsF/2 + nRoundsP)) {
for (let j=0; j<t; j++) state[j] = sigma(state[j]);
} else {
state[0] = sigma(state[0]);
}
mix(state, M);
}
return F.affine(state[0]);
};
};

View File

@@ -0,0 +1,180 @@
// Copyright (c) 2018 Jordi Baylina
// License: LGPL-3.0+
//
const Poseidon = require("./poseidon.js");
const Contract = require("./evmasm");
const SEED = "poseidon";
const NROUNDSF = 8;
const NROUNDSP = 57;
const T = 6;
function toHex256(a) {
let S = a.toString(16);
while (S.length < 64) S="0"+S;
return "0x" + S;
}
function createCode(t, nRoundsF, nRoundsP, seed) {
if (typeof seed === "undefined") seed = SEED;
if (typeof nRoundsF === "undefined") nRoundsF = NROUNDSF;
if (typeof nRoundsP === "undefined") nRoundsP = NROUNDSP;
if (typeof t === "undefined") t = T;
const K = Poseidon.getConstants(t, seed, nRoundsP + nRoundsF);
const M = Poseidon.getMatrix(t, seed, nRoundsP + nRoundsF);
const C = new Contract();
function saveM() {
for (let i=0; i<t; i++) {
for (let j=0; j<t; j++) {
C.push(toHex256(M[i][j]));
C.push((1+i*t+j)*32);
C.mstore();
}
}
}
function ark(r) {
C.push(toHex256(K[r])); // K, st, q
for (let i=0; i<t; i++) {
C.dup(1+t); // q, K, st, q
C.dup(1); // K, q, K, st, q
C.dup(3+i); // st[i], K, q, K, st, q
C.addmod(); // newSt[i], K, st, q
C.swap(2 + i); // xx, K, st, q
C.pop();
}
C.pop();
}
function sigma(p) {
// sq, q
C.dup(t); // q, st, q
C.dup(1+p); // st[p] , q , st, q
C.dup(1); // q, st[p] , q , st, q
C.dup(0); // q, q, st[p] , q , st, q
C.dup(2); // st[p] , q, q, st[p] , q , st, q
C.dup(0); // st[p] , st[p] , q, q, st[p] , q , st, q
C.mulmod(); // st2[p], q, st[p] , q , st, q
C.dup(0); // st2[p], st2[p], q, st[p] , q , st, q
C.mulmod(); // st4[p], st[p] , q , st, q
C.mulmod(); // st5[p], st, q
C.swap(1+p);
C.pop(); // newst, q
}
function mix() {
C.label("mix");
for (let i=0; i<t; i++) {
for (let j=0; j<t; j++) {
if (j==0) {
C.dup(i+t); // q, newSt, oldSt, q
C.push((1+i*t+j)*32);
C.mload(); // M, q, newSt, oldSt, q
C.dup(2+i+j); // oldSt[j], M, q, newSt, oldSt, q
C.mulmod(); // acc, newSt, oldSt, q
} else {
C.dup(1+i+t); // q, acc, newSt, oldSt, q
C.push((1+i*t+j)*32);
C.mload(); // M, q, acc, newSt, oldSt, q
C.dup(3+i+j); // oldSt[j], M, q, acc, newSt, oldSt, q
C.mulmod(); // aux, acc, newSt, oldSt, q
C.dup(2+i+t); // q, aux, acc, newSt, oldSt, q
C.swap(2); // acc, aux, q, newSt, oldSt, q
C.addmod(); // acc, newSt, oldSt, q
}
}
}
for (let i=0; i<t; i++) {
C.swap((t -i) + (t -i-1));
C.pop();
}
C.push(0);
C.mload();
C.jmp();
}
// Check selector
C.push("0x0100000000000000000000000000000000000000000000000000000000");
C.push(0);
C.calldataload();
C.div();
C.push("0xc4420fb4"); // poseidon(uint256[])
C.eq();
C.jmpi("start");
C.invalid();
C.label("start");
saveM();
C.push("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"); // q
// Load 6 values from the call data.
// The function has a single array param param
// [Selector (4)] [Pointer (32)][Length (32)] [data1 (32)] ....
// We ignore the pointer and the length and just load 6 values to the state
// (Stack positions 0-5) If the array is shorter, we just set zeros.
for (let i=0; i<t; i++) {
C.push(0x44+(0x20*(5-i)));
C.calldataload();
}
for (let i=0; i<nRoundsF+nRoundsP; i++) {
ark(i);
if ((i<nRoundsF/2) || (i>=nRoundsP+nRoundsF/2)) {
for (let j=0; j<t; j++) {
sigma(j);
}
} else {
sigma(0);
}
const strLabel = "aferMix"+i;
C._pushLabel(strLabel);
C.push(0);
C.mstore();
C.jmp("mix");
C.label(strLabel);
}
C.push("0x00");
C.mstore(); // Save it to pos 0;
C.push("0x20");
C.push("0x00");
C.return();
mix();
return C.createTxData();
}
module.exports.abi = [
{
"constant": true,
"inputs": [
{
"name": "input",
"type": "uint256[]"
}
],
"name": "poseidon",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "pure",
"type": "function"
}
];
module.exports.createCode = createCode;

View File

@@ -0,0 +1,16 @@
const Poseidon = require("./poseidon.js");
const C = Poseidon.getConstants();
let S = "[\n";
for (let i=0; i<C.length; i++) {
S = S + " " + C[i].toString();
if (i<C.length-1) S = S + ",";
S = S + "\n";
}
S=S+ "]\n";
console.log(S);

View File

@@ -0,0 +1,5 @@
const poseidonGenContract = require("./poseidon_gencontract");
console.log(poseidonGenContract.createCode(6, 8, 57));

View File

@@ -0,0 +1,22 @@
const Poseidon = require("./poseidon.js");
const M = Poseidon.getMatrix();
let S = "[\n ";
for (let i=0; i<M.length; i++) {
const LC = M[i];
S = S + "[\n";
for (let j=0; j<LC.length; j++) {
S = S + " " + M[i][j].toString();
if (j<LC.length-1) S = S + ",";
S = S + "\n";
}
S = S + " ]";
if (i<M.length-1) S = S + ",";
}
S=S+ "\n]\n";
console.log(S);

Some files were not shown because too many files have changed in this diff Show More