@ -0,0 +1 @@ |
|||||
|
/target |
@ -0,0 +1,32 @@ |
|||||
|
[package] |
||||
|
name = "grapevine_sonobe" |
||||
|
version = "0.1.0" |
||||
|
edition = "2021" |
||||
|
|
||||
|
[lib] |
||||
|
crate-type = ["cdylib", "rlib"] |
||||
|
|
||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
||||
|
|
||||
|
[dependencies] |
||||
|
ark-pallas = { version = "0.4.0", features = ["r1cs"] } |
||||
|
ark-vesta = {version="0.4.0", features=["r1cs"]} |
||||
|
ark-circom = { git = "https://github.com/arnaucube/circom-compat.git" } |
||||
|
ark-ec = "0.4.1" |
||||
|
ark-ff = "0.4.1" |
||||
|
ark-r1cs-std = { version = "0.4.0", default-features = false } |
||||
|
ark-relations = { version = "0.4.0", default-features = false } |
||||
|
ark-crypto-primitives = { version = "^0.4.0", default-features = false, features = [ |
||||
|
"r1cs", |
||||
|
"sponge", |
||||
|
"crh", |
||||
|
] } |
||||
|
ark-std = "0.4.0" |
||||
|
color-eyre = "0.6.2" |
||||
|
num-bigint = "0.4.3" |
||||
|
sonobe = { git = "https://github.com/privacy-scaling-explorations/sonobe", package = "folding-schemes", branch = "main" } |
||||
|
serde = "1.0.198" |
||||
|
serde_json = "1.0.116" |
||||
|
|
||||
|
[dev-dependencies] |
||||
|
lazy_static = "1.4.0" |
@ -0,0 +1,21 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
# if artifacts does not exist, make it |
||||
|
if [ ! -d "./artifacts" ]; then |
||||
|
mkdir -p ./artifacts |
||||
|
fi |
||||
|
|
||||
|
# install dependencies |
||||
|
yarn |
||||
|
|
||||
|
# compile circuit |
||||
|
|
||||
|
circom grapevine.circom \ |
||||
|
--r1cs \ |
||||
|
--wasm \ |
||||
|
--prime bn128 \ |
||||
|
--output ./artifacts |
||||
|
|
||||
|
# cleanup |
||||
|
mv ./artifacts/grapevine_js/grapevine.wasm ./artifacts |
||||
|
rm -rf ./artifacts/grapevine_js |
@ -0,0 +1,97 @@ |
|||||
|
pragma circom 2.1.6; |
||||
|
|
||||
|
include "node_modules/circomlib/circuits/poseidon.circom"; |
||||
|
include "node_modules/circomlib/circuits/mux1.circom"; |
||||
|
include "node_modules/circomlib/circuits/comparators.circom"; |
||||
|
include "node_modules/circomlib/circuits/gates.circom"; |
||||
|
include "./templates/chaff.circom"; |
||||
|
|
||||
|
template grapevine(num_felts) { |
||||
|
|
||||
|
// in_out schema |
||||
|
// 0: degrees of separation |
||||
|
// 1: secret hash from previous step |
||||
|
// 2: hash of username + secret hash from previous step |
||||
|
// 3: chaff |
||||
|
|
||||
|
signal input ivc_input[4]; |
||||
|
signal output ivc_output[4]; |
||||
|
|
||||
|
// private inputs |
||||
|
signal input phrase[num_felts]; // secret phrase, if first iteration |
||||
|
signal input usernames[2]; // prev username, current username |
||||
|
signal input auth_secrets[2]; // prev degree's user secret, current degree's user secret |
||||
|
|
||||
|
// name inputs from step_in |
||||
|
signal degrees_of_separation <== ivc_input[0]; |
||||
|
signal given_phrase_hash <== ivc_input[1]; |
||||
|
signal given_degree_secret_hash <== ivc_input[2]; |
||||
|
signal is_chaff_step <== ivc_input[3]; |
||||
|
|
||||
|
// determine whether degrees of separation from secret is zero |
||||
|
component is_degree_zero = IsZero(); |
||||
|
is_degree_zero.in <== degrees_of_separation; |
||||
|
|
||||
|
// compute poseidon hash of secret |
||||
|
// same as the word essentially |
||||
|
component phrase_hasher = Poseidon(num_felts); |
||||
|
phrase_hasher.inputs <== phrase; |
||||
|
|
||||
|
// mux between computed hash and previous iteration's hash to get phrase hash to use |
||||
|
// if degrees of separation = 0 use computed hash, else use hash from previous step |
||||
|
component phrase_mux = Mux1(); |
||||
|
phrase_mux.c[0] <== given_phrase_hash; |
||||
|
phrase_mux.c[1] <== phrase_hasher.out; |
||||
|
phrase_mux.s <== is_degree_zero.out; |
||||
|
|
||||
|
// compute hash of given degree secret |
||||
|
// H(H(preimage), username, auth_secret[0]) |
||||
|
// where preimage is muxed depending on whether degree N is 1 or > 1 |
||||
|
component degree_secret_hasher = Poseidon(3); |
||||
|
degree_secret_hasher.inputs[0] <== phrase_mux.out; |
||||
|
degree_secret_hasher.inputs[1] <== usernames[0]; |
||||
|
degree_secret_hasher.inputs[2] <== auth_secrets[0]; |
||||
|
|
||||
|
// compare computed degree secret hash to prev degree secret hash |
||||
|
component degree_secret_hash_match = IsEqual(); |
||||
|
degree_secret_hash_match.in[0] <== degree_secret_hasher.out; |
||||
|
degree_secret_hash_match.in[1] <== given_degree_secret_hash; |
||||
|
|
||||
|
// create boolean that is true if either is true: |
||||
|
// - given degree secret hash matches computed hash |
||||
|
// - is a chaff step |
||||
|
component degree_secret_match_or_chaff = OR(); |
||||
|
degree_secret_match_or_chaff.a <== degree_secret_hash_match.out; |
||||
|
degree_secret_match_or_chaff.b <== is_chaff_step; |
||||
|
|
||||
|
// create boolean that is muxes according to: |
||||
|
// - if degrees of separation = 0, always true (no check needed) |
||||
|
// - if degree of separation > 0, return output of degree_secret_match_or_chaff |
||||
|
component degree_secret_satisfied_mux = Mux1(); |
||||
|
degree_secret_satisfied_mux.c[0] <== degree_secret_match_or_chaff.out; |
||||
|
degree_secret_satisfied_mux.c[1] <== 1; |
||||
|
degree_secret_satisfied_mux.s <== is_degree_zero.out; |
||||
|
|
||||
|
// constrain degree_secret_satisfied_mux to be true |
||||
|
degree_secret_satisfied_mux.out === 1; |
||||
|
|
||||
|
// compute the next username hash |
||||
|
component next_degree_secret_hash = Poseidon(3); |
||||
|
next_degree_secret_hash.inputs[0] <== phrase_mux.out; |
||||
|
next_degree_secret_hash.inputs[1] <== usernames[1]; |
||||
|
next_degree_secret_hash.inputs[2] <== auth_secrets[1]; |
||||
|
|
||||
|
// mux step_out signal according to whether or not this is a chaff step |
||||
|
component chaff_mux = ChaffMux(); |
||||
|
chaff_mux.degrees_of_separation <== degrees_of_separation; |
||||
|
chaff_mux.given_phrase_hash <== given_phrase_hash; |
||||
|
chaff_mux.given_degree_secret_hash <== given_degree_secret_hash; |
||||
|
chaff_mux.is_chaff_step <== is_chaff_step; |
||||
|
chaff_mux.computed_phrase_hash <== phrase_mux.out; |
||||
|
chaff_mux.computed_degree_secret_hash <== next_degree_secret_hash.out; |
||||
|
|
||||
|
// wire output signals |
||||
|
ivc_output <== chaff_mux.out; |
||||
|
} |
||||
|
|
||||
|
component main { public [ivc_input] } = grapevine(6); |
@ -0,0 +1,16 @@ |
|||||
|
{ |
||||
|
"systemParams": "linux-x64-108", |
||||
|
"modulesFolders": [ |
||||
|
"node_modules" |
||||
|
], |
||||
|
"flags": [], |
||||
|
"linkedModules": [], |
||||
|
"topLevelPatterns": [ |
||||
|
"circomlib@^2.0.5" |
||||
|
], |
||||
|
"lockfileEntries": { |
||||
|
"circomlib@^2.0.5": "https://registry.yarnpkg.com/circomlib/-/circomlib-2.0.5.tgz#183c703e53ed7d011811842dbeeeb9819f4cc1d6" |
||||
|
}, |
||||
|
"files": [], |
||||
|
"artifacts": {} |
||||
|
} |
@ -0,0 +1,63 @@ |
|||||
|
{ |
||||
|
// Use IntelliSense to learn about possible attributes. |
||||
|
// Hover to view descriptions of existing attributes. |
||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 |
||||
|
"version": "0.2.0", |
||||
|
"configurations": [ |
||||
|
{ |
||||
|
"type": "pwa-node", |
||||
|
"request": "launch", |
||||
|
"name": "Launch Program", |
||||
|
"skipFiles": [ |
||||
|
"<node_internals>/**" |
||||
|
], |
||||
|
"program": "${workspaceFolder}/calcoptimizedposeidonconsts/test_poseidon.js", |
||||
|
"cwd": "${workspaceFolder}/calcoptimizedposeidonconsts" |
||||
|
}, |
||||
|
{ |
||||
|
"type": "pwa-node", |
||||
|
"request": "launch", |
||||
|
"name": "Tests", |
||||
|
"skipFiles": [ |
||||
|
"<node_internals>/**" |
||||
|
], |
||||
|
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", |
||||
|
"cwd": "${workspaceFolder}", |
||||
|
"args": ["test/smtverifier.js"] |
||||
|
}, |
||||
|
{ |
||||
|
"type": "pwa-node", |
||||
|
"request": "launch", |
||||
|
"name": "Test Poseidon", |
||||
|
"skipFiles": [ |
||||
|
"<node_internals>/**" |
||||
|
], |
||||
|
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", |
||||
|
"cwd": "${workspaceFolder}", |
||||
|
"args": ["test/poseidoncircuit.js"] |
||||
|
}, |
||||
|
{ |
||||
|
"type": "pwa-node", |
||||
|
"request": "launch", |
||||
|
"name": "Test binsum", |
||||
|
"skipFiles": [ |
||||
|
"<node_internals>/**" |
||||
|
], |
||||
|
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", |
||||
|
"cwd": "${workspaceFolder}", |
||||
|
"args": ["test/binsum.js"] |
||||
|
}, |
||||
|
{ |
||||
|
"type": "pwa-node", |
||||
|
"request": "launch", |
||||
|
"name": "Test babyjub", |
||||
|
"skipFiles": [ |
||||
|
"<node_internals>/**" |
||||
|
], |
||||
|
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", |
||||
|
"cwd": "${workspaceFolder}", |
||||
|
"args": ["test/babyjub.js"] |
||||
|
} |
||||
|
|
||||
|
] |
||||
|
} |
@ -0,0 +1,18 @@ |
|||||
|
# CircomLib |
||||
|
|
||||
|
## Description |
||||
|
|
||||
|
- This repository contains a library of circuit templates. |
||||
|
- All files are copyrighted under 2018 0KIMS association and part of the free software [circom](https://github.com/iden3/circom) (Zero Knowledge Circuit Compiler). |
||||
|
- You can read more about the circom language in [the circom documentation webpage](https://docs.circom.io/). |
||||
|
|
||||
|
## Organisation |
||||
|
|
||||
|
This respository contains 5 folders: |
||||
|
- `circuits`: it contains the implementation of different cryptographic primitives in circom language. |
||||
|
- `calcpedersenbases`: set of functions in JavaScript used to find a set of points in [Baby Jubjub](https://github.com/barryWhiteHat/baby_jubjub) elliptic curve that serve as basis for the [Pedersen Hash](https://github.com/zcash/zcash/issues/2234). |
||||
|
- `doc`: it contains some circuit schemes in ASCII (must be opened with Monodraw, an ASCII art editor for Mac). |
||||
|
- `src`: it contains similar implementation of circuits in JavaScript. |
||||
|
- `test`: tests. |
||||
|
|
||||
|
A description of the specific circuit templates for the `circuit` folder will be soon updated. |
@ -0,0 +1,830 @@ |
|||||
|
# CircomLib/Circuits |
||||
|
|
||||
|
## Description |
||||
|
|
||||
|
- This folder contains circuit templates for standard operations and many cryptographic primitives. |
||||
|
- Below you can find specifications of each function. In the representation of elements, there are three tyes: |
||||
|
- Binary |
||||
|
- String |
||||
|
- Field element (the field is specified in each case. We consider 2 possible fields: Fp and Fr, where p... and r... .) |
||||
|
|
||||
|
## Table of Contents |
||||
|
|
||||
|
[TOC] |
||||
|
|
||||
|
## Jordi |
||||
|
|
||||
|
* 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 |
||||
|
|
||||
|
## Circuits |
||||
|
|
||||
|
### sha256 |
||||
|
|
||||
|
Folder containing the implementation of sha256 hash circuit. |
||||
|
|
||||
|
### smt |
||||
|
|
||||
|
Folder containing the circuit implementation of Sparse Merkle Trees. |
||||
|
|
||||
|
### aliascheck |
||||
|
|
||||
|
- `AliasCheck()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### babyjub |
||||
|
|
||||
|
Arithmetic on [Baby Jubjub elliptic curve](https://github.com/barryWhiteHat/baby_jubjub) in twisted Edwards form. (TODO: Expose here the characteristics of the curve?) |
||||
|
|
||||
|
|
||||
|
- `BabyAdd()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
|
||||
|
It adds two points on the Baby Jubjub curve. More specifically, given two points P1 = (`x1`, `y1`) and P2 = (`x2`, `y2`) it returns a point P3 = (`xout`, `yout`) such that |
||||
|
|
||||
|
(`xout`, `yout`) = (`x1`,`y1`) + (`x2`,`y2`) |
||||
|
= ((`x1y2`+`y1x2`)/(1+`dx1x2y1y2`)),(`y1y2`-`ax1x2`)/(1-`dx1x2y1y2`)) |
||||
|
|
||||
|
- SCHEMA |
||||
|
``` |
||||
|
var a var d |
||||
|
| | |
||||
|
| | |
||||
|
______v_________v_______ |
||||
|
input x1 ----> | | |
||||
|
input y1 ----> | BabyAdd() | ----> output xout |
||||
|
input x2 ----> | | ----> output yout |
||||
|
input y2 ----> |________________________| |
||||
|
``` |
||||
|
|
||||
|
- INPUTS |
||||
|
|
||||
|
| Input | Representation | Description | | |
||||
|
| ------------- | ------------- | ------------- | ------------- | |
||||
|
| `x1` | Bigint | Field element of Fp | First coordinate of a point (x1, y1) on E. | |
||||
|
| `y1` | Bigint | Field element of Fp | Second coordinate of a point (x1, y1) on E. | |
||||
|
| `x2` | Bigint | Field element of Fp | First coordinate of a point (x2, y2) on E. | |
||||
|
| `y2` | Bigint | Field element of Fp | Second coordinate of a point (x2, y2) on E. | |
||||
|
|
||||
|
Requirement: at least `x1`!=`x2` or `y1`!=`y2`. |
||||
|
|
||||
|
- OUTPUT |
||||
|
|
||||
|
| Input | Representation | Description | | |
||||
|
| ------------- | ------------- | ------------- | ------------- | |
||||
|
| `xout` | Bigint | Field element of Fp | First coordinate of the addition point (xout, yout) = (x1, y1) + (x2, y2). | |
||||
|
| `yout` | Bigint | Field element of Fp | Second coordinate of the addition point (xout, yout) = (x1, y1) + (x2, y2). | |
||||
|
|
||||
|
- BENCHMARKS (constraints) |
||||
|
|
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `BabyDbl()` |
||||
|
- DESCRIPTION : doubles a point (`xout`,`yout`) = 2*(`x`,`y`). |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `BabyCheck()` |
||||
|
|
||||
|
- DESCRIPTION : checks if a given point is in the curve. |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `BabyPbk()` |
||||
|
|
||||
|
- DESCRIPTION: : given a private key, it returns the associated public key. |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
|
||||
|
### binsub |
||||
|
|
||||
|
- `BinSub(n)` |
||||
|
|
||||
|
- DESCRIPTION: binary substraction. |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### binsum |
||||
|
|
||||
|
- `nbits(a)` |
||||
|
|
||||
|
- DESCRIPTION : binary sum. |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `BinSum(n, ops)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### bitify |
||||
|
|
||||
|
- `Num2Bits()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Num2Bits_strict()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Bits2Num()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Bits2Num_strict()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Num2BitsNeg()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### comparators |
||||
|
|
||||
|
- `IsZero() ` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `IsEqual()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `ForceEqualIfEnabled()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `LessThan()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `GreaterThan()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `GreaterEqThan()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### compconstant |
||||
|
|
||||
|
- `CompConstant(ct)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### eddsa |
||||
|
|
||||
|
Edwards Digital Signature Algorithm in Baby Jubjbub (link a eddsa) |
||||
|
|
||||
|
- `EdDSAVerifier(n)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### eddsamimc |
||||
|
|
||||
|
- `EdDSAMiMCVerifier()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### eddsamimcsponge |
||||
|
|
||||
|
- `EdDSAMiMCSpongeVerifier()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### eddsaposeidon |
||||
|
|
||||
|
- `EdDSAPoseidonVerifier()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### escalarmul |
||||
|
|
||||
|
- `EscalarMulWindow(base, k)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `EscalarMul(n, base)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### escalarmulany |
||||
|
|
||||
|
- `Multiplexor2()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `BitElementMulAny()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `SegmentMulAny(n)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `EscalarMulAny(n)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### escalarmulfix |
||||
|
|
||||
|
- `WindowMulFix()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `SegmentMulFix(nWindows)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `EscalarMulFix(n, BASE)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### escalarmulw4table |
||||
|
|
||||
|
- `pointAdd` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `EscalarMulW4Table` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### gates |
||||
|
|
||||
|
- `XOR` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `AND` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `OR` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `NOT` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `NAND` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `NOR` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `MultiAND` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### mimc |
||||
|
|
||||
|
Implementation of MiMC-7 hash in Fp being... (link to description of the hash) |
||||
|
|
||||
|
- `MiMC7(nrounds)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `MultiMiMC7(nInputs, nRounds)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### mimcsponge |
||||
|
|
||||
|
- `MiMCSponge(nInputs, nRounds, nOutputs)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `MiMCFeistel(nrounds)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### montgomery |
||||
|
|
||||
|
- `Edwards2Montgomery()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Montgomery2Edwards()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `MontgomeryAdd()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `MontgomeryDouble()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### multiplexer |
||||
|
|
||||
|
- `log2(a)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `EscalarProduct(w)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Decoder(w)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Multiplexer(wIn, nIn)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### mux1 |
||||
|
|
||||
|
- `MultiMux1(n)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Mux1()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### mux2 |
||||
|
|
||||
|
- `MultiMux2(n)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Mux2()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### mux3 |
||||
|
|
||||
|
- `MultiMux3(n)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Mux3()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### mux4 |
||||
|
|
||||
|
- `MultiMux4(n)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Mux4()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### pedersen_old |
||||
|
|
||||
|
Old version of the Pedersen hash (do not use any |
||||
|
more?). |
||||
|
|
||||
|
### pedersen |
||||
|
|
||||
|
- `Window4()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Segment(nWindows)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Pedersen(n)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### pointbits |
||||
|
|
||||
|
- `sqrt(n)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Bits2Point()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Bits2Point_Strict()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Point2Bits` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Point2Bits_Strict` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### poseidon |
||||
|
|
||||
|
Implementation of Poseidon hash function (LINK) |
||||
|
|
||||
|
- `Sigma()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Ark(t, C, r)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Mix(t, M)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
- `Poseidon(nInputs)` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### sign |
||||
|
|
||||
|
- `Sign()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
||||
|
|
||||
|
### switcher |
||||
|
|
||||
|
- `Switcher()` |
||||
|
|
||||
|
- DESCRIPTION |
||||
|
- SCHEMA |
||||
|
- INPUT |
||||
|
- OUTPUT |
||||
|
- BENCHMARKS |
||||
|
- EXAMPLE |
@ -0,0 +1,33 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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; |
||||
|
} |
@ -0,0 +1,107 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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 input in; |
||||
|
signal output Ax; |
||||
|
signal output Ay; |
||||
|
|
||||
|
var BASE8[2] = [ |
||||
|
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]; |
||||
|
} |
@ -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/>. |
||||
|
*/ |
||||
|
|
||||
|
/* |
||||
|
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 |
||||
|
|
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
template BinSub(n) { |
||||
|
signal input in[2][n]; |
||||
|
signal output out[n]; |
||||
|
|
||||
|
signal aux; |
||||
|
|
||||
|
var lin = 2**n; |
||||
|
var lout = 0; |
||||
|
|
||||
|
var i; |
||||
|
|
||||
|
for (i=0; i<n; i++) { |
||||
|
lin = lin + in[0][i]*(2**i); |
||||
|
lin = lin - in[1][i]*(2**i); |
||||
|
} |
||||
|
|
||||
|
for (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; |
||||
|
} |
@ -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/>. |
||||
|
*/ |
||||
|
|
||||
|
/* |
||||
|
|
||||
|
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. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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; |
||||
|
|
||||
|
var e2; |
||||
|
|
||||
|
e2 = 1; |
||||
|
for (k=0; k<n; k++) { |
||||
|
for (j=0; j<ops; j++) { |
||||
|
lin += in[j][k] * e2; |
||||
|
} |
||||
|
e2 = e2 + e2; |
||||
|
} |
||||
|
|
||||
|
e2 = 1; |
||||
|
for (k=0; k<nout; k++) { |
||||
|
out[k] <-- (lin >> k) & 1; |
||||
|
|
||||
|
// Ensure out is binary |
||||
|
out[k] * (out[k] - 1) === 0; |
||||
|
|
||||
|
lout += out[k] * e2; |
||||
|
|
||||
|
e2 = e2+e2; |
||||
|
} |
||||
|
|
||||
|
// Ensure the sum; |
||||
|
|
||||
|
lin === lout; |
||||
|
} |
@ -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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "comparators.circom"; |
||||
|
include "aliascheck.circom"; |
||||
|
|
||||
|
|
||||
|
template Num2Bits(n) { |
||||
|
signal input in; |
||||
|
signal output out[n]; |
||||
|
var lc1=0; |
||||
|
|
||||
|
var e2=1; |
||||
|
for (var i = 0; i<n; i++) { |
||||
|
out[i] <-- (in >> i) & 1; |
||||
|
out[i] * (out[i] -1 ) === 0; |
||||
|
lc1 += out[i] * e2; |
||||
|
e2 = e2+e2; |
||||
|
} |
||||
|
|
||||
|
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; |
||||
|
|
||||
|
var e2 = 1; |
||||
|
for (var i = 0; i<n; i++) { |
||||
|
lc1 += in[i] * e2; |
||||
|
e2 = e2 + e2; |
||||
|
} |
||||
|
|
||||
|
lc1 ==> out; |
||||
|
} |
||||
|
|
||||
|
template Bits2Num_strict() { |
||||
|
signal input in[254]; |
||||
|
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; |
||||
|
} |
@ -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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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) { |
||||
|
assert(n <= 252); |
||||
|
signal input in[2]; |
||||
|
signal output out; |
||||
|
|
||||
|
component n2b = Num2Bits(n+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; |
||||
|
} |
||||
|
|
@ -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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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]; |
||||
|
} |
@ -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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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[2] = [ |
||||
|
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; |
||||
|
} |
@ -0,0 +1,124 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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[2] = [ |
||||
|
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; |
||||
|
} |
@ -0,0 +1,124 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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[2] = [ |
||||
|
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; |
||||
|
} |
@ -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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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*enabled === 0; |
||||
|
|
||||
|
// Calculate the h = H(R,A, msg) |
||||
|
|
||||
|
component hash = Poseidon(5); |
||||
|
|
||||
|
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*enabled === 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[2] = [ |
||||
|
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; |
||||
|
} |
@ -0,0 +1,166 @@ |
|||||
|
/* |
||||
|
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 ──────────────────────────────────────────┘ |
||||
|
|
||||
|
|
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "mux4.circom"; |
||||
|
include "escalarmulw4table.circom"; |
||||
|
include "babyjub.circom"; |
||||
|
|
||||
|
template EscalarMulWindow(base, k) { |
||||
|
|
||||
|
signal input in[2]; |
||||
|
signal input sel[4]; |
||||
|
signal output out[2]; |
||||
|
|
||||
|
var table[16][2]; |
||||
|
component mux; |
||||
|
component adder; |
||||
|
|
||||
|
var i; |
||||
|
|
||||
|
table = EscalarMulW4Table(base, k); |
||||
|
mux = MultiMux4(2); |
||||
|
adder = BabyAdd(); |
||||
|
|
||||
|
for (i=0; i<4; i++) { |
||||
|
sel[i] ==> mux.s[i]; |
||||
|
} |
||||
|
|
||||
|
for (i=0; i<16; i++) { |
||||
|
mux.c[0][i] <== table[i][0]; |
||||
|
mux.c[1][i] <== table[i][1]; |
||||
|
} |
||||
|
|
||||
|
in[0] ==> adder.x1; |
||||
|
in[1] ==> adder.y1; |
||||
|
|
||||
|
mux.out[0] ==> adder.x2; |
||||
|
mux.out[1] ==> adder.y2; |
||||
|
|
||||
|
adder.xout ==> out[0]; |
||||
|
adder.yout ==> out[1]; |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
|
||||
|
|
||||
|
┏━━━━━━━━━┓ ┏━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━┓ |
||||
|
┃ ┃ ┃ ┃ ┃ ┃ |
||||
|
inp ════▶┃Window(0)┃═════▶┃Window(1)┃════════ . . . . ═════════▶┃ Window(nBlocks-1) ┃═════▶ out |
||||
|
┃ ┃ ┃ ┃ ┃ ┃ |
||||
|
┗━━━━━━━━━┛ ┗━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━┛ |
||||
|
▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ |
||||
|
in[0]─────────┘ │ │ │ │ │ │ │ │ │ │ │ |
||||
|
in[1]───────────┘ │ │ │ │ │ │ │ │ │ │ |
||||
|
in[2]─────────────┘ │ │ │ │ │ │ │ 0 0 |
||||
|
in[3]───────────────┘ │ │ │ │ │ │ |
||||
|
in[4]──────────────────────────┘ │ │ │ │ │ |
||||
|
in[5]────────────────────────────┘ │ │ │ │ |
||||
|
in[6]──────────────────────────────┘ │ │ │ |
||||
|
in[7]────────────────────────────────┘ │ │ |
||||
|
. │ │ |
||||
|
. │ │ |
||||
|
in[n-2]─────────────────────────────────────────────────────────────────────┘ │ |
||||
|
in[n-1]───────────────────────────────────────────────────────────────────────┘ |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
template EscalarMul(n, base) { |
||||
|
signal input in[n]; |
||||
|
signal input inp[2]; // Point input to be added |
||||
|
signal output out[2]; |
||||
|
|
||||
|
var nBlocks = ((n-1)>>2)+1; |
||||
|
var i; |
||||
|
var j; |
||||
|
|
||||
|
component windows[nBlocks]; |
||||
|
|
||||
|
// Construct the windows |
||||
|
for (i=0; i<nBlocks; i++) { |
||||
|
windows[i] = EscalarMulWindow(base, i); |
||||
|
} |
||||
|
|
||||
|
// Connect the selectors |
||||
|
for (i=0; i<nBlocks; i++) { |
||||
|
for (j=0; j<4; j++) { |
||||
|
if (i*4+j >= n) { |
||||
|
windows[i].sel[j] <== 0; |
||||
|
} else { |
||||
|
windows[i].sel[j] <== in[i*4+j]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Start with generator |
||||
|
windows[0].in[0] <== inp[0]; |
||||
|
windows[0].in[1] <== inp[1]; |
||||
|
|
||||
|
for(i=0; i<nBlocks-1; i++) { |
||||
|
windows[i].out[0] ==> windows[i+1].in[0]; |
||||
|
windows[i].out[1] ==> windows[i+1].in[1]; |
||||
|
} |
||||
|
|
||||
|
windows[nBlocks-1].out[0] ==> out[0]; |
||||
|
windows[nBlocks-1].out[1] ==> out[1]; |
||||
|
} |
@ -0,0 +1,197 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "montgomery.circom"; |
||||
|
include "babyjub.circom"; |
||||
|
include "comparators.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]; |
||||
|
component zeropoint = IsZero(); |
||||
|
zeropoint.in <== p[0]; |
||||
|
|
||||
|
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) { |
||||
|
// force G8 point if input point is zero |
||||
|
segments[s].p[0] <== p[0] + (5299619240641551281634865583518297030282874472190772894086521144482721001553 - p[0])*zeropoint.out; |
||||
|
segments[s].p[1] <== p[1] + (16950150798460657717958625567821834550301663161624707787222815936182638968203 - p[1])*zeropoint.out; |
||||
|
} 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]*(1-zeropoint.out) ==> out[0]; |
||||
|
segments[0].out[1]+(1-segments[0].out[1])*zeropoint.out ==> out[1]; |
||||
|
} else { |
||||
|
adders[nsegments-2].xout*(1-zeropoint.out) ==> out[0]; |
||||
|
adders[nsegments-2].yout+(1-adders[nsegments-2].yout)*zeropoint.out ==> out[1]; |
||||
|
} |
||||
|
} |
@ -0,0 +1,299 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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]; |
||||
|
} |
||||
|
for (j=0; j<3; j++) { |
||||
|
windows[i].in[j] <== e[3*i+j]; |
||||
|
} |
||||
|
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 (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]; |
||||
|
} |
||||
|
} |
@ -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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
|
||||
|
function EscalarMulW4Table(base, k) { |
||||
|
var out[16][2]; |
||||
|
|
||||
|
var i; |
||||
|
var p[2]; |
||||
|
|
||||
|
var dbl[2] = 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]; |
||||
|
} |
||||
|
|
||||
|
return out; |
||||
|
} |
@ -0,0 +1,96 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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; |
||||
|
component and1; |
||||
|
component and2; |
||||
|
component ands[2]; |
||||
|
if (n==1) { |
||||
|
out <== in[0]; |
||||
|
} else if (n==2) { |
||||
|
and1 = AND(); |
||||
|
and1.a <== in[0]; |
||||
|
and1.b <== in[1]; |
||||
|
out <== and1.out; |
||||
|
} else { |
||||
|
and2 = AND(); |
||||
|
var n1 = n\2; |
||||
|
var n2 = n-n\2; |
||||
|
ands[0] = MultiAND(n1); |
||||
|
ands[1] = MultiAND(n2); |
||||
|
var i; |
||||
|
for (i=0; i<n1; i++) ands[0].in[i] <== in[i]; |
||||
|
for (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; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
@ -0,0 +1,156 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
template MiMC7(nrounds) { |
||||
|
signal input x_in; |
||||
|
signal input k; |
||||
|
signal output out; |
||||
|
|
||||
|
var c[91] = [ |
||||
|
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]; |
||||
|
} |
@ -0,0 +1,293 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
// 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]; |
||||
|
|
||||
|
var i; |
||||
|
|
||||
|
// S = R||C |
||||
|
component S[nInputs + nOutputs - 1]; |
||||
|
|
||||
|
for (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 (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; |
||||
|
|
||||
|
// doesn't contain the first and last round constants, which are always zero |
||||
|
var c_partial[218] = [ |
||||
|
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 |
||||
|
]; |
||||
|
|
||||
|
var t; |
||||
|
signal t2[nrounds]; |
||||
|
signal t4[nrounds]; |
||||
|
signal xL[nrounds-1]; |
||||
|
signal xR[nrounds-1]; |
||||
|
|
||||
|
var c; |
||||
|
for (var i=0; i<nrounds; i++) { |
||||
|
if ((i == 0) || (i == nrounds - 1)) { |
||||
|
c = 0; |
||||
|
} else { |
||||
|
c = c_partial[i - 1]; |
||||
|
} |
||||
|
t = (i==0) ? k+xL_in : k + xL[i-1] + c; |
||||
|
t2[i] <== t*t; |
||||
|
t4[i] <== t2[i]*t2[i]; |
||||
|
if (i<nrounds-1) { |
||||
|
var aux = (i==0) ? xR_in : xR[i-1] ; |
||||
|
xL[i] <== aux + 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]; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,142 @@ |
|||||
|
/* |
||||
|
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 |
||||
|
|
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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]; |
||||
|
} |
@ -0,0 +1,115 @@ |
|||||
|
/* |
||||
|
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; |
||||
|
} |
||||
|
*/ |
||||
|
|
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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; |
||||
|
} |
@ -0,0 +1,48 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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; |
||||
|
} |
@ -0,0 +1,63 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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; |
||||
|
} |
@ -0,0 +1,75 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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; |
||||
|
} |
@ -0,0 +1,119 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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; |
||||
|
} |
@ -0,0 +1,257 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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(); |
||||
|
for (j=0; j<4; j++) { |
||||
|
windows[i].in[j] <== in[4*i+j]; |
||||
|
} |
||||
|
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]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
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[10][2] = [ |
||||
|
[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]; |
||||
|
} |
||||
|
} |
||||
|
|
@ -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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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[10][2] = [ |
||||
|
[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]; |
||||
|
} |
@ -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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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 < 0 ) { |
||||
|
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; |
||||
|
} |
@ -0,0 +1,208 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "./poseidon_constants.circom"; |
||||
|
|
||||
|
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, r) { |
||||
|
signal input in[t]; |
||||
|
signal output out[t]; |
||||
|
|
||||
|
for (var i=0; i<t; i++) { |
||||
|
out[i] <== in[i] + C[i + r]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
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 += M[j][i]*in[j]; |
||||
|
} |
||||
|
out[i] <== lc; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template MixLast(t, M, s) { |
||||
|
signal input in[t]; |
||||
|
signal output out; |
||||
|
|
||||
|
var lc = 0; |
||||
|
for (var j=0; j<t; j++) { |
||||
|
lc += M[j][s]*in[j]; |
||||
|
} |
||||
|
out <== lc; |
||||
|
} |
||||
|
|
||||
|
template MixS(t, S, r) { |
||||
|
signal input in[t]; |
||||
|
signal output out[t]; |
||||
|
|
||||
|
|
||||
|
var lc = 0; |
||||
|
for (var i=0; i<t; i++) { |
||||
|
lc += S[(t*2-1)*r+i]*in[i]; |
||||
|
} |
||||
|
out[0] <== lc; |
||||
|
for (var i=1; i<t; i++) { |
||||
|
out[i] <== in[i] + in[0] * S[(t*2-1)*r + t + i -1]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template PoseidonEx(nInputs, nOuts) { |
||||
|
signal input inputs[nInputs]; |
||||
|
signal input initialState; |
||||
|
signal output out[nOuts]; |
||||
|
|
||||
|
// Using recommended parameters from whitepaper https://eprint.iacr.org/2019/458.pdf (table 2, table 8) |
||||
|
// Generated by https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/calc_round_numbers.py |
||||
|
// And rounded up to nearest integer that divides by t |
||||
|
var N_ROUNDS_P[16] = [56, 57, 56, 60, 60, 63, 64, 63, 60, 66, 60, 65, 70, 60, 64, 68]; |
||||
|
var t = nInputs + 1; |
||||
|
var nRoundsF = 8; |
||||
|
var nRoundsP = N_ROUNDS_P[t - 2]; |
||||
|
var C[t*nRoundsF + nRoundsP] = POSEIDON_C(t); |
||||
|
var S[ N_ROUNDS_P[t-2] * (t*2-1) ] = POSEIDON_S(t); |
||||
|
var M[t][t] = POSEIDON_M(t); |
||||
|
var P[t][t] = POSEIDON_P(t); |
||||
|
|
||||
|
component ark[nRoundsF]; |
||||
|
component sigmaF[nRoundsF][t]; |
||||
|
component sigmaP[nRoundsP]; |
||||
|
component mix[nRoundsF-1]; |
||||
|
component mixS[nRoundsP]; |
||||
|
component mixLast[nOuts]; |
||||
|
|
||||
|
|
||||
|
ark[0] = Ark(t, C, 0); |
||||
|
for (var j=0; j<t; j++) { |
||||
|
if (j>0) { |
||||
|
ark[0].in[j] <== inputs[j-1]; |
||||
|
} else { |
||||
|
ark[0].in[j] <== initialState; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for (var r = 0; r < nRoundsF\2-1; r++) { |
||||
|
for (var j=0; j<t; j++) { |
||||
|
sigmaF[r][j] = Sigma(); |
||||
|
if(r==0) { |
||||
|
sigmaF[r][j].in <== ark[0].out[j]; |
||||
|
} else { |
||||
|
sigmaF[r][j].in <== mix[r-1].out[j]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
ark[r+1] = Ark(t, C, (r+1)*t); |
||||
|
for (var j=0; j<t; j++) { |
||||
|
ark[r+1].in[j] <== sigmaF[r][j].out; |
||||
|
} |
||||
|
|
||||
|
mix[r] = Mix(t,M); |
||||
|
for (var j=0; j<t; j++) { |
||||
|
mix[r].in[j] <== ark[r+1].out[j]; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
for (var j=0; j<t; j++) { |
||||
|
sigmaF[nRoundsF\2-1][j] = Sigma(); |
||||
|
sigmaF[nRoundsF\2-1][j].in <== mix[nRoundsF\2-2].out[j]; |
||||
|
} |
||||
|
|
||||
|
ark[nRoundsF\2] = Ark(t, C, (nRoundsF\2)*t ); |
||||
|
for (var j=0; j<t; j++) { |
||||
|
ark[nRoundsF\2].in[j] <== sigmaF[nRoundsF\2-1][j].out; |
||||
|
} |
||||
|
|
||||
|
mix[nRoundsF\2-1] = Mix(t,P); |
||||
|
for (var j=0; j<t; j++) { |
||||
|
mix[nRoundsF\2-1].in[j] <== ark[nRoundsF\2].out[j]; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
for (var r = 0; r < nRoundsP; r++) { |
||||
|
sigmaP[r] = Sigma(); |
||||
|
if (r==0) { |
||||
|
sigmaP[r].in <== mix[nRoundsF\2-1].out[0]; |
||||
|
} else { |
||||
|
sigmaP[r].in <== mixS[r-1].out[0]; |
||||
|
} |
||||
|
|
||||
|
mixS[r] = MixS(t, S, r); |
||||
|
for (var j=0; j<t; j++) { |
||||
|
if (j==0) { |
||||
|
mixS[r].in[j] <== sigmaP[r].out + C[(nRoundsF\2+1)*t + r]; |
||||
|
} else { |
||||
|
if (r==0) { |
||||
|
mixS[r].in[j] <== mix[nRoundsF\2-1].out[j]; |
||||
|
} else { |
||||
|
mixS[r].in[j] <== mixS[r-1].out[j]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for (var r = 0; r < nRoundsF\2-1; r++) { |
||||
|
for (var j=0; j<t; j++) { |
||||
|
sigmaF[nRoundsF\2 + r][j] = Sigma(); |
||||
|
if (r==0) { |
||||
|
sigmaF[nRoundsF\2 + r][j].in <== mixS[nRoundsP-1].out[j]; |
||||
|
} else { |
||||
|
sigmaF[nRoundsF\2 + r][j].in <== mix[nRoundsF\2+r-1].out[j]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
ark[ nRoundsF\2 + r + 1] = Ark(t, C, (nRoundsF\2+1)*t + nRoundsP + r*t ); |
||||
|
for (var j=0; j<t; j++) { |
||||
|
ark[nRoundsF\2 + r + 1].in[j] <== sigmaF[nRoundsF\2 + r][j].out; |
||||
|
} |
||||
|
|
||||
|
mix[nRoundsF\2 + r] = Mix(t,M); |
||||
|
for (var j=0; j<t; j++) { |
||||
|
mix[nRoundsF\2 + r].in[j] <== ark[nRoundsF\2 + r + 1].out[j]; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
for (var j=0; j<t; j++) { |
||||
|
sigmaF[nRoundsF-1][j] = Sigma(); |
||||
|
sigmaF[nRoundsF-1][j].in <== mix[nRoundsF-2].out[j]; |
||||
|
} |
||||
|
|
||||
|
for (var i=0; i<nOuts; i++) { |
||||
|
mixLast[i] = MixLast(t,M,i); |
||||
|
for (var j=0; j<t; j++) { |
||||
|
mixLast[i].in[j] <== sigmaF[nRoundsF-1][j].out; |
||||
|
} |
||||
|
out[i] <== mixLast[i].out; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
template Poseidon(nInputs) { |
||||
|
signal input inputs[nInputs]; |
||||
|
signal output out; |
||||
|
|
||||
|
component pEx = PoseidonEx(nInputs, 1); |
||||
|
pEx.initialState <== 0; |
||||
|
for (var i=0; i<nInputs; i++) { |
||||
|
pEx.inputs[i] <== inputs[i]; |
||||
|
} |
||||
|
out <== pEx.out[0]; |
||||
|
} |
@ -0,0 +1,97 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "./poseidon_constants.circom"; |
||||
|
|
||||
|
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, r) { |
||||
|
signal input in[t]; |
||||
|
signal output out[t]; |
||||
|
|
||||
|
for (var i=0; i<t; i++) { |
||||
|
out[i] <== in[i] + C[i + r]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
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 += M[i][j]*in[j]; |
||||
|
} |
||||
|
out[i] <== lc; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template Poseidon(nInputs) { |
||||
|
signal input inputs[nInputs]; |
||||
|
signal output out; |
||||
|
|
||||
|
// Using recommended parameters from whitepaper https://eprint.iacr.org/2019/458.pdf (table 2, table 8) |
||||
|
// Generated by https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/calc_round_numbers.py |
||||
|
// And rounded up to nearest integer that divides by t |
||||
|
var N_ROUNDS_P[16] = [56, 57, 56, 60, 60, 63, 64, 63, 60, 66, 60, 65, 70, 60, 64, 68]; |
||||
|
var t = nInputs + 1; |
||||
|
var nRoundsF = 8; |
||||
|
var nRoundsP = N_ROUNDS_P[t - 2]; |
||||
|
var C[t*(nRoundsF + nRoundsP)] = POSEIDON_C(t); |
||||
|
var M[t][t] = POSEIDON_M(t); |
||||
|
|
||||
|
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, t*i); |
||||
|
for (var j=0; j<t; j++) { |
||||
|
if (i==0) { |
||||
|
if (j>0) { |
||||
|
ark[i].in[j] <== inputs[j-1]; |
||||
|
} 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; |
||||
|
mix[i] = Mix(t, M); |
||||
|
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; |
||||
|
mix[i] = Mix(t, M); |
||||
|
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]; |
||||
|
} |
@ -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/>. |
||||
|
*/ |
||||
|
|
||||
|
/* 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 |
||||
|
|
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
template Ch_t(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]; |
||||
|
} |
||||
|
} |
@ -0,0 +1,53 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
template H(x) { |
||||
|
signal output out[32]; |
||||
|
var c[8] = [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[64] = [ |
||||
|
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; |
||||
|
} |
||||
|
} |
@ -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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "sha256_2.circom"; |
||||
|
|
||||
|
template Main() { |
||||
|
signal input a; |
||||
|
signal 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(); |
@ -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/>. |
||||
|
*/ |
||||
|
|
||||
|
/* 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 |
||||
|
|
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
template Maj_t(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]; |
||||
|
} |
||||
|
} |
@ -0,0 +1,28 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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 ]; |
||||
|
} |
||||
|
} |
@ -0,0 +1,81 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "constants.circom"; |
||||
|
include "sha256compression.circom"; |
||||
|
|
||||
|
template Sha256(nBits) { |
||||
|
signal input in[nBits]; |
||||
|
signal output out[256]; |
||||
|
|
||||
|
var i; |
||||
|
var k; |
||||
|
var nBlocks; |
||||
|
var bitsLastBlock; |
||||
|
|
||||
|
|
||||
|
nBlocks = ((nBits + 64)\512)+1; |
||||
|
|
||||
|
signal paddedIn[nBlocks*512]; |
||||
|
|
||||
|
for (k=0; k<nBits; k++) { |
||||
|
paddedIn[k] <== in[k]; |
||||
|
} |
||||
|
paddedIn[nBits] <== 1; |
||||
|
|
||||
|
for (k=nBits+1; k<nBlocks*512-64; k++) { |
||||
|
paddedIn[k] <== 0; |
||||
|
} |
||||
|
|
||||
|
for (k = 0; k< 64; k++) { |
||||
|
paddedIn[nBlocks*512 - k -1] <== (nBits >> k)&1; |
||||
|
} |
||||
|
|
||||
|
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 sha256compression[nBlocks]; |
||||
|
|
||||
|
for (i=0; i<nBlocks; i++) { |
||||
|
|
||||
|
sha256compression[i] = Sha256compression() ; |
||||
|
|
||||
|
if (i==0) { |
||||
|
for (k=0; k<32; k++ ) { |
||||
|
sha256compression[i].hin[0*32+k] <== ha0.out[k]; |
||||
|
sha256compression[i].hin[1*32+k] <== hb0.out[k]; |
||||
|
sha256compression[i].hin[2*32+k] <== hc0.out[k]; |
||||
|
sha256compression[i].hin[3*32+k] <== hd0.out[k]; |
||||
|
sha256compression[i].hin[4*32+k] <== he0.out[k]; |
||||
|
sha256compression[i].hin[5*32+k] <== hf0.out[k]; |
||||
|
sha256compression[i].hin[6*32+k] <== hg0.out[k]; |
||||
|
sha256compression[i].hin[7*32+k] <== hh0.out[k]; |
||||
|
} |
||||
|
} else { |
||||
|
for (k=0; k<32; k++ ) { |
||||
|
sha256compression[i].hin[32*0+k] <== sha256compression[i-1].out[32*0+31-k]; |
||||
|
sha256compression[i].hin[32*1+k] <== sha256compression[i-1].out[32*1+31-k]; |
||||
|
sha256compression[i].hin[32*2+k] <== sha256compression[i-1].out[32*2+31-k]; |
||||
|
sha256compression[i].hin[32*3+k] <== sha256compression[i-1].out[32*3+31-k]; |
||||
|
sha256compression[i].hin[32*4+k] <== sha256compression[i-1].out[32*4+31-k]; |
||||
|
sha256compression[i].hin[32*5+k] <== sha256compression[i-1].out[32*5+31-k]; |
||||
|
sha256compression[i].hin[32*6+k] <== sha256compression[i-1].out[32*6+31-k]; |
||||
|
sha256compression[i].hin[32*7+k] <== sha256compression[i-1].out[32*7+31-k]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for (k=0; k<512; k++) { |
||||
|
sha256compression[i].inp[k] <== paddedIn[i*512+k]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for (k=0; k<256; k++) { |
||||
|
out[k] <== sha256compression[nBlocks-1].out[k]; |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,91 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "constants.circom"; |
||||
|
include "sha256compression.circom"; |
||||
|
include "../bitify.circom"; |
||||
|
|
||||
|
template Sha256_2() { |
||||
|
signal input a; |
||||
|
signal input b; |
||||
|
signal output out; |
||||
|
|
||||
|
var i; |
||||
|
var k; |
||||
|
|
||||
|
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() ; |
||||
|
|
||||
|
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); |
||||
|
|
||||
|
for (k=0; k<32; k++ ) { |
||||
|
sha256compression.hin[0*32+k] <== ha0.out[k]; |
||||
|
sha256compression.hin[1*32+k] <== hb0.out[k]; |
||||
|
sha256compression.hin[2*32+k] <== hc0.out[k]; |
||||
|
sha256compression.hin[3*32+k] <== hd0.out[k]; |
||||
|
sha256compression.hin[4*32+k] <== he0.out[k]; |
||||
|
sha256compression.hin[5*32+k] <== hf0.out[k]; |
||||
|
sha256compression.hin[6*32+k] <== hg0.out[k]; |
||||
|
sha256compression.hin[7*32+k] <== hh0.out[k]; |
||||
|
} |
||||
|
|
||||
|
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; |
||||
|
} |
@ -0,0 +1,166 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "constants.circom"; |
||||
|
include "t1.circom"; |
||||
|
include "t2.circom"; |
||||
|
include "../binsum.circom"; |
||||
|
include "sigmaplus.circom"; |
||||
|
include "sha256compression_function.circom"; |
||||
|
|
||||
|
|
||||
|
template Sha256compression() { |
||||
|
signal input hin[256]; |
||||
|
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 outCalc[256] = sha256compression(hin, inp); |
||||
|
|
||||
|
var i; |
||||
|
for (i=0; i<256; i++) out[i] <-- outCalc[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 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]; |
||||
|
} |
||||
|
|
||||
|
for (k=0; k<32; k++) { |
||||
|
w[t][k] <== sigmaPlus[t-16].out[k]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for (k=0; k<32; k++ ) { |
||||
|
a[0][k] <== hin[k]; |
||||
|
b[0][k] <== hin[32*1 + k]; |
||||
|
c[0][k] <== hin[32*2 + k]; |
||||
|
d[0][k] <== hin[32*3 + k]; |
||||
|
e[0][k] <== hin[32*4 + k]; |
||||
|
f[0][k] <== hin[32*5 + k]; |
||||
|
g[0][k] <== hin[32*6 + k]; |
||||
|
h[0][k] <== hin[32*7 + 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] <== hin[32*0+k]; |
||||
|
fsum[0].in[1][k] <== a[64][k]; |
||||
|
fsum[1].in[0][k] <== hin[32*1+k]; |
||||
|
fsum[1].in[1][k] <== b[64][k]; |
||||
|
fsum[2].in[0][k] <== hin[32*2+k]; |
||||
|
fsum[2].in[1][k] <== c[64][k]; |
||||
|
fsum[3].in[0][k] <== hin[32*3+k]; |
||||
|
fsum[3].in[1][k] <== d[64][k]; |
||||
|
fsum[4].in[0][k] <== hin[32*4+k]; |
||||
|
fsum[4].in[1][k] <== e[64][k]; |
||||
|
fsum[5].in[0][k] <== hin[32*5+k]; |
||||
|
fsum[5].in[1][k] <== f[64][k]; |
||||
|
fsum[6].in[0][k] <== hin[32*6+k]; |
||||
|
fsum[6].in[1][k] <== g[64][k]; |
||||
|
fsum[7].in[0][k] <== hin[32*7+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]; |
||||
|
} |
||||
|
} |
@ -0,0 +1,112 @@ |
|||||
|
// signal input hin[256]; |
||||
|
// signal input inp[512]; |
||||
|
// signal output out[256]; |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
function rrot(x, n) { |
||||
|
return ((x >> n) | (x << (32-n))) & 0xFFFFFFFF; |
||||
|
} |
||||
|
|
||||
|
function bsigma0(x) { |
||||
|
return rrot(x,2) ^ rrot(x,13) ^ rrot(x,22); |
||||
|
} |
||||
|
|
||||
|
function bsigma1(x) { |
||||
|
return rrot(x,6) ^ rrot(x,11) ^ rrot(x,25); |
||||
|
} |
||||
|
|
||||
|
function ssigma0(x) { |
||||
|
return rrot(x,7) ^ rrot(x,18) ^ (x >> 3); |
||||
|
} |
||||
|
|
||||
|
function ssigma1(x) { |
||||
|
return rrot(x,17) ^ rrot(x,19) ^ (x >> 10); |
||||
|
} |
||||
|
|
||||
|
function Maj(x, y, z) { |
||||
|
return (x&y) ^ (x&z) ^ (y&z); |
||||
|
} |
||||
|
|
||||
|
function Ch(x, y, z) { |
||||
|
return (x & y) ^ ((0xFFFFFFFF ^x) & z); |
||||
|
} |
||||
|
|
||||
|
function sha256K(i) { |
||||
|
var k[64] = [ |
||||
|
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 |
||||
|
]; |
||||
|
return k[i]; |
||||
|
} |
||||
|
|
||||
|
function sha256compression(hin, inp) { |
||||
|
var H[8]; |
||||
|
var a; |
||||
|
var b; |
||||
|
var c; |
||||
|
var d; |
||||
|
var e; |
||||
|
var f; |
||||
|
var g; |
||||
|
var h; |
||||
|
var out[256]; |
||||
|
for (var i=0; i<8; i++) { |
||||
|
H[i] = 0; |
||||
|
for (var j=0; j<32; j++) { |
||||
|
H[i] += hin[i*32+j] << j; |
||||
|
} |
||||
|
} |
||||
|
a=H[0]; |
||||
|
b=H[1]; |
||||
|
c=H[2]; |
||||
|
d=H[3]; |
||||
|
e=H[4]; |
||||
|
f=H[5]; |
||||
|
g=H[6]; |
||||
|
h=H[7]; |
||||
|
var w[64]; |
||||
|
var T1; |
||||
|
var T2; |
||||
|
for (var i=0; i<64; i++) { |
||||
|
if (i<16) { |
||||
|
w[i]=0; |
||||
|
for (var j=0; j<32; j++) { |
||||
|
w[i] += inp[i*32+31-j]<<j; |
||||
|
} |
||||
|
} else { |
||||
|
w[i] = (ssigma1(w[i-2]) + w[i-7] + ssigma0(w[i-15]) + w[i-16]) & 0xFFFFFFFF; |
||||
|
} |
||||
|
T1 = (h + bsigma1(e) + Ch(e,f,g) + sha256K(i) + w[i]) & 0xFFFFFFFF; |
||||
|
T2 = (bsigma0(a) + Maj(a,b,c)) & 0xFFFFFFFF; |
||||
|
|
||||
|
h=g; |
||||
|
g=f; |
||||
|
f=e; |
||||
|
e=(d+T1) & 0xFFFFFFFF; |
||||
|
d=c; |
||||
|
c=b; |
||||
|
b=a; |
||||
|
a=(T1+T2) & 0xFFFFFFFF; |
||||
|
|
||||
|
} |
||||
|
H[0] = H[0] + a; |
||||
|
H[1] = H[1] + b; |
||||
|
H[2] = H[2] + c; |
||||
|
H[3] = H[3] + d; |
||||
|
H[4] = H[4] + e; |
||||
|
H[5] = H[5] + f; |
||||
|
H[6] = H[6] + g; |
||||
|
H[7] = H[7] + h; |
||||
|
for (var i=0; i<8; i++) { |
||||
|
for (var j=0; j<32; j++) { |
||||
|
out[i*32+31-j] = (H[i] >> j) & 1; |
||||
|
} |
||||
|
} |
||||
|
return out; |
||||
|
} |
@ -0,0 +1,33 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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 ]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
@ -0,0 +1,77 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "xor3.circom"; |
||||
|
include "rotate.circom"; |
||||
|
include "shift.circom"; |
||||
|
|
||||
|
template SmallSigma(ra, rb, rc) { |
||||
|
signal input in[32]; |
||||
|
signal output out[32]; |
||||
|
var k; |
||||
|
|
||||
|
component rota = RotR(32, ra); |
||||
|
component rotb = RotR(32, rb); |
||||
|
component shrc = ShR(32, rc); |
||||
|
|
||||
|
for (k=0; k<32; k++) { |
||||
|
rota.in[k] <== in[k]; |
||||
|
rotb.in[k] <== in[k]; |
||||
|
shrc.in[k] <== in[k]; |
||||
|
} |
||||
|
|
||||
|
component xor3 = Xor3(32); |
||||
|
for (k=0; k<32; k++) { |
||||
|
xor3.a[k] <== rota.out[k]; |
||||
|
xor3.b[k] <== rotb.out[k]; |
||||
|
xor3.c[k] <== shrc.out[k]; |
||||
|
} |
||||
|
|
||||
|
for (k=0; k<32; k++) { |
||||
|
out[k] <== xor3.out[k]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template BigSigma(ra, rb, rc) { |
||||
|
signal input in[32]; |
||||
|
signal output out[32]; |
||||
|
var k; |
||||
|
|
||||
|
component rota = RotR(32, ra); |
||||
|
component rotb = RotR(32, rb); |
||||
|
component rotc = RotR(32, rc); |
||||
|
for (k=0; k<32; k++) { |
||||
|
rota.in[k] <== in[k]; |
||||
|
rotb.in[k] <== in[k]; |
||||
|
rotc.in[k] <== in[k]; |
||||
|
} |
||||
|
|
||||
|
component xor3 = Xor3(32); |
||||
|
|
||||
|
for (k=0; k<32; k++) { |
||||
|
xor3.a[k] <== rota.out[k]; |
||||
|
xor3.b[k] <== rotb.out[k]; |
||||
|
xor3.c[k] <== rotc.out[k]; |
||||
|
} |
||||
|
|
||||
|
for (k=0; k<32; k++) { |
||||
|
out[k] <== xor3.out[k]; |
||||
|
} |
||||
|
} |
@ -0,0 +1,50 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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]; |
||||
|
var k; |
||||
|
|
||||
|
component sigma1 = SmallSigma(17,19,10); |
||||
|
component sigma0 = SmallSigma(7, 18, 3); |
||||
|
for (k=0; k<32; k++) { |
||||
|
sigma1.in[k] <== in2[k]; |
||||
|
sigma0.in[k] <== in15[k]; |
||||
|
} |
||||
|
|
||||
|
component sum = BinSum(32, 4); |
||||
|
for (k=0; k<32; 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]; |
||||
|
} |
||||
|
|
||||
|
for (k=0; k<32; k++) { |
||||
|
out[k] <== sum.out[k]; |
||||
|
} |
||||
|
} |
@ -0,0 +1,58 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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]; |
||||
|
|
||||
|
var ki; |
||||
|
|
||||
|
component ch = Ch_t(32); |
||||
|
component bigsigma1 = BigSigma(6, 11, 25); |
||||
|
|
||||
|
for (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]; |
||||
|
} |
||||
|
|
||||
|
component sum = BinSum(32, 5); |
||||
|
for (ki=0; ki<32; 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]; |
||||
|
} |
||||
|
|
||||
|
for (ki=0; ki<32; ki++) { |
||||
|
out[ki] <== sum.out[ki]; |
||||
|
} |
||||
|
} |
@ -0,0 +1,51 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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]; |
||||
|
var k; |
||||
|
|
||||
|
component bigsigma0 = BigSigma(2, 13, 22); |
||||
|
component maj = Maj_t(32); |
||||
|
for (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]; |
||||
|
} |
||||
|
|
||||
|
component sum = BinSum(32, 2); |
||||
|
|
||||
|
for (k=0; k<32; k++) { |
||||
|
sum.in[0][k] <== bigsigma0.out[k]; |
||||
|
sum.in[1][k] <== maj.out[k]; |
||||
|
} |
||||
|
|
||||
|
for (k=0; k<32; k++) { |
||||
|
out[k] <== sum.out[k]; |
||||
|
} |
||||
|
} |
@ -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/>. |
||||
|
*/ |
||||
|
|
||||
|
/* 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 |
||||
|
|
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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]; |
||||
|
} |
||||
|
} |
@ -0,0 +1,36 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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; |
||||
|
} |
@ -0,0 +1,58 @@ |
|||||
|
/* |
||||
|
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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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; |
||||
|
} |
@ -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/>. |
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "../poseidon.circom"; |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
Hash1 = H(1 | key | value) |
||||
|
*/ |
||||
|
|
||||
|
template SMTHash1() { |
||||
|
signal input key; |
||||
|
signal input value; |
||||
|
signal output out; |
||||
|
|
||||
|
component h = Poseidon(3); // 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); // Constant |
||||
|
h.inputs[0] <== L; |
||||
|
h.inputs[1] <== R; |
||||
|
|
||||
|
out <== h.out; |
||||
|
} |
@ -0,0 +1,103 @@ |
|||||
|
/* |
||||
|
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 |
||||
|
│ │ |
||||
|
└───────────┘ |
||||
|
|
||||
|
*/ |
||||
|
pragma circom 2.0.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. |
||||
|
|
||||
|
var i; |
||||
|
|
||||
|
component isZero[nLevels]; |
||||
|
|
||||
|
for (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 (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]); |
||||
|
} |
@ -0,0 +1,261 @@ |
|||||
|
/* |
||||
|
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 |
||||
|
|
||||
|
|
||||
|
***************************************************************************************************/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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; |
||||
|
|
||||
|
var i; |
||||
|
|
||||
|
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 (i=0; i<nLevels; i++) smtLevIns.siblings[i] <== siblings[i]; |
||||
|
smtLevIns.enabled <== enabled; |
||||
|
|
||||
|
component xors[nLevels]; |
||||
|
for (i=0; i<nLevels; i++) { |
||||
|
xors[i] = XOR(); |
||||
|
xors[i].a <== n2bOld.out[i]; |
||||
|
xors[i].b <== n2bNew.out[i]; |
||||
|
} |
||||
|
|
||||
|
component sm[nLevels]; |
||||
|
for (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 (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; |
||||
|
} |
@ -0,0 +1,95 @@ |
|||||
|
/* |
||||
|
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. |
||||
|
|
||||
|
*****/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
|
||||
|
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); |
||||
|
} |
@ -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/>. |
||||
|
*/ |
||||
|
|
||||
|
/*************************************************************************************************** |
||||
|
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 |
||||
|
|
||||
|
***************************************************************************************************/ |
||||
|
pragma circom 2.0.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; |
||||
|
|
||||
|
} |
@ -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/>. |
||||
|
*/ |
||||
|
|
||||
|
/* |
||||
|
|
||||
|
SMTVerifier is a component to verify inclusion/exclusion of an element in the tree |
||||
|
|
||||
|
|
||||
|
fnc: 0 -> VERIFY INCLUSION |
||||
|
1 -> VERIFY NOT INCLUSION |
||||
|
|
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
|
||||
|
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; |
||||
|
|
||||
|
var i; |
||||
|
|
||||
|
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 (i=0; i<nLevels; i++) smtLevIns.siblings[i] <== siblings[i]; |
||||
|
smtLevIns.enabled <== enabled; |
||||
|
|
||||
|
component sm[nLevels]; |
||||
|
for (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 (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; |
||||
|
|
||||
|
} |
@ -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. |
||||
|
|
||||
|
*****/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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; |
||||
|
} |
@ -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/>. |
||||
|
*/ |
||||
|
|
||||
|
/* |
||||
|
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 #─────────┘ |
||||
|
## ## |
||||
|
######### |
||||
|
|
||||
|
*/ |
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
|
||||
|
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; |
||||
|
} |
@ -0,0 +1,42 @@ |
|||||
|
/* |
||||
|
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 |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
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; |
||||
|
} |
@ -0,0 +1,2 @@ |
|||||
|
|
||||
|
|
@ -0,0 +1,33 @@ |
|||||
|
{ |
||||
|
"name": "circomlib", |
||||
|
"version": "2.0.5", |
||||
|
"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", |
||||
|
"devDependencies": { |
||||
|
"blake-hash": "^2.0.0", |
||||
|
"chai": "^4.3.4", |
||||
|
"circom_tester": "0.0.13", |
||||
|
"circomlibjs": "^0.1.4", |
||||
|
"mocha": "^9.1.3" |
||||
|
} |
||||
|
} |
@ -0,0 +1,77 @@ |
|||||
|
const chai = require("chai"); |
||||
|
const path = require("path"); |
||||
|
|
||||
|
const assert = chai.assert; |
||||
|
|
||||
|
const Scalar = require("ffjavascript").Scalar; |
||||
|
const F1Field = require("ffjavascript").F1Field; |
||||
|
const utils = require("ffjavascript").utils; |
||||
|
const q = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); |
||||
|
const F = new F1Field(q); |
||||
|
|
||||
|
const wasm_tester = require("circom_tester").wasm; |
||||
|
|
||||
|
function print(circuit, w, s) { |
||||
|
console.log(s + ": " + w[circuit.getSignalIdx(s)]); |
||||
|
} |
||||
|
|
||||
|
function getBits(v, n) { |
||||
|
const res = []; |
||||
|
for (let i=0; i<n; i++) { |
||||
|
if (Scalar.isOdd(Scalar.shr(v,i))) { |
||||
|
res.push(F.one); |
||||
|
} else { |
||||
|
res.push(F.zero); |
||||
|
} |
||||
|
} |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
describe("Aliascheck test", function () { |
||||
|
this.timeout(100000); |
||||
|
|
||||
|
let cir; |
||||
|
before( async() => { |
||||
|
|
||||
|
cir = await wasm_tester(path.join(__dirname, "circuits", "aliascheck_test.circom")); |
||||
|
}); |
||||
|
|
||||
|
it("Satisfy the aliastest 0", async () => { |
||||
|
const inp = getBits(0, 254); |
||||
|
await cir.calculateWitness({in: inp}, true); |
||||
|
}); |
||||
|
|
||||
|
it("Satisfy the aliastest 3", async () => { |
||||
|
const inp = getBits(3, 254); |
||||
|
await cir.calculateWitness({in: inp}, true); |
||||
|
}); |
||||
|
|
||||
|
it("Satisfy the aliastest q-1", async () => { |
||||
|
const inp = getBits(F.e(-1), 254); |
||||
|
// console.log(JSON.stringify(utils.stringifyBigInts(inp)));
|
||||
|
await cir.calculateWitness({in: inp}, true); |
||||
|
}); |
||||
|
|
||||
|
it("Should not satisfy an input of q", async () => { |
||||
|
const inp = getBits(q, 254); |
||||
|
try { |
||||
|
await cir.calculateWitness({in: inp}, true); |
||||
|
assert(false); |
||||
|
} catch(err) { |
||||
|
assert(err.message.includes("Assert Failed")); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
it("Should not satisfy all ones", async () => { |
||||
|
|
||||
|
const inp = getBits(Scalar.sub(Scalar.shl(1, 254) , 1) , 254); |
||||
|
try { |
||||
|
await cir.calculateWitness({in: inp}, true); |
||||
|
assert(false); |
||||
|
} catch(err) { |
||||
|
assert(err.message.includes("Assert Failed")); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
}); |
@ -0,0 +1,118 @@ |
|||||
|
const chai = require("chai"); |
||||
|
const path = require("path"); |
||||
|
|
||||
|
const createBlakeHash = require("blake-hash"); |
||||
|
const buildEddsa = require("circomlibjs").buildEddsa; |
||||
|
|
||||
|
const assert = chai.assert; |
||||
|
|
||||
|
const wasm_tester = require("circom_tester").wasm; |
||||
|
const utils = require("ffjavascript").utils; |
||||
|
const Scalar = require("ffjavascript").Scalar; |
||||
|
|
||||
|
describe("Baby Jub test", function () { |
||||
|
let eddsa; |
||||
|
let F; |
||||
|
let circuitAdd; |
||||
|
let circuitTest; |
||||
|
let circuitPbk; |
||||
|
|
||||
|
this.timeout(100000); |
||||
|
|
||||
|
before( async() => { |
||||
|
|
||||
|
eddsa = await buildEddsa(); |
||||
|
F = eddsa.F; |
||||
|
|
||||
|
circuitAdd = await wasm_tester(path.join(__dirname, "circuits", "babyadd_tester.circom")); |
||||
|
|
||||
|
circuitTest = await wasm_tester(path.join(__dirname, "circuits", "babycheck_test.circom")); |
||||
|
|
||||
|
circuitPbk = await wasm_tester(path.join(__dirname, "circuits", "babypbk_test.circom")); |
||||
|
}); |
||||
|
|
||||
|
it("Should add point (0,1) and (0,1)", async () => { |
||||
|
|
||||
|
const input={ |
||||
|
x1: 0, |
||||
|
y1: 1, |
||||
|
x2: 0, |
||||
|
y2: 1 |
||||
|
}; |
||||
|
|
||||
|
const w = await circuitAdd.calculateWitness(input, true); |
||||
|
|
||||
|
await circuitAdd.assertOut(w, {xout: 0, yout: 1}); |
||||
|
}); |
||||
|
|
||||
|
it("Should add 2 same numbers", async () => { |
||||
|
|
||||
|
const input={ |
||||
|
x1: 17777552123799933955779906779655732241715742912184938656739573121738514868268n, |
||||
|
y1: 2626589144620713026669568689430873010625803728049924121243784502389097019475n, |
||||
|
x2: 17777552123799933955779906779655732241715742912184938656739573121738514868268n, |
||||
|
y2: 2626589144620713026669568689430873010625803728049924121243784502389097019475n |
||||
|
}; |
||||
|
|
||||
|
const w = await circuitAdd.calculateWitness(input, true); |
||||
|
|
||||
|
await circuitAdd.assertOut(w, { |
||||
|
xout: 6890855772600357754907169075114257697580319025794532037257385534741338397365n, |
||||
|
yout: 4338620300185947561074059802482547481416142213883829469920100239455078257889n |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
it("Should add 2 different numbers", async () => { |
||||
|
|
||||
|
const input={ |
||||
|
x1: 17777552123799933955779906779655732241715742912184938656739573121738514868268n, |
||||
|
y1: 2626589144620713026669568689430873010625803728049924121243784502389097019475n, |
||||
|
x2: 16540640123574156134436876038791482806971768689494387082833631921987005038935n, |
||||
|
y2: 20819045374670962167435360035096875258406992893633759881276124905556507972311n |
||||
|
}; |
||||
|
|
||||
|
const w = await circuitAdd.calculateWitness(input, true); |
||||
|
|
||||
|
await circuitAdd.assertOut(w, { |
||||
|
xout: 7916061937171219682591368294088513039687205273691143098332585753343424131937n, |
||||
|
yout: 14035240266687799601661095864649209771790948434046947201833777492504781204499n |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
it("Should check (0,1) is a valid point", async() => { |
||||
|
const w = await circuitTest.calculateWitness({x: 0, y:1}, true); |
||||
|
|
||||
|
await circuitTest.checkConstraints(w); |
||||
|
}); |
||||
|
|
||||
|
it("Should check (1,0) is an invalid point", async() => { |
||||
|
try { |
||||
|
await circuitTest.calculateWitness({x: 1, y: 0}, true); |
||||
|
assert(false, "Should be a valid point"); |
||||
|
} catch(err) { |
||||
|
assert(err.message.includes("Assert Failed")); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
it("Should extract the public key from the private one", async () => { |
||||
|
|
||||
|
const rawpvk = Buffer.from("0001020304050607080900010203040506070809000102030405060708090021", "hex"); |
||||
|
const pvk = eddsa.pruneBuffer(createBlakeHash("blake512").update(rawpvk).digest().slice(0,32)); |
||||
|
const S = Scalar.shr(utils.leBuff2int(pvk), 3); |
||||
|
|
||||
|
const A = eddsa.prv2pub(rawpvk); |
||||
|
|
||||
|
const input = { |
||||
|
in : S |
||||
|
}; |
||||
|
|
||||
|
const w = await circuitPbk.calculateWitness(input, true); |
||||
|
|
||||
|
await circuitPbk.assertOut(w, {Ax : F.toObject(A[0]), Ay: F.toObject(A[1])}); |
||||
|
|
||||
|
await circuitPbk.checkConstraints(w); |
||||
|
}); |
||||
|
|
||||
|
}); |
@ -0,0 +1,52 @@ |
|||||
|
const path = require("path"); |
||||
|
|
||||
|
const Scalar = require("ffjavascript").Scalar; |
||||
|
const wasm_tester = require("circom_tester").wasm; |
||||
|
|
||||
|
function print(circuit, w, s) { |
||||
|
console.log(s + ": " + w[circuit.getSignalIdx(s)]); |
||||
|
} |
||||
|
|
||||
|
async function checkSub(_a,_b, circuit) { |
||||
|
let a=Scalar.e(_a); |
||||
|
let b=Scalar.e(_b); |
||||
|
if (Scalar.lt(a, 0)) a = Scalar.add(a, Scalar.shl(1, 16)); |
||||
|
if (Scalar.lt(b, 0)) b = Scalar.add(b, Scalar.shl(1, 16)); |
||||
|
const w = await circuit.calculateWitness({a: a, b: b}, true); |
||||
|
|
||||
|
let res = Scalar.sub(a, b); |
||||
|
if (Scalar.lt(res, 0)) res = Scalar.add(res, Scalar.shl(1, 16)); |
||||
|
|
||||
|
await circuit.assertOut(w, {out: res}); |
||||
|
} |
||||
|
|
||||
|
describe("BinSub test", function () { |
||||
|
|
||||
|
this.timeout(100000); |
||||
|
|
||||
|
let circuit; |
||||
|
before( async() => { |
||||
|
circuit = await wasm_tester(path.join(__dirname, "circuits", "binsub_test.circom")); |
||||
|
}); |
||||
|
|
||||
|
it("Should check variuos ege cases", async () => { |
||||
|
await checkSub(0,0, circuit); |
||||
|
await checkSub(1,0, circuit); |
||||
|
await checkSub(-1,0, circuit); |
||||
|
await checkSub(2,1, circuit); |
||||
|
await checkSub(2,2, circuit); |
||||
|
await checkSub(2,3, circuit); |
||||
|
await checkSub(2,-1, circuit); |
||||
|
await checkSub(2,-2, circuit); |
||||
|
await checkSub(2,-3, circuit); |
||||
|
await checkSub(-2,-3, circuit); |
||||
|
await checkSub(-2,-2, circuit); |
||||
|
await checkSub(-2,-1, circuit); |
||||
|
await checkSub(-2,0, circuit); |
||||
|
await checkSub(-2,1, circuit); |
||||
|
await checkSub(-2,2, circuit); |
||||
|
await checkSub(-2,3, circuit); |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
}); |
@ -0,0 +1,38 @@ |
|||||
|
const chai = require("chai"); |
||||
|
const path = require("path"); |
||||
|
|
||||
|
const wasm_tester = require("circom_tester").wasm; |
||||
|
|
||||
|
const F1Field = require("ffjavascript").F1Field; |
||||
|
const Scalar = require("ffjavascript").Scalar; |
||||
|
exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); |
||||
|
const Fr = new F1Field(exports.p); |
||||
|
|
||||
|
const assert = chai.assert; |
||||
|
|
||||
|
describe("Binary sum test", function () { |
||||
|
this.timeout(100000000); |
||||
|
|
||||
|
it("Should create a constant circuit", async () => { |
||||
|
const circuit = await wasm_tester(path.join(__dirname, "circuits", "constants_test.circom")); |
||||
|
await circuit.loadConstraints(); |
||||
|
assert.equal(circuit.nVars, 2); |
||||
|
assert.equal(circuit.constraints.length, 1); |
||||
|
|
||||
|
const witness = await circuit.calculateWitness({ "in": Fr.toString(Fr.e("0xd807aa98"))}, true); |
||||
|
|
||||
|
assert(Fr.eq(Fr.e(witness[0]),Fr.e(1))); |
||||
|
assert(Fr.eq(Fr.e(witness[1]),Fr.e("0xd807aa98"))); |
||||
|
}); |
||||
|
it("Should create a sum circuit", async () => { |
||||
|
const circuit = await wasm_tester(path.join(__dirname, "circuits", "sum_test.circom")); |
||||
|
await circuit.loadConstraints(); |
||||
|
|
||||
|
assert.equal(circuit.constraints.length, 97); // 32 (in1) + 32(in2) + 32(out) + 1 (carry)
|
||||
|
|
||||
|
const witness = await circuit.calculateWitness({ "a": "111", "b": "222" }, true); |
||||
|
|
||||
|
assert(Fr.eq(Fr.e(witness[0]),Fr.e(1))); |
||||
|
assert(Fr.eq(Fr.e(witness[1]),Fr.e("333"))); |
||||
|
}); |
||||
|
}); |
@ -0,0 +1,4 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
include "../../circuits/aliascheck.circom"; |
||||
|
|
||||
|
component main = AliasCheck(); |
@ -0,0 +1,4 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
include "../../circuits/babyjub.circom"; |
||||
|
|
||||
|
component main = BabyAdd(); |
@ -0,0 +1,4 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
include "../../circuits/babyjub.circom"; |
||||
|
|
||||
|
component main = BabyCheck(); |
@ -0,0 +1,4 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
include "../../circuits/babyjub.circom"; |
||||
|
|
||||
|
component main = BabyPbk(); |
@ -0,0 +1,33 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "../../circuits/bitify.circom"; |
||||
|
include "../../circuits/binsub.circom"; |
||||
|
|
||||
|
template A() { |
||||
|
signal input a; //private |
||||
|
signal input b; |
||||
|
signal output out; |
||||
|
|
||||
|
var i; |
||||
|
|
||||
|
component n2ba = Num2Bits(16); |
||||
|
component n2bb = Num2Bits(16); |
||||
|
component sub = BinSub(16); |
||||
|
component b2n = Bits2Num(16); |
||||
|
|
||||
|
n2ba.in <== a; |
||||
|
n2bb.in <== b; |
||||
|
|
||||
|
for (i=0; i<16; i++) { |
||||
|
sub.in[0][i] <== n2ba.out[i]; |
||||
|
sub.in[1][i] <== n2bb.out[i]; |
||||
|
} |
||||
|
|
||||
|
for (i=0; i<16; i++) { |
||||
|
b2n.in[i] <== sub.out[i]; |
||||
|
} |
||||
|
|
||||
|
out <== b2n.out; |
||||
|
} |
||||
|
|
||||
|
component main = A(); |
@ -0,0 +1,20 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "../../circuits/sha256/constants.circom"; |
||||
|
|
||||
|
template A() { |
||||
|
signal input in; |
||||
|
component h0; |
||||
|
h0 = K(8); |
||||
|
|
||||
|
var lc = 0; |
||||
|
var e = 1; |
||||
|
for (var i=0; i<32; i++) { |
||||
|
lc = lc + e*h0.out[i]; |
||||
|
e *= 2; |
||||
|
} |
||||
|
|
||||
|
lc === in; |
||||
|
} |
||||
|
|
||||
|
component main {public [in]} = A(); |
@ -0,0 +1,5 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "../../circuits/eddsa.circom"; |
||||
|
|
||||
|
component main = EdDSAVerifier(80); |
@ -0,0 +1,5 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "../../circuits/eddsamimc.circom"; |
||||
|
|
||||
|
component main = EdDSAMiMCVerifier(); |
@ -0,0 +1,5 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "../../circuits/eddsaposeidon.circom"; |
||||
|
|
||||
|
component main = EdDSAPoseidonVerifier(); |
@ -0,0 +1,5 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "../../circuits/montgomery.circom"; |
||||
|
|
||||
|
component main = Edwards2Montgomery(); |
@ -0,0 +1,27 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "../../circuits/escalarmul.circom"; |
||||
|
|
||||
|
|
||||
|
template Main() { |
||||
|
signal input in[256]; |
||||
|
signal output out[2]; |
||||
|
|
||||
|
var i; |
||||
|
|
||||
|
var base[2] = [5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203]; |
||||
|
|
||||
|
component escalarMul = EscalarMul(256, base); |
||||
|
|
||||
|
escalarMul.inp[0] <== 0; |
||||
|
escalarMul.inp[1] <== 1; |
||||
|
|
||||
|
for (i=0; i<256; i++) { |
||||
|
in[i] ==> escalarMul.in[i]; |
||||
|
} |
||||
|
|
||||
|
escalarMul.out[0] ==> out[0]; |
||||
|
escalarMul.out[1] ==> out[1]; |
||||
|
} |
||||
|
|
||||
|
component main = Main(); |
@ -0,0 +1,33 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "../../circuits/escalarmul.circom"; |
||||
|
include "../../circuits/bitify.circom"; |
||||
|
|
||||
|
|
||||
|
template Main() { |
||||
|
signal input in; |
||||
|
signal output out[2]; |
||||
|
|
||||
|
var base[2] = [5299619240641551281634865583518297030282874472190772894086521144482721001553, |
||||
|
16950150798460657717958625567821834550301663161624707787222815936182638968203]; |
||||
|
|
||||
|
|
||||
|
component n2b = Num2Bits(253); |
||||
|
component escalarMul = EscalarMul(253, base); |
||||
|
|
||||
|
escalarMul.inp[0] <== 0; |
||||
|
escalarMul.inp[1] <== 1; |
||||
|
|
||||
|
var i; |
||||
|
|
||||
|
in ==> n2b.in; |
||||
|
|
||||
|
for (i=0; i<253; i++) { |
||||
|
n2b.out[i] ==> escalarMul.in[i]; |
||||
|
} |
||||
|
|
||||
|
escalarMul.out[0] ==> out[0]; |
||||
|
escalarMul.out[1] ==> out[1]; |
||||
|
} |
||||
|
|
||||
|
component main = Main(); |
@ -0,0 +1,28 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "../../circuits/escalarmul.circom"; |
||||
|
|
||||
|
|
||||
|
template Main() { |
||||
|
signal input in[256]; |
||||
|
signal output out[2]; |
||||
|
|
||||
|
var i; |
||||
|
|
||||
|
var base[2] = [5299619240641551281634865583518297030282874472190772894086521144482721001553, |
||||
|
16950150798460657717958625567821834550301663161624707787222815936182638968203]; |
||||
|
|
||||
|
component escalarMul = EscalarMul(256, base); |
||||
|
|
||||
|
escalarMul.inp[0] <== 0; |
||||
|
escalarMul.inp[1] <== 1; |
||||
|
|
||||
|
for (i=0; i<256; i++) { |
||||
|
in[i] ==> escalarMul.in[i]; |
||||
|
} |
||||
|
|
||||
|
escalarMul.out[0] ==> out[0]; |
||||
|
escalarMul.out[1] ==> out[1]; |
||||
|
} |
||||
|
|
||||
|
component main = Main(); |
@ -0,0 +1,30 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "../../circuits/escalarmulany.circom"; |
||||
|
include "../../circuits/bitify.circom"; |
||||
|
|
||||
|
template Main() { |
||||
|
signal input e; |
||||
|
signal input p[2]; |
||||
|
signal output out[2]; |
||||
|
|
||||
|
component n2b = Num2Bits(253); |
||||
|
component escalarMulAny = EscalarMulAny(253); |
||||
|
|
||||
|
escalarMulAny.p[0] <== p[0]; |
||||
|
escalarMulAny.p[1] <== p[1]; |
||||
|
|
||||
|
var i; |
||||
|
|
||||
|
e ==> n2b.in; |
||||
|
|
||||
|
for (i=0; i<253; i++) { |
||||
|
n2b.out[i] ==> escalarMulAny.e[i]; |
||||
|
} |
||||
|
|
||||
|
escalarMulAny.out[0] ==> out[0]; |
||||
|
escalarMulAny.out[1] ==> out[1]; |
||||
|
} |
||||
|
|
||||
|
component main = Main(); |
||||
|
|
@ -0,0 +1,31 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "../../circuits/escalarmulfix.circom"; |
||||
|
include "../../circuits/bitify.circom"; |
||||
|
|
||||
|
|
||||
|
template Main() { |
||||
|
signal input e; |
||||
|
signal output out[2]; |
||||
|
|
||||
|
var base[2] = [5299619240641551281634865583518297030282874472190772894086521144482721001553, |
||||
|
16950150798460657717958625567821834550301663161624707787222815936182638968203]; |
||||
|
|
||||
|
|
||||
|
component n2b = Num2Bits(253); |
||||
|
component escalarMul = EscalarMulFix(253, base); |
||||
|
|
||||
|
var i; |
||||
|
|
||||
|
e ==> n2b.in; |
||||
|
|
||||
|
for (i=0; i<253; i++) { |
||||
|
n2b.out[i] ==> escalarMul.e[i]; |
||||
|
} |
||||
|
|
||||
|
escalarMul.out[0] ==> out[0]; |
||||
|
escalarMul.out[1] ==> out[1]; |
||||
|
} |
||||
|
|
||||
|
component main = Main(); |
||||
|
|
@ -0,0 +1,20 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "../../circuits/escalarmulw4table.circom"; |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
template Main() { |
||||
|
signal output out[16][2]; |
||||
|
var base[2] = [5299619240641551281634865583518297030282874472190772894086521144482721001553, |
||||
|
16950150798460657717958625567821834550301663161624707787222815936182638968203]; |
||||
|
|
||||
|
var escalarMul[16][2] = EscalarMulW4Table(base, 0); |
||||
|
for (var i=0; i<16; i++) { |
||||
|
out[i][0] <== escalarMul[i][0]; |
||||
|
out[i][1] <== escalarMul[i][1]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
component main = Main(); |