forked from tornado-packages/archive-monorepo
Set up monorepo
Signed-off-by: T-Hax <>
This commit is contained in:
commit
6006120e60
10
.editorconfig
Normal file
10
.editorconfig
Normal file
@ -0,0 +1,10 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
[*.{js,json,yml}]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
1
.env.example
Normal file
1
.env.example
Normal file
@ -0,0 +1 @@
|
||||
export GITEA_AUTH_TOKEN=
|
4
.gitattributes
vendored
Normal file
4
.gitattributes
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/.yarn/** linguist-vendored
|
||||
/.yarn/releases/* binary
|
||||
/.yarn/plugins/**/* binary
|
||||
/.pnp.* binary linguist-generated
|
17
.gitignore
vendored
Normal file
17
.gitignore
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
# NOT using zero installs
|
||||
|
||||
.pnp.*
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/sdks
|
||||
!.yarn/versions
|
||||
|
||||
# Environment
|
||||
|
||||
.env
|
||||
|
||||
# node modules
|
||||
|
||||
node_modules
|
5
.vscode/extensions.json
vendored
Normal file
5
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"arcanis.vscode-zipfs"
|
||||
]
|
||||
}
|
7
.vscode/settings.json
vendored
Normal file
7
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"search.exclude": {
|
||||
"**/.yarn": true,
|
||||
"**/.pnp.*": true
|
||||
}
|
||||
}
|
BIN
.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
vendored
Normal file
BIN
.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
vendored
Normal file
Binary file not shown.
5
.yarn/sdks/integrations.yml
vendored
Normal file
5
.yarn/sdks/integrations.yml
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# This file is automatically generated by @yarnpkg/sdks.
|
||||
# Manual changes might be lost!
|
||||
|
||||
integrations:
|
||||
- vscode
|
31
.yarnrc.yml
Normal file
31
.yarnrc.yml
Normal file
@ -0,0 +1,31 @@
|
||||
# So basically, we want to selectively download packages from the Gitea repository but still allow the
|
||||
# main repositories, so we are going to have to scope our packages properly.
|
||||
npmScopes:
|
||||
tornado:
|
||||
# The @tornado scope can just be set to the right registry by editing the T-Hax here.
|
||||
# I could even make it an env var but it seems too much, that is for secrets.
|
||||
npmPublishRegistry: "https://development.tornadocash.community/api/packages/T-Hax/npm/"
|
||||
npmRegistryServer: "https://development.tornadocash.community/api/packages/T-Hax/npm/"
|
||||
# The below can be EXPORTED via some env file which actually exports the variables though
|
||||
# Check the env.example, you will notice it's not a regular env
|
||||
# So split your env files up, since this is only for manual actions
|
||||
npmAuthToken: ${GITEA_AUTH_TOKEN}
|
||||
|
||||
# If the following isn't set you won't have a node_modules folder
|
||||
# You might be used to a node_modules folder instead of a pnp or other folder type
|
||||
# If you want to use the new linkers uncomment or change the following
|
||||
nodeLinker: "node-modules"
|
||||
|
||||
# So the tornadocash org, the person who maintains it, might setup something (in future) like,
|
||||
# tornadocash:
|
||||
# npmPublishRegistry: "https://development.tornadocash.community/api/packages/tornadocash/npm/"
|
||||
# npmRegistryServer: "https://development.tornadocash.community/api/packages/tornadocash/npm/"
|
||||
|
||||
# We disable telemetry for obvious reasons. enableTelemetry: false
|
||||
enableTelemetry: false
|
||||
|
||||
plugins:
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
|
||||
spec: "@yarnpkg/plugin-workspace-tools"
|
||||
|
||||
npmPublishAccess: public
|
74
@tornado/circomlib/.gitignore
vendored
Normal file
74
@tornado/circomlib/.gitignore
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Typescript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
tmp
|
||||
|
||||
.DS_Store
|
||||
|
||||
# yarn v3
|
||||
.pnp.*
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/sdks
|
||||
!.yarn/versions
|
21
@tornado/circomlib/README.md
Normal file
21
@tornado/circomlib/README.md
Normal file
@ -0,0 +1,21 @@
|
||||
# @T-Hax/circomlib
|
||||
|
||||
This repository serves to configure the equivalent Tornado Cash repository for npm publishing. Below the rest of the description.
|
||||
|
||||
# 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).
|
||||
|
||||
## 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.
|
83
@tornado/circomlib/calcpedersenbases/calcpedersenbases.js
Normal file
83
@tornado/circomlib/calcpedersenbases/calcpedersenbases.js
Normal file
@ -0,0 +1,83 @@
|
||||
const bn128 = require("snarkjs").bn128;
|
||||
const bigInt = require("snarkjs").bigInt;
|
||||
const createBlakeHash = require("blake-hash");
|
||||
const babyJub = require("../src/babyjub");
|
||||
|
||||
function getPoint(S) {
|
||||
const F = bn128.Fr;
|
||||
const h = createBlakeHash("blake256").update(S).digest();
|
||||
|
||||
if (h.length != 32) {
|
||||
throw new Error("Invalid length")
|
||||
}
|
||||
|
||||
let sign = false;
|
||||
if (h[31] & 0x80) {
|
||||
h[31] = h[31] & 0x7F;
|
||||
sign = true;
|
||||
}
|
||||
|
||||
let y = bigInt(0);
|
||||
for (let i=0; i<32; i++) {
|
||||
y = y.shl(8);
|
||||
y = y.add(bigInt(h[i]));
|
||||
}
|
||||
|
||||
const a = bigInt("168700");
|
||||
const d = bigInt("168696");
|
||||
|
||||
const y2 = F.square(y);
|
||||
|
||||
let x = F.sqrt(F.div(
|
||||
F.sub(F.one, y2),
|
||||
F.sub(a, F.mul(d, y2))));
|
||||
|
||||
if (x == null) return null;
|
||||
|
||||
if (sign) x = F.neg(x);
|
||||
|
||||
const p = [bn128.Fr.affine(x), bn128.Fr.affine(y)];
|
||||
|
||||
const p8 = babyJub.mulPointEscalar(p, 8);
|
||||
|
||||
return p8;
|
||||
}
|
||||
|
||||
|
||||
function generatePoint(S) {
|
||||
let p= null;
|
||||
let idx = 0;
|
||||
while (p==null) {
|
||||
let sidx = "" + idx;
|
||||
while (sidx.length<16) sidx = "0"+sidx;
|
||||
p = getPoint(S+"_"+sidx);
|
||||
idx++;
|
||||
}
|
||||
if (!babyJub.inCurve(p)){
|
||||
throw new Error("Point not in curve");
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const g = [
|
||||
bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
|
||||
bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")];
|
||||
|
||||
// Sanity check
|
||||
if (!babyJub.inCurve(g)) {
|
||||
throw new Error("Generator not In curve -> Some thing goes wrong...");
|
||||
}
|
||||
|
||||
for (let i=0; i<25; i++) {
|
||||
let S = "" +i;
|
||||
while (S.length<16) S = "0"+S;
|
||||
const P = generatePoint("Iden3_PedersenGenerator_"+S);
|
||||
console.log(`[${P[0].toString()}, ${P[1].toString()}]`);
|
||||
}
|
||||
|
||||
|
||||
|
830
@tornado/circomlib/circuits/README.md
Normal file
830
@tornado/circomlib/circuits/README.md
Normal file
@ -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, 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)`
|
||||
|
||||
- DESCRIPTION
|
||||
- SCHEMA
|
||||
- INPUT
|
||||
- OUTPUT
|
||||
- BENCHMARKS
|
||||
- EXAMPLE
|
||||
|
||||
- `Mix(t, M)`
|
||||
|
||||
- DESCRIPTION
|
||||
- SCHEMA
|
||||
- INPUT
|
||||
- OUTPUT
|
||||
- BENCHMARKS
|
||||
- EXAMPLE
|
||||
|
||||
- `Poseidon(nInputs, t, nRoundsF, nRoundsP)`
|
||||
|
||||
- DESCRIPTION
|
||||
- SCHEMA
|
||||
- INPUT
|
||||
- OUTPUT
|
||||
- BENCHMARKS
|
||||
- EXAMPLE
|
||||
|
||||
### sign
|
||||
|
||||
- `Sign()`
|
||||
|
||||
- DESCRIPTION
|
||||
- SCHEMA
|
||||
- INPUT
|
||||
- OUTPUT
|
||||
- BENCHMARKS
|
||||
- EXAMPLE
|
||||
|
||||
### switcher
|
||||
|
||||
- `Switcher()`
|
||||
|
||||
- DESCRIPTION
|
||||
- SCHEMA
|
||||
- INPUT
|
||||
- OUTPUT
|
||||
- BENCHMARKS
|
||||
- EXAMPLE
|
43
@tornado/circomlib/circuits/aliascheck.circom
Normal file
43
@tornado/circomlib/circuits/aliascheck.circom
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "compconstant.circom";
|
||||
|
||||
|
||||
template AliasCheck() {
|
||||
signal input in[254];
|
||||
|
||||
component compConstant = CompConstant(-1);
|
||||
|
||||
for (var i=0; i<254; i++) in[i] ==> compConstant.in[i];
|
||||
|
||||
compConstant.out === 0;
|
||||
}
|
||||
|
||||
template AliasCheckBabyJub() {
|
||||
signal input in[251];
|
||||
signal input enabled;
|
||||
|
||||
component compConstant = CompConstant(2736030358979909402780800718157159386076813972158567259200215660948447373040);
|
||||
|
||||
for (var i=0; i<251; i++) in[i] ==> compConstant.in[i];
|
||||
for (var i=0; i<3; i++) 0 ==> compConstant.in[251+i];
|
||||
|
||||
compConstant.out*enabled === 0;
|
||||
}
|
106
@tornado/circomlib/circuits/babyjub.circom
Normal file
106
@tornado/circomlib/circuits/babyjub.circom
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "bitify.circom";
|
||||
include "escalarmulfix.circom";
|
||||
|
||||
template BabyAdd() {
|
||||
signal input x1;
|
||||
signal input y1;
|
||||
signal input x2;
|
||||
signal input y2;
|
||||
signal output xout;
|
||||
signal output yout;
|
||||
|
||||
signal beta;
|
||||
signal gamma;
|
||||
signal delta;
|
||||
signal tau;
|
||||
|
||||
var a = 168700;
|
||||
var d = 168696;
|
||||
|
||||
beta <== x1*y2;
|
||||
gamma <== y1*x2;
|
||||
delta <== (-a*x1+y1)*(x2 + y2);
|
||||
tau <== beta * gamma;
|
||||
|
||||
xout <-- (beta + gamma) / (1+ d*tau);
|
||||
(1+ d*tau) * xout === (beta + gamma);
|
||||
|
||||
yout <-- (delta + a*beta - gamma) / (1-d*tau);
|
||||
(1-d*tau)*yout === (delta + a*beta - gamma);
|
||||
}
|
||||
|
||||
template BabyDbl() {
|
||||
signal input x;
|
||||
signal input y;
|
||||
signal output xout;
|
||||
signal output yout;
|
||||
|
||||
component adder = BabyAdd();
|
||||
adder.x1 <== x;
|
||||
adder.y1 <== y;
|
||||
adder.x2 <== x;
|
||||
adder.y2 <== y;
|
||||
|
||||
adder.xout ==> xout;
|
||||
adder.yout ==> yout;
|
||||
}
|
||||
|
||||
|
||||
template BabyCheck() {
|
||||
signal input x;
|
||||
signal input y;
|
||||
|
||||
signal x2;
|
||||
signal y2;
|
||||
|
||||
var a = 168700;
|
||||
var d = 168696;
|
||||
|
||||
x2 <== x*x;
|
||||
y2 <== y*y;
|
||||
|
||||
a*x2 + y2 === 1 + d*x2*y2;
|
||||
}
|
||||
|
||||
// Extracts the public key from private key, as mentioned in https://tools.ietf.org/html/rfc8032
|
||||
template BabyPbk() {
|
||||
signal private input in;
|
||||
signal output Ax;
|
||||
signal output Ay;
|
||||
|
||||
var BASE8 = [
|
||||
5299619240641551281634865583518297030282874472190772894086521144482721001553,
|
||||
16950150798460657717958625567821834550301663161624707787222815936182638968203
|
||||
];
|
||||
|
||||
component pvkBits = Num2Bits(253);
|
||||
pvkBits.in <== in;
|
||||
|
||||
component mulFix = EscalarMulFix(253, BASE8);
|
||||
|
||||
var i;
|
||||
for (i=0; i<253; i++) {
|
||||
mulFix.e[i] <== pvkBits.out[i];
|
||||
}
|
||||
Ax <== mulFix.out[0];
|
||||
Ay <== mulFix.out[1];
|
||||
}
|
71
@tornado/circomlib/circuits/binsub.circom
Normal file
71
@tornado/circomlib/circuits/binsub.circom
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
This component creates a binary substraction.
|
||||
|
||||
|
||||
Main Constraint:
|
||||
(in[0][0] * 2^0 + in[0][1] * 2^1 + ..... + in[0][n-1] * 2^(n-1)) +
|
||||
+ 2^n
|
||||
- (in[1][0] * 2^0 + in[1][1] * 2^1 + ..... + in[1][n-1] * 2^(n-1))
|
||||
===
|
||||
out[0] * 2^0 + out[1] * 2^1 + + out[n-1] *2^(n-1) + aux
|
||||
|
||||
|
||||
out[0] * (out[0] - 1) === 0
|
||||
out[1] * (out[0] - 1) === 0
|
||||
.
|
||||
.
|
||||
.
|
||||
out[n-1] * (out[n-1] - 1) === 0
|
||||
aux * (aux-1) == 0
|
||||
|
||||
*/
|
||||
|
||||
template BinSub(n) {
|
||||
signal input in[2][n];
|
||||
signal output out[n];
|
||||
|
||||
signal aux;
|
||||
|
||||
var lin = 2**n;
|
||||
var lout = 0;
|
||||
|
||||
for (var i=0; i<n; i++) {
|
||||
lin = lin + in[0][i]*(2**i);
|
||||
lin = lin - in[1][i]*(2**i);
|
||||
}
|
||||
|
||||
for (var i=0; i<n; i++) {
|
||||
out[i] <-- (lin >> i) & 1;
|
||||
|
||||
// Ensure out is binary
|
||||
out[i] * (out[i] - 1) === 0;
|
||||
|
||||
lout = lout + out[i]*(2**i);
|
||||
}
|
||||
|
||||
aux <-- (lin >> n) & 1;
|
||||
aux*(aux-1) === 0;
|
||||
lout = lout + aux*(2**n);
|
||||
|
||||
// Ensure the sum;
|
||||
lin === lout;
|
||||
}
|
95
@tornado/circomlib/circuits/binsum.circom
Normal file
95
@tornado/circomlib/circuits/binsum.circom
Normal file
@ -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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/* a must be < Nq/2, where Nq is the number of elements in the scalar field */
|
||||
function nbits(a) {
|
||||
var n = 1;
|
||||
var r = 0;
|
||||
while (n-1<a) {
|
||||
r++;
|
||||
n *= 2;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/* n must be such that (2**(n+1) -2) < Nq/ops, where Nq is the number of bits in the scalar field */
|
||||
template BinSum(n, ops) {
|
||||
var nout = nbits((2**n -1)*ops);
|
||||
signal input in[ops][n];
|
||||
signal output out[nout];
|
||||
|
||||
var lin = 0;
|
||||
var lout = 0;
|
||||
|
||||
var k;
|
||||
var j;
|
||||
|
||||
for (k=0; k<n; k++) {
|
||||
for (j=0; j<ops; j++) {
|
||||
lin += in[j][k] * 2**k;
|
||||
}
|
||||
}
|
||||
|
||||
for (k=0; k<nout; k++) {
|
||||
out[k] <-- (lin >> k) & 1;
|
||||
|
||||
// Ensure out is binary
|
||||
out[k] * (out[k] - 1) === 0;
|
||||
|
||||
lout += out[k] * 2**k;
|
||||
}
|
||||
|
||||
// Ensure the sum;
|
||||
|
||||
lin === lout;
|
||||
}
|
103
@tornado/circomlib/circuits/bitify.circom
Normal file
103
@tornado/circomlib/circuits/bitify.circom
Normal file
@ -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/>.
|
||||
*/
|
||||
|
||||
include "comparators.circom";
|
||||
include "aliascheck.circom";
|
||||
|
||||
|
||||
/* This doesn't check aliasing, so for n > 253 there are multiple bit strings for each number */
|
||||
template Num2Bits(n) {
|
||||
signal input in;
|
||||
signal output out[n];
|
||||
var lc1=0;
|
||||
|
||||
for (var i = 0; i<n; i++) {
|
||||
out[i] <-- (in >> i) & 1;
|
||||
out[i] * (out[i] -1 ) === 0;
|
||||
lc1 += out[i] * 2**i;
|
||||
}
|
||||
|
||||
lc1 === in;
|
||||
}
|
||||
|
||||
template Num2Bits_strict() {
|
||||
signal input in;
|
||||
signal output out[254];
|
||||
|
||||
component aliasCheck = AliasCheck();
|
||||
component n2b = Num2Bits(254);
|
||||
in ==> n2b.in;
|
||||
|
||||
for (var i=0; i<254; i++) {
|
||||
n2b.out[i] ==> out[i];
|
||||
n2b.out[i] ==> aliasCheck.in[i];
|
||||
}
|
||||
}
|
||||
|
||||
template Bits2Num(n) {
|
||||
signal input in[n];
|
||||
signal output out;
|
||||
var lc1=0;
|
||||
|
||||
for (var i = 0; i<n; i++) {
|
||||
lc1 += in[i] * 2**i;
|
||||
}
|
||||
|
||||
lc1 ==> out;
|
||||
}
|
||||
|
||||
template Bits2Num_strict() {
|
||||
signal input in[n];
|
||||
signal output out;
|
||||
|
||||
component aliasCheck = AliasCheck();
|
||||
component b2n = Bits2Num(254);
|
||||
|
||||
for (var i=0; i<254; i++) {
|
||||
in[i] ==> b2n.in[i];
|
||||
in[i] ==> aliasCheck.in[i];
|
||||
}
|
||||
|
||||
b2n.out ==> out;
|
||||
}
|
||||
|
||||
/* n must not exceed 253 */
|
||||
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;
|
||||
}
|
139
@tornado/circomlib/circuits/comparators.circom
Normal file
139
@tornado/circomlib/circuits/comparators.circom
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "bitify.circom";
|
||||
include "binsum.circom";
|
||||
|
||||
template IsZero() {
|
||||
signal input in;
|
||||
signal output out;
|
||||
|
||||
signal inv;
|
||||
|
||||
inv <-- in!=0 ? 1/in : 0;
|
||||
|
||||
out <== -in*inv +1;
|
||||
in*out === 0;
|
||||
}
|
||||
|
||||
|
||||
template IsEqual() {
|
||||
signal input in[2];
|
||||
signal output out;
|
||||
|
||||
component isz = IsZero();
|
||||
|
||||
in[1] - in[0] ==> isz.in;
|
||||
|
||||
isz.out ==> out;
|
||||
}
|
||||
|
||||
template ForceEqualIfEnabled() {
|
||||
signal input enabled;
|
||||
signal input in[2];
|
||||
|
||||
component isz = IsZero();
|
||||
|
||||
in[1] - in[0] ==> isz.in;
|
||||
|
||||
(1 - isz.out)*enabled === 0;
|
||||
}
|
||||
|
||||
/*
|
||||
// N is the number of bits the input have.
|
||||
// The MSF is the sign bit.
|
||||
template LessThan(n) {
|
||||
signal input in[2];
|
||||
signal output out;
|
||||
|
||||
component num2Bits0;
|
||||
component num2Bits1;
|
||||
|
||||
component adder;
|
||||
|
||||
adder = BinSum(n, 2);
|
||||
|
||||
num2Bits0 = Num2Bits(n);
|
||||
num2Bits1 = Num2BitsNeg(n);
|
||||
|
||||
in[0] ==> num2Bits0.in;
|
||||
in[1] ==> num2Bits1.in;
|
||||
|
||||
var i;
|
||||
for (i=0;i<n;i++) {
|
||||
num2Bits0.out[i] ==> adder.in[0][i];
|
||||
num2Bits1.out[i] ==> adder.in[1][i];
|
||||
}
|
||||
|
||||
adder.out[n-1] ==> out;
|
||||
}
|
||||
*/
|
||||
|
||||
template LessThan(n) {
|
||||
signal input in[2];
|
||||
signal output out;
|
||||
|
||||
component n2b = Num2Bits(n*2+1);
|
||||
|
||||
n2b.in <== in[0]+ (1<<n) - in[1];
|
||||
|
||||
out <== 1-n2b.out[n];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// N is the number of bits the input have.
|
||||
// The MSF is the sign bit.
|
||||
template LessEqThan(n) {
|
||||
signal input in[2];
|
||||
signal output out;
|
||||
|
||||
component lt = LessThan(n);
|
||||
|
||||
lt.in[0] <== in[0];
|
||||
lt.in[1] <== in[1]+1;
|
||||
lt.out ==> out;
|
||||
}
|
||||
|
||||
// N is the number of bits the input have.
|
||||
// The MSF is the sign bit.
|
||||
template GreaterThan(n) {
|
||||
signal input in[2];
|
||||
signal output out;
|
||||
|
||||
component lt = LessThan(n);
|
||||
|
||||
lt.in[0] <== in[1];
|
||||
lt.in[1] <== in[0];
|
||||
lt.out ==> out;
|
||||
}
|
||||
|
||||
// N is the number of bits the input have.
|
||||
// The MSF is the sign bit.
|
||||
template GreaterEqThan(n) {
|
||||
signal input in[2];
|
||||
signal output out;
|
||||
|
||||
component lt = LessThan(n);
|
||||
|
||||
lt.in[0] <== in[1];
|
||||
lt.in[1] <== in[0]+1;
|
||||
lt.out ==> out;
|
||||
}
|
||||
|
74
@tornado/circomlib/circuits/compconstant.circom
Normal file
74
@tornado/circomlib/circuits/compconstant.circom
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "bitify.circom";
|
||||
|
||||
// Returns 1 if in (in binary) > ct
|
||||
|
||||
template CompConstant(ct) {
|
||||
signal input in[254];
|
||||
signal output out;
|
||||
|
||||
signal parts[127];
|
||||
signal sout;
|
||||
|
||||
var clsb;
|
||||
var cmsb;
|
||||
var slsb;
|
||||
var smsb;
|
||||
|
||||
var sum=0;
|
||||
|
||||
var b = (1 << 128) -1;
|
||||
var a = 1;
|
||||
var e = 1;
|
||||
var i;
|
||||
|
||||
for (i=0;i<127; i++) {
|
||||
clsb = (ct >> (i*2)) & 1;
|
||||
cmsb = (ct >> (i*2+1)) & 1;
|
||||
slsb = in[i*2];
|
||||
smsb = in[i*2+1];
|
||||
|
||||
|
||||
if ((cmsb==0)&(clsb==0)) {
|
||||
parts[i] <== -b*smsb*slsb + b*smsb + b*slsb;
|
||||
} else if ((cmsb==0)&(clsb==1)) {
|
||||
parts[i] <== a*smsb*slsb - a*slsb + b*smsb - a*smsb + a;
|
||||
} else if ((cmsb==1)&(clsb==0)) {
|
||||
parts[i] <== b*smsb*slsb - a*smsb + a;
|
||||
} else {
|
||||
parts[i] <== -a*smsb*slsb + a;
|
||||
}
|
||||
|
||||
sum = sum + parts[i];
|
||||
|
||||
b = b -e;
|
||||
a = a +e;
|
||||
e = e*2;
|
||||
}
|
||||
|
||||
sout <== sum;
|
||||
|
||||
component num2bits = Num2Bits(135);
|
||||
|
||||
num2bits.in <== sout;
|
||||
|
||||
out <== num2bits.out[127];
|
||||
}
|
141
@tornado/circomlib/circuits/eddsa.circom
Normal file
141
@tornado/circomlib/circuits/eddsa.circom
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "aliascheck.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 aliasCheck = AliasCheckBabyJub();
|
||||
aliasCheck.enabled <== 1;
|
||||
|
||||
for (i=0; i<251; i++) {
|
||||
S[i] ==> aliasCheck.in[i];
|
||||
}
|
||||
S[251] === 0;
|
||||
S[252] === 0;
|
||||
S[253] === 0;
|
||||
S[254] === 0;
|
||||
S[255] === 0;
|
||||
|
||||
// Convert A to Field elements (And verify A)
|
||||
|
||||
component bits2pointA = Bits2Point_Strict();
|
||||
|
||||
for (i=0; i<256; i++) {
|
||||
bits2pointA.in[i] <== A[i];
|
||||
}
|
||||
Ax <== bits2pointA.out[0];
|
||||
Ay <== bits2pointA.out[1];
|
||||
|
||||
// Convert R8 to Field elements (And verify R8)
|
||||
|
||||
component bits2pointR8 = Bits2Point_Strict();
|
||||
|
||||
for (i=0; i<256; i++) {
|
||||
bits2pointR8.in[i] <== R8[i];
|
||||
}
|
||||
R8x <== bits2pointR8.out[0];
|
||||
R8y <== bits2pointR8.out[1];
|
||||
|
||||
// Calculate the h = H(R,A, msg)
|
||||
|
||||
component hash = Pedersen(512+n);
|
||||
|
||||
for (i=0; i<256; i++) {
|
||||
hash.in[i] <== R8[i];
|
||||
hash.in[256+i] <== A[i];
|
||||
}
|
||||
for (i=0; i<n; i++) {
|
||||
hash.in[512+i] <== msg[i];
|
||||
}
|
||||
|
||||
component point2bitsH = Point2Bits_Strict();
|
||||
point2bitsH.in[0] <== hash.out[0];
|
||||
point2bitsH.in[1] <== hash.out[1];
|
||||
|
||||
// Calculate second part of the right side: right2 = h*8*A
|
||||
|
||||
// Multiply by 8 by adding it 3 times. This also ensure that the result is in
|
||||
// the subgroup.
|
||||
component dbl1 = BabyDbl();
|
||||
dbl1.x <== Ax;
|
||||
dbl1.y <== Ay;
|
||||
component dbl2 = BabyDbl();
|
||||
dbl2.x <== dbl1.xout;
|
||||
dbl2.y <== dbl1.yout;
|
||||
component dbl3 = BabyDbl();
|
||||
dbl3.x <== dbl2.xout;
|
||||
dbl3.y <== dbl2.yout;
|
||||
|
||||
// We check that A is not zero.
|
||||
component isZero = IsZero();
|
||||
isZero.in <== dbl3.x;
|
||||
isZero.out === 0;
|
||||
|
||||
component mulAny = EscalarMulAny(256);
|
||||
for (i=0; i<256; i++) {
|
||||
mulAny.e[i] <== point2bitsH.out[i];
|
||||
}
|
||||
mulAny.p[0] <== dbl3.xout;
|
||||
mulAny.p[1] <== dbl3.yout;
|
||||
|
||||
|
||||
// Compute the right side: right = R8 + right2
|
||||
|
||||
component addRight = BabyAdd();
|
||||
addRight.x1 <== R8x;
|
||||
addRight.y1 <== R8y;
|
||||
addRight.x2 <== mulAny.out[0];
|
||||
addRight.y2 <== mulAny.out[1];
|
||||
|
||||
// Calculate left side of equation left = S*B8
|
||||
|
||||
var BASE8 = [
|
||||
5299619240641551281634865583518297030282874472190772894086521144482721001553,
|
||||
16950150798460657717958625567821834550301663161624707787222815936182638968203
|
||||
];
|
||||
component mulFix = EscalarMulFix(256, BASE8);
|
||||
for (i=0; i<256; i++) {
|
||||
mulFix.e[i] <== S[i];
|
||||
}
|
||||
|
||||
// Do the comparation left == right
|
||||
|
||||
mulFix.out[0] === addRight.xout;
|
||||
mulFix.out[1] === addRight.yout;
|
||||
}
|
122
@tornado/circomlib/circuits/eddsamimc.circom
Normal file
122
@tornado/circomlib/circuits/eddsamimc.circom
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "aliascheck.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(251);
|
||||
snum2bits.in <== S;
|
||||
|
||||
component aliasCheck = AliasCheckBabyJub();
|
||||
aliasCheck.enabled <== 1;
|
||||
|
||||
for (i=0; i<251; i++) {
|
||||
snum2bits.out[i] ==> aliasCheck.in[i];
|
||||
}
|
||||
|
||||
// Calculate the h = H(R,A, msg)
|
||||
|
||||
component hash = MultiMiMC7(5, 91);
|
||||
hash.in[0] <== R8x;
|
||||
hash.in[1] <== R8y;
|
||||
hash.in[2] <== Ax;
|
||||
hash.in[3] <== Ay;
|
||||
hash.in[4] <== M;
|
||||
hash.k <== 0;
|
||||
|
||||
component h2bits = Num2Bits_strict();
|
||||
h2bits.in <== hash.out;
|
||||
|
||||
// Calculate second part of the right side: right2 = h*8*A
|
||||
|
||||
// Multiply by 8 by adding it 3 times. This also ensure that the result is in
|
||||
// the subgroup.
|
||||
component dbl1 = BabyDbl();
|
||||
dbl1.x <== Ax;
|
||||
dbl1.y <== Ay;
|
||||
component dbl2 = BabyDbl();
|
||||
dbl2.x <== dbl1.xout;
|
||||
dbl2.y <== dbl1.yout;
|
||||
component dbl3 = BabyDbl();
|
||||
dbl3.x <== dbl2.xout;
|
||||
dbl3.y <== dbl2.yout;
|
||||
|
||||
// We check that A is not zero.
|
||||
component isZero = IsZero();
|
||||
isZero.in <== dbl3.x;
|
||||
isZero.out === 0;
|
||||
|
||||
component mulAny = EscalarMulAny(254);
|
||||
for (i=0; i<254; i++) {
|
||||
mulAny.e[i] <== h2bits.out[i];
|
||||
}
|
||||
mulAny.p[0] <== dbl3.xout;
|
||||
mulAny.p[1] <== dbl3.yout;
|
||||
|
||||
|
||||
// Compute the right side: right = R8 + right2
|
||||
|
||||
component addRight = BabyAdd();
|
||||
addRight.x1 <== R8x;
|
||||
addRight.y1 <== R8y;
|
||||
addRight.x2 <== mulAny.out[0];
|
||||
addRight.y2 <== mulAny.out[1];
|
||||
|
||||
// Calculate left side of equation left = S*B8
|
||||
|
||||
var BASE8 = [
|
||||
5299619240641551281634865583518297030282874472190772894086521144482721001553,
|
||||
16950150798460657717958625567821834550301663161624707787222815936182638968203
|
||||
];
|
||||
component mulFix = EscalarMulFix(251, BASE8);
|
||||
for (i=0; i<251; 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;
|
||||
}
|
122
@tornado/circomlib/circuits/eddsamimcsponge.circom
Normal file
122
@tornado/circomlib/circuits/eddsamimcsponge.circom
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "aliascheck.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(251);
|
||||
snum2bits.in <== S;
|
||||
|
||||
component aliasCheck = AliasCheckBabyJub();
|
||||
aliasCheck.enabled <== 1;
|
||||
|
||||
for (i=0; i<251; i++) {
|
||||
snum2bits.out[i] ==> aliasCheck.in[i];
|
||||
}
|
||||
|
||||
// Calculate the h = H(R,A, msg)
|
||||
|
||||
component hash = MiMCSponge(5, 1);
|
||||
hash.ins[0] <== R8x;
|
||||
hash.ins[1] <== R8y;
|
||||
hash.ins[2] <== Ax;
|
||||
hash.ins[3] <== Ay;
|
||||
hash.ins[4] <== M;
|
||||
hash.k <== 0;
|
||||
|
||||
component h2bits = Num2Bits_strict();
|
||||
h2bits.in <== hash.outs[0];
|
||||
|
||||
// Calculate second part of the right side: right2 = h*8*A
|
||||
|
||||
// Multiply by 8 by adding it 3 times. This also ensure that the result is in
|
||||
// the subgroup.
|
||||
component dbl1 = BabyDbl();
|
||||
dbl1.x <== Ax;
|
||||
dbl1.y <== Ay;
|
||||
component dbl2 = BabyDbl();
|
||||
dbl2.x <== dbl1.xout;
|
||||
dbl2.y <== dbl1.yout;
|
||||
component dbl3 = BabyDbl();
|
||||
dbl3.x <== dbl2.xout;
|
||||
dbl3.y <== dbl2.yout;
|
||||
|
||||
// We check that A is not zero.
|
||||
component isZero = IsZero();
|
||||
isZero.in <== dbl3.x;
|
||||
isZero.out === 0;
|
||||
|
||||
component mulAny = EscalarMulAny(254);
|
||||
for (i=0; i<254; i++) {
|
||||
mulAny.e[i] <== h2bits.out[i];
|
||||
}
|
||||
mulAny.p[0] <== dbl3.xout;
|
||||
mulAny.p[1] <== dbl3.yout;
|
||||
|
||||
|
||||
// Compute the right side: right = R8 + right2
|
||||
|
||||
component addRight = BabyAdd();
|
||||
addRight.x1 <== R8x;
|
||||
addRight.y1 <== R8y;
|
||||
addRight.x2 <== mulAny.out[0];
|
||||
addRight.y2 <== mulAny.out[1];
|
||||
|
||||
// Calculate left side of equation left = S*B8
|
||||
|
||||
var BASE8 = [
|
||||
5299619240641551281634865583518297030282874472190772894086521144482721001553,
|
||||
16950150798460657717958625567821834550301663161624707787222815936182638968203
|
||||
];
|
||||
component mulFix = EscalarMulFix(251, BASE8);
|
||||
for (i=0; i<251; 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;
|
||||
}
|
121
@tornado/circomlib/circuits/eddsaposeidon.circom
Normal file
121
@tornado/circomlib/circuits/eddsaposeidon.circom
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "compconstant.circom";
|
||||
include "poseidon.circom";
|
||||
include "bitify.circom";
|
||||
include "escalarmulany.circom";
|
||||
include "escalarmulfix.circom";
|
||||
|
||||
template EdDSAPoseidonVerifier() {
|
||||
signal input enabled;
|
||||
signal input Ax;
|
||||
signal input Ay;
|
||||
|
||||
signal input S;
|
||||
signal input R8x;
|
||||
signal input R8y;
|
||||
|
||||
signal input M;
|
||||
|
||||
var i;
|
||||
|
||||
// Ensure S<Subgroup Order
|
||||
|
||||
component snum2bits = Num2Bits(251);
|
||||
snum2bits.in <== S;
|
||||
|
||||
component aliasCheck = AliasCheckBabyJub();
|
||||
aliasCheck.enabled <== enabled;
|
||||
|
||||
for (i=0; i<251; i++) {
|
||||
snum2bits.out[i] ==> aliasCheck.in[i];
|
||||
}
|
||||
|
||||
// Calculate the h = H(R,A, msg)
|
||||
|
||||
component hash = Poseidon(5, 6, 8, 57);
|
||||
|
||||
hash.inputs[0] <== R8x;
|
||||
hash.inputs[1] <== R8y;
|
||||
hash.inputs[2] <== Ax;
|
||||
hash.inputs[3] <== Ay;
|
||||
hash.inputs[4] <== M;
|
||||
|
||||
component h2bits = Num2Bits_strict();
|
||||
h2bits.in <== hash.out;
|
||||
|
||||
// Calculate second part of the right side: right2 = h*8*A
|
||||
|
||||
// Multiply by 8 by adding it 3 times. This also ensure that the result is in
|
||||
// the subgroup.
|
||||
component dbl1 = BabyDbl();
|
||||
dbl1.x <== Ax;
|
||||
dbl1.y <== Ay;
|
||||
component dbl2 = BabyDbl();
|
||||
dbl2.x <== dbl1.xout;
|
||||
dbl2.y <== dbl1.yout;
|
||||
component dbl3 = BabyDbl();
|
||||
dbl3.x <== dbl2.xout;
|
||||
dbl3.y <== dbl2.yout;
|
||||
|
||||
// We check that A is not zero.
|
||||
component isZero = IsZero();
|
||||
isZero.in <== dbl3.x;
|
||||
isZero.out*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 = [
|
||||
5299619240641551281634865583518297030282874472190772894086521144482721001553,
|
||||
16950150798460657717958625567821834550301663161624707787222815936182638968203
|
||||
];
|
||||
component mulFix = EscalarMulFix(251, BASE8);
|
||||
for (i=0; i<251; 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;
|
||||
}
|
165
@tornado/circomlib/circuits/escalarmul.circom
Normal file
165
@tornado/circomlib/circuits/escalarmul.circom
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
┏━━━━━━━━━━━┓
|
||||
┃ ┃
|
||||
┃ ┃
|
||||
(inx, iny) ══════════════════════════════════════════▶┃ EC Point ┃
|
||||
┃ ╠═▶ (outx, outy)
|
||||
╔══▶┃ Adder ┃
|
||||
║ ┃ ┃
|
||||
║ ┃ ┃
|
||||
║ ┃ ┃
|
||||
┏━━━━━━━━━━━┓ ┏━━━━━━━━━━━━┓ ║ ┗━━━━━━━━━━━┛
|
||||
┃ ┃ ┃ ┃ ║
|
||||
┃ ┃ ┃ ┃ ║
|
||||
┃ ╠═══(p0x,p0y)═══▶┃ ┃ ║
|
||||
┃ ╠═══(p1x,p1y)═══▶┃ ┃ ║
|
||||
┃ ╠═══(p2x,p2y)═══▶┃ ┃ ║
|
||||
┃ ╠═══(p3x,p3y)═══▶┃ ┃ ║
|
||||
┃ ╠═══(p4x,p4y)═══▶┃ ┃ ║
|
||||
┃ ╠═══(p5x,p5y)═══▶┃ ┃ ║
|
||||
┃ ╠═══(p6x,p6y)═══▶┃ ┃ ║
|
||||
┃ Constant ╠═══(p7x,p7y)═══▶┃ ┃ ║
|
||||
┃ Points ┃ ┃ Mux4 ╠══╝
|
||||
┃ ╠═══(p8x,p8y)═══▶┃ ┃
|
||||
┃ ╠═══(p9x,p9y)═══▶┃ ┃
|
||||
┃ ╠══(p10x,p10y)══▶┃ ┃
|
||||
┃ ╠══(p11x,p11y)══▶┃ ┃
|
||||
┃ ╠══(p12x,p12y)══▶┃ ┃
|
||||
┃ ╠══(p13x,p13y)══▶┃ ┃
|
||||
┃ ╠══(p14x,p14y)══▶┃ ┃
|
||||
┃ ╠══(p15x,p15y)══▶┃ ┃
|
||||
┃ ┃ ┃ ┃
|
||||
┃ ┃ ┃ ┃
|
||||
┗━━━━━━━━━━━┛ ┗━━━━━━━━━━━━┛
|
||||
▲ ▲ ▲ ▲
|
||||
│ │ │ │
|
||||
s0 ─────────────────────────────────┘ │ │ │
|
||||
s1 ────────────────────────────────────┘ │ │
|
||||
s2 ───────────────────────────────────────┘ │
|
||||
s3 ──────────────────────────────────────────┘
|
||||
|
||||
|
||||
*/
|
||||
|
||||
include "mux4.circom";
|
||||
include "escalarmulw4table.circom";
|
||||
include "babyjub.circom";
|
||||
|
||||
template EscalarMulWindow(base, k) {
|
||||
|
||||
signal input in[2];
|
||||
signal input sel[4];
|
||||
signal output out[2];
|
||||
|
||||
var table;
|
||||
component mux;
|
||||
component adder;
|
||||
|
||||
var i;
|
||||
|
||||
table = EscalarMulW4Table(base, k);
|
||||
mux = MultiMux4(2);
|
||||
adder = BabyAdd();
|
||||
|
||||
for (i=0; i<4; i++) {
|
||||
sel[i] ==> mux.s[i];
|
||||
}
|
||||
|
||||
for (i=0; i<16; i++) {
|
||||
mux.c[0][i] <== table[i][0];
|
||||
mux.c[1][i] <== table[i][1];
|
||||
}
|
||||
|
||||
in[0] ==> adder.x1;
|
||||
in[1] ==> adder.y1;
|
||||
|
||||
mux.out[0] ==> adder.x2;
|
||||
mux.out[1] ==> adder.y2;
|
||||
|
||||
adder.xout ==> out[0];
|
||||
adder.yout ==> out[1];
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
|
||||
┏━━━━━━━━━┓ ┏━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━┓
|
||||
┃ ┃ ┃ ┃ ┃ ┃
|
||||
inp ════▶┃Window(0)┃═════▶┃Window(1)┃════════ . . . . ═════════▶┃ Window(nBlocks-1) ┃═════▶ out
|
||||
┃ ┃ ┃ ┃ ┃ ┃
|
||||
┗━━━━━━━━━┛ ┗━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━┛
|
||||
▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲
|
||||
in[0]─────────┘ │ │ │ │ │ │ │ │ │ │ │
|
||||
in[1]───────────┘ │ │ │ │ │ │ │ │ │ │
|
||||
in[2]─────────────┘ │ │ │ │ │ │ │ 0 0
|
||||
in[3]───────────────┘ │ │ │ │ │ │
|
||||
in[4]──────────────────────────┘ │ │ │ │ │
|
||||
in[5]────────────────────────────┘ │ │ │ │
|
||||
in[6]──────────────────────────────┘ │ │ │
|
||||
in[7]────────────────────────────────┘ │ │
|
||||
. │ │
|
||||
. │ │
|
||||
in[n-2]─────────────────────────────────────────────────────────────────────┘ │
|
||||
in[n-1]───────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
*/
|
||||
|
||||
template EscalarMul(n, base) {
|
||||
signal input in[n];
|
||||
signal input inp[2]; // Point input to be added
|
||||
signal output out[2];
|
||||
|
||||
var nBlocks = ((n-1)>>2)+1;
|
||||
var i;
|
||||
var j;
|
||||
|
||||
component windows[nBlocks];
|
||||
|
||||
// Construct the windows
|
||||
for (i=0; i<nBlocks; i++) {
|
||||
windows[i] = EscalarMulWindow(base, i);
|
||||
}
|
||||
|
||||
// Connect the selectors
|
||||
for (i=0; i<nBlocks; i++) {
|
||||
for (j=0; j<4; j++) {
|
||||
if (i*4+j >= n) {
|
||||
windows[i].sel[j] <== 0;
|
||||
} else {
|
||||
windows[i].sel[j] <== in[i*4+j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Start with generator
|
||||
windows[0].in[0] <== inp[0];
|
||||
windows[0].in[1] <== inp[1];
|
||||
|
||||
for(i=0; i<nBlocks-1; i++) {
|
||||
windows[i].out[0] ==> windows[i+1].in[0];
|
||||
windows[i].out[1] ==> windows[i+1].in[1];
|
||||
}
|
||||
|
||||
windows[nBlocks-1].out[0] ==> out[0];
|
||||
windows[nBlocks-1].out[1] ==> out[1];
|
||||
}
|
196
@tornado/circomlib/circuits/escalarmulany.circom
Normal file
196
@tornado/circomlib/circuits/escalarmulany.circom
Normal file
@ -0,0 +1,196 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "montgomery.circom";
|
||||
include "babyjub.circom";
|
||||
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];
|
||||
}
|
||||
}
|
300
@tornado/circomlib/circuits/escalarmulfix.circom
Normal file
300
@tornado/circomlib/circuits/escalarmulfix.circom
Normal file
@ -0,0 +1,300 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "mux3.circom";
|
||||
include "montgomery.circom";
|
||||
include "babyjub.circom";
|
||||
|
||||
/*
|
||||
Window of 3 elements, it calculates
|
||||
out = base + base*in[0] + 2*base*in[1] + 4*base*in[2]
|
||||
out4 = 4*base
|
||||
|
||||
The result should be compensated.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
The scalar is s = a0 + a1*2^3 + a2*2^6 + ...... + a81*2^243
|
||||
First We calculate Q = B + 2^3*B + 2^6*B + ......... + 2^246*B
|
||||
|
||||
Then we calculate S1 = 2*2^246*B + (1 + a0)*B + (2^3 + a1)*B + .....+ (2^243 + a81)*B
|
||||
|
||||
And Finaly we compute the result: RES = SQ - Q
|
||||
|
||||
As you can see the input of the adders cannot be equal nor zero, except for the last
|
||||
substraction that it's done in montgomery.
|
||||
|
||||
A good way to see it is that the accumulator input of the adder >= 2^247*B and the other input
|
||||
is the output of the windows that it's going to be <= 2^246*B
|
||||
*/
|
||||
/* base must not be the neutral element nor points of small order */
|
||||
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
|
||||
nWindows must not exceed 82
|
||||
Signals:
|
||||
e: The scalar in bits
|
||||
base: the base point in edwards format
|
||||
out: The result
|
||||
dbl: Point in Montgomery to be linked to the next segment.
|
||||
*/
|
||||
|
||||
template SegmentMulFix(nWindows) {
|
||||
signal input e[nWindows*3];
|
||||
signal input base[2];
|
||||
signal output out[2];
|
||||
signal output dbl[2];
|
||||
|
||||
var i;
|
||||
var j;
|
||||
|
||||
// Convert the base to montgomery
|
||||
|
||||
component e2m = Edwards2Montgomery();
|
||||
e2m.in[0] <== base[0];
|
||||
e2m.in[1] <== base[1];
|
||||
|
||||
component windows[nWindows];
|
||||
component adders[nWindows];
|
||||
component cadders[nWindows];
|
||||
|
||||
// In the last step we add an extra doubler so that numbers do not match.
|
||||
component dblLast = MontgomeryDouble();
|
||||
|
||||
for (i=0; i<nWindows; i++) {
|
||||
windows[i] = WindowMulFix();
|
||||
cadders[i] = MontgomeryAdd();
|
||||
if (i==0) {
|
||||
windows[i].base[0] <== e2m.out[0];
|
||||
windows[i].base[1] <== e2m.out[1];
|
||||
cadders[i].in1[0] <== e2m.out[0];
|
||||
cadders[i].in1[1] <== e2m.out[1];
|
||||
} else {
|
||||
windows[i].base[0] <== windows[i-1].out8[0];
|
||||
windows[i].base[1] <== windows[i-1].out8[1];
|
||||
cadders[i].in1[0] <== cadders[i-1].out[0];
|
||||
cadders[i].in1[1] <== cadders[i-1].out[1];
|
||||
}
|
||||
if (i<nWindows-1) {
|
||||
cadders[i].in2[0] <== windows[i].out8[0];
|
||||
cadders[i].in2[1] <== windows[i].out8[1];
|
||||
} else {
|
||||
dblLast.in[0] <== windows[i].out8[0];
|
||||
dblLast.in[1] <== windows[i].out8[1];
|
||||
cadders[i].in2[0] <== dblLast.out[0];
|
||||
cadders[i].in2[1] <== dblLast.out[1];
|
||||
}
|
||||
for (j=0; j<3; j++) {
|
||||
windows[i].in[j] <== e[3*i+j];
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<nWindows; i++) {
|
||||
adders[i] = MontgomeryAdd();
|
||||
if (i==0) {
|
||||
adders[i].in1[0] <== dblLast.out[0];
|
||||
adders[i].in1[1] <== dblLast.out[1];
|
||||
} else {
|
||||
adders[i].in1[0] <== adders[i-1].out[0];
|
||||
adders[i].in1[1] <== adders[i-1].out[1];
|
||||
}
|
||||
adders[i].in2[0] <== windows[i].out[0];
|
||||
adders[i].in2[1] <== windows[i].out[1];
|
||||
}
|
||||
|
||||
component m2e = Montgomery2Edwards();
|
||||
component cm2e = Montgomery2Edwards();
|
||||
|
||||
m2e.in[0] <== adders[nWindows-1].out[0];
|
||||
m2e.in[1] <== adders[nWindows-1].out[1];
|
||||
cm2e.in[0] <== cadders[nWindows-1].out[0];
|
||||
cm2e.in[1] <== cadders[nWindows-1].out[1];
|
||||
|
||||
component cAdd = BabyAdd();
|
||||
cAdd.x1 <== m2e.out[0];
|
||||
cAdd.y1 <== m2e.out[1];
|
||||
cAdd.x2 <== -cm2e.out[0];
|
||||
cAdd.y2 <== cm2e.out[1];
|
||||
|
||||
cAdd.xout ==> out[0];
|
||||
cAdd.yout ==> out[1];
|
||||
|
||||
windows[nWindows-1].out8[0] ==> dbl[0];
|
||||
windows[nWindows-1].out8[1] ==> dbl[1];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This component multiplies a escalar times a fixed point BASE (twisted edwards format)
|
||||
Signals
|
||||
e: The escalar in binary format
|
||||
out: The output point in twisted edwards
|
||||
*/
|
||||
template EscalarMulFix(n, BASE) {
|
||||
signal input e[n]; // Input in binary format
|
||||
signal output out[2]; // Point (Twisted format)
|
||||
|
||||
var nsegments = (n-1)\246 +1; // 249 probably would work. But I'm not sure and for security I keep 246
|
||||
var nlastsegment = n - (nsegments-1)*246;
|
||||
|
||||
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) ? 246 : nlastsegment;
|
||||
nWindows = ((nseg - 1)\3)+1;
|
||||
|
||||
segments[s] = SegmentMulFix(nWindows);
|
||||
|
||||
for (i=0; i<nseg; i++) {
|
||||
segments[s].e[i] <== e[s*246+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];
|
||||
}
|
||||
}
|
51
@tornado/circomlib/circuits/escalarmulw4table.circom
Normal file
51
@tornado/circomlib/circuits/escalarmulw4table.circom
Normal file
@ -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/>.
|
||||
*/
|
||||
|
||||
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 = 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;
|
||||
}
|
92
@tornado/circomlib/circuits/gates.circom
Normal file
92
@tornado/circomlib/circuits/gates.circom
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
template XOR() {
|
||||
signal input a;
|
||||
signal input b;
|
||||
signal output out;
|
||||
|
||||
out <== a + b - 2*a*b;
|
||||
}
|
||||
|
||||
template AND() {
|
||||
signal input a;
|
||||
signal input b;
|
||||
signal output out;
|
||||
|
||||
out <== a*b;
|
||||
}
|
||||
|
||||
template OR() {
|
||||
signal input a;
|
||||
signal input b;
|
||||
signal output out;
|
||||
|
||||
out <== a + b - a*b;
|
||||
}
|
||||
|
||||
template NOT() {
|
||||
signal input in;
|
||||
signal output out;
|
||||
|
||||
out <== 1 + in - 2*in;
|
||||
}
|
||||
|
||||
template NAND() {
|
||||
signal input a;
|
||||
signal input b;
|
||||
signal output out;
|
||||
|
||||
out <== 1 - a*b;
|
||||
}
|
||||
|
||||
template NOR() {
|
||||
signal input a;
|
||||
signal input b;
|
||||
signal output out;
|
||||
|
||||
out <== a*b + 1 - a - b;
|
||||
}
|
||||
|
||||
template MultiAND(n) {
|
||||
signal input in[n];
|
||||
signal output out;
|
||||
if (n==1) {
|
||||
out <== in[0];
|
||||
} else if (n==2) {
|
||||
component and1 = AND();
|
||||
and1.a <== in[0];
|
||||
and1.b <== in[1];
|
||||
out <== and1.out;
|
||||
} else {
|
||||
component and2 = AND();
|
||||
component ands[2];
|
||||
var n1 = n\2;
|
||||
var n2 = n-n\2;
|
||||
ands[0] = MultiAND(n1);
|
||||
ands[1] = MultiAND(n2);
|
||||
for (var i=0; i<n1; i++) ands[0].in[i] <== in[i];
|
||||
for (var i=0; i<n2; i++) ands[1].in[i] <== in[n1+i];
|
||||
and2.a <== ands[0].out;
|
||||
and2.b <== ands[1].out;
|
||||
out <== and2.out;
|
||||
}
|
||||
}
|
||||
|
||||
|
155
@tornado/circomlib/circuits/mimc.circom
Normal file
155
@tornado/circomlib/circuits/mimc.circom
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
template MiMC7(nrounds) {
|
||||
signal input x_in;
|
||||
signal input k;
|
||||
signal output out;
|
||||
|
||||
var c = [
|
||||
0,
|
||||
20888961410941983456478427210666206549300505294776164667214940546594746570981,
|
||||
15265126113435022738560151911929040668591755459209400716467504685752745317193,
|
||||
8334177627492981984476504167502758309043212251641796197711684499645635709656,
|
||||
1374324219480165500871639364801692115397519265181803854177629327624133579404,
|
||||
11442588683664344394633565859260176446561886575962616332903193988751292992472,
|
||||
2558901189096558760448896669327086721003508630712968559048179091037845349145,
|
||||
11189978595292752354820141775598510151189959177917284797737745690127318076389,
|
||||
3262966573163560839685415914157855077211340576201936620532175028036746741754,
|
||||
17029914891543225301403832095880481731551830725367286980611178737703889171730,
|
||||
4614037031668406927330683909387957156531244689520944789503628527855167665518,
|
||||
19647356996769918391113967168615123299113119185942498194367262335168397100658,
|
||||
5040699236106090655289931820723926657076483236860546282406111821875672148900,
|
||||
2632385916954580941368956176626336146806721642583847728103570779270161510514,
|
||||
17691411851977575435597871505860208507285462834710151833948561098560743654671,
|
||||
11482807709115676646560379017491661435505951727793345550942389701970904563183,
|
||||
8360838254132998143349158726141014535383109403565779450210746881879715734773,
|
||||
12663821244032248511491386323242575231591777785787269938928497649288048289525,
|
||||
3067001377342968891237590775929219083706800062321980129409398033259904188058,
|
||||
8536471869378957766675292398190944925664113548202769136103887479787957959589,
|
||||
19825444354178182240559170937204690272111734703605805530888940813160705385792,
|
||||
16703465144013840124940690347975638755097486902749048533167980887413919317592,
|
||||
13061236261277650370863439564453267964462486225679643020432589226741411380501,
|
||||
10864774797625152707517901967943775867717907803542223029967000416969007792571,
|
||||
10035653564014594269791753415727486340557376923045841607746250017541686319774,
|
||||
3446968588058668564420958894889124905706353937375068998436129414772610003289,
|
||||
4653317306466493184743870159523234588955994456998076243468148492375236846006,
|
||||
8486711143589723036499933521576871883500223198263343024003617825616410932026,
|
||||
250710584458582618659378487568129931785810765264752039738223488321597070280,
|
||||
2104159799604932521291371026105311735948154964200596636974609406977292675173,
|
||||
16313562605837709339799839901240652934758303521543693857533755376563489378839,
|
||||
6032365105133504724925793806318578936233045029919447519826248813478479197288,
|
||||
14025118133847866722315446277964222215118620050302054655768867040006542798474,
|
||||
7400123822125662712777833064081316757896757785777291653271747396958201309118,
|
||||
1744432620323851751204287974553233986555641872755053103823939564833813704825,
|
||||
8316378125659383262515151597439205374263247719876250938893842106722210729522,
|
||||
6739722627047123650704294650168547689199576889424317598327664349670094847386,
|
||||
21211457866117465531949733809706514799713333930924902519246949506964470524162,
|
||||
13718112532745211817410303291774369209520657938741992779396229864894885156527,
|
||||
5264534817993325015357427094323255342713527811596856940387954546330728068658,
|
||||
18884137497114307927425084003812022333609937761793387700010402412840002189451,
|
||||
5148596049900083984813839872929010525572543381981952060869301611018636120248,
|
||||
19799686398774806587970184652860783461860993790013219899147141137827718662674,
|
||||
19240878651604412704364448729659032944342952609050243268894572835672205984837,
|
||||
10546185249390392695582524554167530669949955276893453512788278945742408153192,
|
||||
5507959600969845538113649209272736011390582494851145043668969080335346810411,
|
||||
18177751737739153338153217698774510185696788019377850245260475034576050820091,
|
||||
19603444733183990109492724100282114612026332366576932662794133334264283907557,
|
||||
10548274686824425401349248282213580046351514091431715597441736281987273193140,
|
||||
1823201861560942974198127384034483127920205835821334101215923769688644479957,
|
||||
11867589662193422187545516240823411225342068709600734253659804646934346124945,
|
||||
18718569356736340558616379408444812528964066420519677106145092918482774343613,
|
||||
10530777752259630125564678480897857853807637120039176813174150229243735996839,
|
||||
20486583726592018813337145844457018474256372770211860618687961310422228379031,
|
||||
12690713110714036569415168795200156516217175005650145422920562694422306200486,
|
||||
17386427286863519095301372413760745749282643730629659997153085139065756667205,
|
||||
2216432659854733047132347621569505613620980842043977268828076165669557467682,
|
||||
6309765381643925252238633914530877025934201680691496500372265330505506717193,
|
||||
20806323192073945401862788605803131761175139076694468214027227878952047793390,
|
||||
4037040458505567977365391535756875199663510397600316887746139396052445718861,
|
||||
19948974083684238245321361840704327952464170097132407924861169241740046562673,
|
||||
845322671528508199439318170916419179535949348988022948153107378280175750024,
|
||||
16222384601744433420585982239113457177459602187868460608565289920306145389382,
|
||||
10232118865851112229330353999139005145127746617219324244541194256766741433339,
|
||||
6699067738555349409504843460654299019000594109597429103342076743347235369120,
|
||||
6220784880752427143725783746407285094967584864656399181815603544365010379208,
|
||||
6129250029437675212264306655559561251995722990149771051304736001195288083309,
|
||||
10773245783118750721454994239248013870822765715268323522295722350908043393604,
|
||||
4490242021765793917495398271905043433053432245571325177153467194570741607167,
|
||||
19596995117319480189066041930051006586888908165330319666010398892494684778526,
|
||||
837850695495734270707668553360118467905109360511302468085569220634750561083,
|
||||
11803922811376367215191737026157445294481406304781326649717082177394185903907,
|
||||
10201298324909697255105265958780781450978049256931478989759448189112393506592,
|
||||
13564695482314888817576351063608519127702411536552857463682060761575100923924,
|
||||
9262808208636973454201420823766139682381973240743541030659775288508921362724,
|
||||
173271062536305557219323722062711383294158572562695717740068656098441040230,
|
||||
18120430890549410286417591505529104700901943324772175772035648111937818237369,
|
||||
20484495168135072493552514219686101965206843697794133766912991150184337935627,
|
||||
19155651295705203459475805213866664350848604323501251939850063308319753686505,
|
||||
11971299749478202793661982361798418342615500543489781306376058267926437157297,
|
||||
18285310723116790056148596536349375622245669010373674803854111592441823052978,
|
||||
7069216248902547653615508023941692395371990416048967468982099270925308100727,
|
||||
6465151453746412132599596984628739550147379072443683076388208843341824127379,
|
||||
16143532858389170960690347742477978826830511669766530042104134302796355145785,
|
||||
19362583304414853660976404410208489566967618125972377176980367224623492419647,
|
||||
1702213613534733786921602839210290505213503664731919006932367875629005980493,
|
||||
10781825404476535814285389902565833897646945212027592373510689209734812292327,
|
||||
4212716923652881254737947578600828255798948993302968210248673545442808456151,
|
||||
7594017890037021425366623750593200398174488805473151513558919864633711506220,
|
||||
18979889247746272055963929241596362599320706910852082477600815822482192194401,
|
||||
13602139229813231349386885113156901793661719180900395818909719758150455500533
|
||||
];
|
||||
|
||||
var t;
|
||||
signal t2[nrounds];
|
||||
signal t4[nrounds];
|
||||
signal t6[nrounds];
|
||||
signal t7[nrounds-1];
|
||||
|
||||
for (var i=0; i<nrounds; i++) {
|
||||
t = (i==0) ? k+x_in : k + t7[i-1] + c[i];
|
||||
t2[i] <== t*t;
|
||||
t4[i] <== t2[i]*t2[i];
|
||||
t6[i] <== t4[i]*t2[i];
|
||||
if (i<nrounds-1) {
|
||||
t7[i] <== t6[i]*t;
|
||||
} else {
|
||||
out <== t6[i]*t + k;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template MultiMiMC7(nInputs, nRounds) {
|
||||
signal input in[nInputs];
|
||||
signal input k;
|
||||
signal output out;
|
||||
signal r[nInputs +1];
|
||||
|
||||
component mims[nInputs];
|
||||
|
||||
r[0] <== k;
|
||||
for (var i=0; i<nInputs; i++) {
|
||||
mims[i] = MiMC7(nRounds);
|
||||
mims[i].x_in <== in[i];
|
||||
mims[i].k <== r[i];
|
||||
r[i+1] <== r[i] + in[i] + mims[i].out;
|
||||
}
|
||||
|
||||
out <== r[nInputs];
|
||||
}
|
290
@tornado/circomlib/circuits/mimcsponge.circom
Normal file
290
@tornado/circomlib/circuits/mimcsponge.circom
Normal file
@ -0,0 +1,290 @@
|
||||
// implements MiMC-2n/n as hash using a sponge construction.
|
||||
// log_5(21888242871839275222246405745257275088548364400416034343698204186575808495617) ~= 110
|
||||
// => nRounds should be 220
|
||||
template MiMCSponge(nInputs, nOutputs) {
|
||||
signal input ins[nInputs];
|
||||
signal input k;
|
||||
signal output outs[nOutputs];
|
||||
|
||||
var nRounds = 220;
|
||||
|
||||
// S = R||C
|
||||
component S[nInputs + nOutputs - 1];
|
||||
|
||||
for (var i = 0; i < nInputs; i++) {
|
||||
S[i] = MiMCFeistel(nRounds);
|
||||
S[i].k <== k;
|
||||
if (i == 0) {
|
||||
S[i].xL_in <== ins[0];
|
||||
S[i].xR_in <== 0;
|
||||
} else {
|
||||
S[i].xL_in <== S[i-1].xL_out + ins[i];
|
||||
S[i].xR_in <== S[i-1].xR_out;
|
||||
}
|
||||
}
|
||||
|
||||
outs[0] <== S[nInputs - 1].xL_out;
|
||||
|
||||
for (var i = 0; i < nOutputs - 1; i++) {
|
||||
S[nInputs + i] = MiMCFeistel(nRounds);
|
||||
S[nInputs + i].k <== k;
|
||||
S[nInputs + i].xL_in <== S[nInputs + i - 1].xL_out;
|
||||
S[nInputs + i].xR_in <== S[nInputs + i - 1].xR_out;
|
||||
outs[i + 1] <== S[nInputs + i].xL_out;
|
||||
}
|
||||
}
|
||||
|
||||
template MiMCFeistel(nrounds) {
|
||||
signal input xL_in;
|
||||
signal input xR_in;
|
||||
signal input k;
|
||||
signal output xL_out;
|
||||
signal output xR_out;
|
||||
|
||||
// doesn't contain the first and last round constants, which are always zero
|
||||
var c_partial = [
|
||||
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) {
|
||||
xL[i] <== ((i==0) ? xR_in : xR[i-1]) + t4[i]*t;
|
||||
xR[i] <== (i==0) ? xL_in : xL[i-1];
|
||||
} else {
|
||||
xR_out <== xR[i-1] + t4[i]*t;
|
||||
xL_out <== xL[i-1];
|
||||
}
|
||||
}
|
||||
}
|
142
@tornado/circomlib/circuits/montgomery.circom
Normal file
142
@tornado/circomlib/circuits/montgomery.circom
Normal file
@ -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
|
||||
|
||||
*/
|
||||
|
||||
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
|
||||
|
||||
*/
|
||||
|
||||
/* in1 must be != in2 */
|
||||
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];
|
||||
}
|
113
@tornado/circomlib/circuits/multiplexer.circom
Normal file
113
@tornado/circomlib/circuits/multiplexer.circom
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// --> Assignation without constraint
|
||||
// <-- Assignation without constraint
|
||||
// === Constraint
|
||||
// <== Assignation with constraint
|
||||
// ==> Assignation with constraint
|
||||
// All variables are members of the field F[p]
|
||||
// https://github.com/zcash-hackworks/sapling-crypto
|
||||
// https://github.com/ebfull/bellman
|
||||
|
||||
/*
|
||||
function log2(a) {
|
||||
if (a==0) {
|
||||
return 0;
|
||||
}
|
||||
let n = 1;
|
||||
let r = 1;
|
||||
while (n<a) {
|
||||
r++;
|
||||
n *= 2;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
*/
|
||||
|
||||
template EscalarProduct(w) {
|
||||
signal input in1[w];
|
||||
signal input in2[w];
|
||||
signal output out;
|
||||
signal aux[w];
|
||||
var lc = 0;
|
||||
for (var i=0; i<w; i++) {
|
||||
aux[i] <== in1[i]*in2[i];
|
||||
lc = lc + aux[i];
|
||||
}
|
||||
out <== lc;
|
||||
}
|
||||
|
||||
template Decoder(w) {
|
||||
signal input inp;
|
||||
signal output out[w];
|
||||
signal output success;
|
||||
var lc=0;
|
||||
|
||||
for (var i=0; i<w; i++) {
|
||||
out[i] <-- (inp == i) ? 1 : 0;
|
||||
out[i] * (inp-i) === 0;
|
||||
lc = lc + out[i];
|
||||
}
|
||||
|
||||
lc ==> success;
|
||||
success * (success -1) === 0;
|
||||
}
|
||||
|
||||
|
||||
template Multiplexer(wIn, nIn) {
|
||||
signal input inp[nIn][wIn];
|
||||
signal input sel;
|
||||
signal output out[wIn];
|
||||
component dec = Decoder(nIn);
|
||||
component ep[wIn];
|
||||
|
||||
for (var k=0; k<wIn; k++) {
|
||||
ep[k] = EscalarProduct(nIn);
|
||||
}
|
||||
|
||||
sel ==> dec.inp;
|
||||
for (var j=0; j<wIn; j++) {
|
||||
for (var k=0; k<nIn; k++) {
|
||||
inp[k][j] ==> ep[j].in1[k];
|
||||
dec.out[k] ==> ep[j].in2[k];
|
||||
}
|
||||
ep[j].out ==> out[j];
|
||||
}
|
||||
dec.success === 1;
|
||||
}
|
47
@tornado/circomlib/circuits/mux1.circom
Normal file
47
@tornado/circomlib/circuits/mux1.circom
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
template MultiMux1(n) {
|
||||
signal input c[n][2]; // Constants
|
||||
signal input s; // Selector
|
||||
signal output out[n];
|
||||
|
||||
for (var i=0; i<n; i++) {
|
||||
|
||||
out[i] <== (c[i][1] - c[i][0])*s + c[i][0];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template Mux1() {
|
||||
var i;
|
||||
signal input c[2]; // Constants
|
||||
signal input s; // Selector
|
||||
signal output out;
|
||||
|
||||
component mux = MultiMux1(1);
|
||||
|
||||
for (i=0; i<2; i++) {
|
||||
mux.c[0][i] <== c[i];
|
||||
}
|
||||
|
||||
s ==> mux.s;
|
||||
|
||||
mux.out[0] ==> out;
|
||||
}
|
62
@tornado/circomlib/circuits/mux2.circom
Normal file
62
@tornado/circomlib/circuits/mux2.circom
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
template MultiMux2(n) {
|
||||
signal input c[n][4]; // Constants
|
||||
signal input s[2]; // Selector
|
||||
signal output out[n];
|
||||
|
||||
signal a10[n];
|
||||
signal a1[n];
|
||||
signal a0[n];
|
||||
signal a[n];
|
||||
|
||||
signal s10;
|
||||
s10 <== s[1] * s[0];
|
||||
|
||||
for (var i=0; i<n; i++) {
|
||||
|
||||
a10[i] <== ( c[i][ 3]-c[i][ 2]-c[i][ 1]+c[i][ 0] ) * s10;
|
||||
a1[i] <== ( c[i][ 2]-c[i][ 0] ) * s[1];
|
||||
a0[i] <== ( c[i][ 1]-c[i][ 0] ) * s[0];
|
||||
a[i] <== ( c[i][ 0] )
|
||||
|
||||
out[i] <== ( a10[i] + a1[i] + a0[i] + a[i] );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template Mux2() {
|
||||
var i;
|
||||
signal input c[4]; // Constants
|
||||
signal input s[2]; // Selector
|
||||
signal output out;
|
||||
|
||||
component mux = MultiMux2(1);
|
||||
|
||||
for (i=0; i<4; i++) {
|
||||
mux.c[0][i] <== c[i];
|
||||
}
|
||||
|
||||
for (i=0; i<2; i++) {
|
||||
s[i] ==> mux.s[i];
|
||||
}
|
||||
|
||||
mux.out[0] ==> out;
|
||||
}
|
74
@tornado/circomlib/circuits/mux3.circom
Normal file
74
@tornado/circomlib/circuits/mux3.circom
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
template MultiMux3(n) {
|
||||
signal input c[n][8]; // Constants
|
||||
signal input s[3]; // Selector
|
||||
signal output out[n];
|
||||
|
||||
signal a210[n];
|
||||
signal a21[n];
|
||||
signal a20[n];
|
||||
signal a2[n];
|
||||
|
||||
signal a10[n];
|
||||
signal a1[n];
|
||||
signal a0[n];
|
||||
signal a[n];
|
||||
|
||||
// 4 constrains for the intermediary variables
|
||||
signal s10;
|
||||
s10 <== s[1] * s[0];
|
||||
|
||||
for (var i=0; i<n; i++) {
|
||||
|
||||
a210[i] <== ( c[i][ 7]-c[i][ 6]-c[i][ 5]+c[i][ 4] - c[i][ 3]+c[i][ 2]+c[i][ 1]-c[i][ 0] ) * s10;
|
||||
a21[i] <== ( c[i][ 6]-c[i][ 4]-c[i][ 2]+c[i][ 0] ) * s[1];
|
||||
a20[i] <== ( c[i][ 5]-c[i][ 4]-c[i][ 1]+c[i][ 0] ) * s[0];
|
||||
a2[i] <== ( c[i][ 4]-c[i][ 0] );
|
||||
|
||||
a10[i] <== ( c[i][ 3]-c[i][ 2]-c[i][ 1]+c[i][ 0] ) * s10;
|
||||
a1[i] <== ( c[i][ 2]-c[i][ 0] ) * s[1];
|
||||
a0[i] <== ( c[i][ 1]-c[i][ 0] ) * s[0];
|
||||
a[i] <== ( c[i][ 0] )
|
||||
|
||||
out[i] <== ( a210[i] + a21[i] + a20[i] + a2[i] ) * s[2] +
|
||||
( a10[i] + a1[i] + a0[i] + a[i] );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template Mux3() {
|
||||
var i;
|
||||
signal input c[8]; // Constants
|
||||
signal input s[3]; // Selector
|
||||
signal output out;
|
||||
|
||||
component mux = MultiMux3(1);
|
||||
|
||||
for (i=0; i<8; i++) {
|
||||
mux.c[0][i] <== c[i];
|
||||
}
|
||||
|
||||
for (i=0; i<3; i++) {
|
||||
s[i] ==> mux.s[i];
|
||||
}
|
||||
|
||||
mux.out[0] ==> out;
|
||||
}
|
118
@tornado/circomlib/circuits/mux4.circom
Normal file
118
@tornado/circomlib/circuits/mux4.circom
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
template MultiMux4(n) {
|
||||
signal input c[n][16]; // Constants
|
||||
signal input s[4]; // Selector
|
||||
signal output out[n];
|
||||
|
||||
signal a3210[n];
|
||||
signal a321[n];
|
||||
signal a320[n];
|
||||
signal a310[n];
|
||||
signal a32[n];
|
||||
signal a31[n];
|
||||
signal a30[n];
|
||||
signal a3[n];
|
||||
|
||||
signal a210[n];
|
||||
signal a21[n];
|
||||
signal a20[n];
|
||||
signal a10[n];
|
||||
signal a2[n];
|
||||
signal a1[n];
|
||||
signal a0[n];
|
||||
signal a[n];
|
||||
|
||||
// 4 constrains for the intermediary variables
|
||||
signal s10;
|
||||
s10 <== s[1] * s[0];
|
||||
signal s20;
|
||||
s20 <== s[2] * s[0];
|
||||
signal s21;
|
||||
s21 <== s[2] * s[1];
|
||||
signal s210;
|
||||
s210 <== s21 * s[0];
|
||||
|
||||
|
||||
for (var i=0; i<n; i++) {
|
||||
|
||||
a3210[i] <== ( c[i][15]-c[i][14]-c[i][13]+c[i][12] - c[i][11]+c[i][10]+c[i][ 9]-c[i][ 8]
|
||||
-c[i][ 7]+c[i][ 6]+c[i][ 5]-c[i][ 4] + c[i][ 3]-c[i][ 2]-c[i][ 1]+c[i][ 0] ) * s210;
|
||||
a321[i] <== ( c[i][14]-c[i][12]-c[i][10]+c[i][ 8] - c[i][ 6]+c[i][ 4]+c[i][ 2]-c[i][ 0] ) * s21;
|
||||
a320[i] <== ( c[i][13]-c[i][12]-c[i][ 9]+c[i][ 8] - c[i][ 5]+c[i][ 4]+c[i][ 1]-c[i][ 0] ) * s20;
|
||||
a310[i] <== ( c[i][11]-c[i][10]-c[i][ 9]+c[i][ 8] - c[i][ 3]+c[i][ 2]+c[i][ 1]-c[i][ 0] ) * s10;
|
||||
a32[i] <== ( c[i][12]-c[i][ 8]-c[i][ 4]+c[i][ 0] ) * s[2];
|
||||
a31[i] <== ( c[i][10]-c[i][ 8]-c[i][ 2]+c[i][ 0] ) * s[1];
|
||||
a30[i] <== ( c[i][ 9]-c[i][ 8]-c[i][ 1]+c[i][ 0] ) * s[0];
|
||||
a3[i] <== ( c[i][ 8]-c[i][ 0] );
|
||||
|
||||
a210[i] <== ( c[i][ 7]-c[i][ 6]-c[i][ 5]+c[i][ 4] - c[i][ 3]+c[i][ 2]+c[i][ 1]-c[i][ 0] ) * s210;
|
||||
a21[i] <== ( c[i][ 6]-c[i][ 4]-c[i][ 2]+c[i][ 0] ) * s21;
|
||||
a20[i] <== ( c[i][ 5]-c[i][ 4]-c[i][ 1]+c[i][ 0] ) * s20;
|
||||
a10[i] <== ( c[i][ 3]-c[i][ 2]-c[i][ 1]+c[i][ 0] ) * s10;
|
||||
a2[i] <== ( c[i][ 4]-c[i][ 0] ) * s[2];
|
||||
a1[i] <== ( c[i][ 2]-c[i][ 0] ) * s[1];
|
||||
a0[i] <== ( c[i][ 1]-c[i][ 0] ) * s[0];
|
||||
a[i] <== ( c[i][ 0] )
|
||||
|
||||
out[i] <== ( a3210[i] + a321[i] + a320[i] + a310[i] + a32[i] + a31[i] + a30[i] + a3[i] ) * s[3] +
|
||||
( a210[i] + a21[i] + a20[i] + a10[i] + a2[i] + a1[i] + a0[i] + a[i] );
|
||||
|
||||
/*
|
||||
out[i] <== ( s210 * ( c[i][15]-c[i][14]-c[i][13]+c[i][12] - c[i][11]+c[i][10]+c[i][ 9]-c[i][ 8]
|
||||
-c[i][ 7]+c[i][ 6]+c[i][ 5]-c[i][ 4] + c[i][ 3]-c[i][ 2]-c[i][ 1]+c[i][ 0] ) +
|
||||
s21 * ( c[i][14]-c[i][12]-c[i][10]+c[i][ 8] - c[i][ 6]+c[i][ 4]+c[i][ 2]-c[i][ 0] ) +
|
||||
s20 * ( c[i][13]-c[i][12]-c[i][ 9]+c[i][ 8] - c[i][ 5]+c[i][ 4]+c[i][ 1]-c[i][ 0] ) +
|
||||
s10 * ( c[i][11]-c[i][10]-c[i][ 9]+c[i][ 8] - c[i][ 3]+c[i][ 2]+c[i][ 1]-c[i][ 0] ) +
|
||||
s[2] * ( c[i][12]-c[i][ 8]-c[i][ 4]+c[i][ 0] ) +
|
||||
s[1] * ( c[i][10]-c[i][ 8]-c[i][ 2]+c[i][ 0] ) +
|
||||
s[0] * ( c[i][ 9]-c[i][ 8]-c[i][ 1]+c[i][ 0] ) +
|
||||
( c[i][ 8]-c[i][ 0] ) ) * s[3] +
|
||||
( s210 * ( c[i][ 7]-c[i][ 6]-c[i][ 5]+c[i][ 4] - c[i][ 3]+c[i][ 2]+c[i][ 1]-c[i][ 0] ) +
|
||||
s21 * ( c[i][ 6]-c[i][ 4]-c[i][ 2]+c[i][ 0] ) +
|
||||
s20 * ( c[i][ 5]-c[i][ 4]-c[i][ 1]+c[i][ 0] ) +
|
||||
s10 * ( c[i][ 3]-c[i][ 2]-c[i][ 1]+c[i][ 0] ) +
|
||||
s[2] * ( c[i][ 4]-c[i][ 0] ) +
|
||||
s[1] * ( c[i][ 2]-c[i][ 0] ) +
|
||||
s[0] * ( c[i][ 1]-c[i][ 0] ) +
|
||||
( c[i][ 0] ));
|
||||
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
template Mux4() {
|
||||
var i;
|
||||
signal input c[16]; // Constants
|
||||
signal input s[4]; // Selector
|
||||
signal output out;
|
||||
|
||||
component mux = MultiMux4(1);
|
||||
|
||||
for (i=0; i<16; i++) {
|
||||
mux.c[0][i] <== c[i];
|
||||
}
|
||||
|
||||
for (i=0; i<4; i++) {
|
||||
s[i] ==> mux.s[i];
|
||||
}
|
||||
|
||||
mux.out[0] ==> out;
|
||||
}
|
256
@tornado/circomlib/circuits/pedersen.circom
Normal file
256
@tornado/circomlib/circuits/pedersen.circom
Normal file
@ -0,0 +1,256 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "montgomery.circom";
|
||||
include "mux3.circom";
|
||||
include "babyjub.circom";
|
||||
|
||||
template Window4() {
|
||||
signal input in[4];
|
||||
signal input base[2];
|
||||
signal output out[2];
|
||||
signal output out8[2]; // Returns 8*Base (To be linked)
|
||||
|
||||
component mux = MultiMux3(2);
|
||||
|
||||
mux.s[0] <== in[0];
|
||||
mux.s[1] <== in[1];
|
||||
mux.s[2] <== in[2];
|
||||
|
||||
component dbl2 = MontgomeryDouble();
|
||||
component adr3 = MontgomeryAdd();
|
||||
component adr4 = MontgomeryAdd();
|
||||
component adr5 = MontgomeryAdd();
|
||||
component adr6 = MontgomeryAdd();
|
||||
component adr7 = MontgomeryAdd();
|
||||
component adr8 = MontgomeryAdd();
|
||||
|
||||
// in[0] -> 1*BASE
|
||||
|
||||
mux.c[0][0] <== base[0];
|
||||
mux.c[1][0] <== base[1];
|
||||
|
||||
// in[1] -> 2*BASE
|
||||
dbl2.in[0] <== base[0];
|
||||
dbl2.in[1] <== base[1];
|
||||
mux.c[0][1] <== dbl2.out[0];
|
||||
mux.c[1][1] <== dbl2.out[1];
|
||||
|
||||
// in[2] -> 3*BASE
|
||||
adr3.in1[0] <== base[0];
|
||||
adr3.in1[1] <== base[1];
|
||||
adr3.in2[0] <== dbl2.out[0];
|
||||
adr3.in2[1] <== dbl2.out[1];
|
||||
mux.c[0][2] <== adr3.out[0];
|
||||
mux.c[1][2] <== adr3.out[1];
|
||||
|
||||
// in[3] -> 4*BASE
|
||||
adr4.in1[0] <== base[0];
|
||||
adr4.in1[1] <== base[1];
|
||||
adr4.in2[0] <== adr3.out[0];
|
||||
adr4.in2[1] <== adr3.out[1];
|
||||
mux.c[0][3] <== adr4.out[0];
|
||||
mux.c[1][3] <== adr4.out[1];
|
||||
|
||||
// in[4] -> 5*BASE
|
||||
adr5.in1[0] <== base[0];
|
||||
adr5.in1[1] <== base[1];
|
||||
adr5.in2[0] <== adr4.out[0];
|
||||
adr5.in2[1] <== adr4.out[1];
|
||||
mux.c[0][4] <== adr5.out[0];
|
||||
mux.c[1][4] <== adr5.out[1];
|
||||
|
||||
// in[5] -> 6*BASE
|
||||
adr6.in1[0] <== base[0];
|
||||
adr6.in1[1] <== base[1];
|
||||
adr6.in2[0] <== adr5.out[0];
|
||||
adr6.in2[1] <== adr5.out[1];
|
||||
mux.c[0][5] <== adr6.out[0];
|
||||
mux.c[1][5] <== adr6.out[1];
|
||||
|
||||
// in[6] -> 7*BASE
|
||||
adr7.in1[0] <== base[0];
|
||||
adr7.in1[1] <== base[1];
|
||||
adr7.in2[0] <== adr6.out[0];
|
||||
adr7.in2[1] <== adr6.out[1];
|
||||
mux.c[0][6] <== adr7.out[0];
|
||||
mux.c[1][6] <== adr7.out[1];
|
||||
|
||||
// in[7] -> 8*BASE
|
||||
adr8.in1[0] <== base[0];
|
||||
adr8.in1[1] <== base[1];
|
||||
adr8.in2[0] <== adr7.out[0];
|
||||
adr8.in2[1] <== adr7.out[1];
|
||||
mux.c[0][7] <== adr8.out[0];
|
||||
mux.c[1][7] <== adr8.out[1];
|
||||
|
||||
out8[0] <== adr8.out[0];
|
||||
out8[1] <== adr8.out[1];
|
||||
|
||||
out[0] <== mux.out[0];
|
||||
out[1] <== - mux.out[1]*2*in[3] + mux.out[1]; // Negate y if in[3] is one
|
||||
}
|
||||
|
||||
|
||||
/* nWindows must not exceed 50 */
|
||||
template Segment(nWindows) {
|
||||
signal input in[nWindows*4];
|
||||
signal input base[2];
|
||||
signal output out[2];
|
||||
|
||||
var i;
|
||||
var j;
|
||||
|
||||
// Convert the base to montgomery
|
||||
|
||||
component e2m = Edwards2Montgomery();
|
||||
e2m.in[0] <== base[0];
|
||||
e2m.in[1] <== base[1];
|
||||
|
||||
component windows[nWindows];
|
||||
component doublers1[nWindows-1];
|
||||
component doublers2[nWindows-1];
|
||||
component adders[nWindows-1];
|
||||
for (i=0; i<nWindows; i++) {
|
||||
windows[i] = Window4();
|
||||
if (i==0) {
|
||||
windows[i].base[0] <== e2m.out[0];
|
||||
windows[i].base[1] <== e2m.out[1];
|
||||
} else {
|
||||
doublers1[i-1] = MontgomeryDouble();
|
||||
doublers2[i-1] = MontgomeryDouble();
|
||||
doublers1[i-1].in[0] <== windows[i-1].out8[0];
|
||||
doublers1[i-1].in[1] <== windows[i-1].out8[1];
|
||||
doublers2[i-1].in[0] <== doublers1[i-1].out[0];
|
||||
doublers2[i-1].in[1] <== doublers1[i-1].out[1];
|
||||
|
||||
windows[i].base[0] <== doublers2[i-1].out[0];
|
||||
windows[i].base[1] <== doublers2[i-1].out[1];
|
||||
|
||||
adders[i-1] = MontgomeryAdd();
|
||||
if (i==1) {
|
||||
adders[i-1].in1[0] <== windows[0].out[0];
|
||||
adders[i-1].in1[1] <== windows[0].out[1];
|
||||
} else {
|
||||
adders[i-1].in1[0] <== adders[i-2].out[0];
|
||||
adders[i-1].in1[1] <== adders[i-2].out[1];
|
||||
}
|
||||
adders[i-1].in2[0] <== windows[i].out[0];
|
||||
adders[i-1].in2[1] <== windows[i].out[1];
|
||||
}
|
||||
for (j=0; j<4; j++) {
|
||||
windows[i].in[j] <== in[4*i+j];
|
||||
}
|
||||
}
|
||||
|
||||
component m2e = Montgomery2Edwards();
|
||||
|
||||
if (nWindows > 1) {
|
||||
m2e.in[0] <== adders[nWindows-2].out[0];
|
||||
m2e.in[1] <== adders[nWindows-2].out[1];
|
||||
} else {
|
||||
m2e.in[0] <== windows[0].out[0];
|
||||
m2e.in[1] <== windows[0].out[1];
|
||||
}
|
||||
|
||||
out[0] <== m2e.out[0];
|
||||
out[1] <== m2e.out[1];
|
||||
}
|
||||
|
||||
template Pedersen(n) {
|
||||
signal input in[n];
|
||||
signal output out[2];
|
||||
|
||||
var BASE = [
|
||||
[10457101036533406547632367118273992217979173478358440826365724437999023779287,19824078218392094440610104313265183977899662750282163392862422243483260492317],
|
||||
[2671756056509184035029146175565761955751135805354291559563293617232983272177,2663205510731142763556352975002641716101654201788071096152948830924149045094],
|
||||
[5802099305472655231388284418920769829666717045250560929368476121199858275951,5980429700218124965372158798884772646841287887664001482443826541541529227896],
|
||||
[7107336197374528537877327281242680114152313102022415488494307685842428166594,2857869773864086953506483169737724679646433914307247183624878062391496185654],
|
||||
[20265828622013100949498132415626198973119240347465898028410217039057588424236,1160461593266035632937973507065134938065359936056410650153315956301179689506],
|
||||
[1487999857809287756929114517587739322941449154962237464737694709326309567994,14017256862867289575056460215526364897734808720610101650676790868051368668003],
|
||||
[14618644331049802168996997831720384953259095788558646464435263343433563860015,13115243279999696210147231297848654998887864576952244320558158620692603342236],
|
||||
[6814338563135591367010655964669793483652536871717891893032616415581401894627,13660303521961041205824633772157003587453809761793065294055279768121314853695],
|
||||
[3571615583211663069428808372184817973703476260057504149923239576077102575715,11981351099832644138306422070127357074117642951423551606012551622164230222506],
|
||||
[18597552580465440374022635246985743886550544261632147935254624835147509493269,6753322320275422086923032033899357299485124665258735666995435957890214041481]
|
||||
]
|
||||
|
||||
var nSegments = ((n-1)\200)+1;
|
||||
|
||||
component segments[nSegments];
|
||||
|
||||
var i;
|
||||
var j;
|
||||
var nBits;
|
||||
var nWindows;
|
||||
for (i=0; i<nSegments; i++) {
|
||||
nBits = (i == (nSegments-1)) ? n - (nSegments-1)*200 : 200;
|
||||
nWindows = ((nBits - 1)\4)+1;
|
||||
segments[i] = Segment(nWindows);
|
||||
segments[i].base[0] <== BASE[i][0];
|
||||
segments[i].base[1] <== BASE[i][1];
|
||||
for (j = 0; j<nBits; j++) {
|
||||
segments[i].in[j] <== in[i*200+j];
|
||||
}
|
||||
// Fill padding bits
|
||||
for (j = nBits; j < nWindows*4; j++) {
|
||||
segments[i].in[j] <== 0;
|
||||
}
|
||||
}
|
||||
|
||||
component adders[nSegments-1];
|
||||
|
||||
for (i=0; i<nSegments-1; i++) {
|
||||
adders[i] = BabyAdd();
|
||||
if (i==0) {
|
||||
adders[i].x1 <== segments[0].out[0];
|
||||
adders[i].y1 <== segments[0].out[1];
|
||||
adders[i].x2 <== segments[1].out[0];
|
||||
adders[i].y2 <== segments[1].out[1];
|
||||
} else {
|
||||
adders[i].x1 <== adders[i-1].xout;
|
||||
adders[i].y1 <== adders[i-1].yout;
|
||||
adders[i].x2 <== segments[i+1].out[0];
|
||||
adders[i].y2 <== segments[i+1].out[1];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
coponent packPoint = PackPoint();
|
||||
|
||||
if (nSegments>1) {
|
||||
packPoint.in[0] <== adders[nSegments-2].xout;
|
||||
packPoint.in[1] <== adders[nSegments-2].yout;
|
||||
} else {
|
||||
packPoint.in[0] <== segments[0].out[0];
|
||||
packPoint.in[1] <== segments[0].out[1];
|
||||
}
|
||||
|
||||
out[0] <== packPoint.out[0];
|
||||
out[1] <== packPoint.out[1];
|
||||
*/
|
||||
|
||||
if (nSegments>1) {
|
||||
out[0] <== adders[nSegments-2].xout;
|
||||
out[1] <== adders[nSegments-2].yout;
|
||||
} else {
|
||||
out[0] <== segments[0].out[0];
|
||||
out[1] <== segments[0].out[1];
|
||||
}
|
||||
}
|
||||
|
66
@tornado/circomlib/circuits/pedersen_old.circom
Normal file
66
@tornado/circomlib/circuits/pedersen_old.circom
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "escalarmul.circom";
|
||||
|
||||
template Pedersen(n) {
|
||||
signal input in[n];
|
||||
signal output out[2];
|
||||
|
||||
var nexps = ((n-1) \ 250) + 1;
|
||||
var nlastbits = n - (nexps-1)*250;
|
||||
|
||||
component escalarMuls[nexps];
|
||||
|
||||
var PBASE = [
|
||||
[10457101036533406547632367118273992217979173478358440826365724437999023779287,19824078218392094440610104313265183977899662750282163392862422243483260492317],
|
||||
[2671756056509184035029146175565761955751135805354291559563293617232983272177,2663205510731142763556352975002641716101654201788071096152948830924149045094],
|
||||
[5802099305472655231388284418920769829666717045250560929368476121199858275951,5980429700218124965372158798884772646841287887664001482443826541541529227896],
|
||||
[7107336197374528537877327281242680114152313102022415488494307685842428166594,2857869773864086953506483169737724679646433914307247183624878062391496185654],
|
||||
[20265828622013100949498132415626198973119240347465898028410217039057588424236,1160461593266035632937973507065134938065359936056410650153315956301179689506],
|
||||
[1487999857809287756929114517587739322941449154962237464737694709326309567994,14017256862867289575056460215526364897734808720610101650676790868051368668003],
|
||||
[14618644331049802168996997831720384953259095788558646464435263343433563860015,13115243279999696210147231297848654998887864576952244320558158620692603342236],
|
||||
[6814338563135591367010655964669793483652536871717891893032616415581401894627,13660303521961041205824633772157003587453809761793065294055279768121314853695],
|
||||
[3571615583211663069428808372184817973703476260057504149923239576077102575715,11981351099832644138306422070127357074117642951423551606012551622164230222506],
|
||||
[18597552580465440374022635246985743886550544261632147935254624835147509493269,6753322320275422086923032033899357299485124665258735666995435957890214041481]
|
||||
];
|
||||
|
||||
var i;
|
||||
var j;
|
||||
var nexpbits;
|
||||
for (i=0; i<nexps; i++) {
|
||||
nexpbits = (i == nexps-1) ? nlastbits : 250;
|
||||
escalarMuls[i] = EscalarMul(nexpbits, PBASE[i]);
|
||||
|
||||
for (j=0; j<nexpbits; j++) {
|
||||
escalarMuls[i].in[j] <== in[250*i + j];
|
||||
}
|
||||
|
||||
if (i==0) {
|
||||
escalarMuls[i].inp[0] <== 0;
|
||||
escalarMuls[i].inp[1] <== 1;
|
||||
} else {
|
||||
escalarMuls[i].inp[0] <== escalarMuls[i-1].out[0];
|
||||
escalarMuls[i].inp[1] <== escalarMuls[i-1].out[1];
|
||||
}
|
||||
}
|
||||
|
||||
escalarMuls[nexps-1].out[0] ==> out[0];
|
||||
escalarMuls[nexps-1].out[1] ==> out[1];
|
||||
}
|
163
@tornado/circomlib/circuits/pointbits.circom
Normal file
163
@tornado/circomlib/circuits/pointbits.circom
Normal file
@ -0,0 +1,163 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "bitify.circom";
|
||||
include "aliascheck.circom";
|
||||
include "compconstant.circom";
|
||||
include "babyjub.circom";
|
||||
|
||||
|
||||
function sqrt(n) {
|
||||
|
||||
if (n == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Test that have solution
|
||||
var res = n ** ((-1) >> 1);
|
||||
// if (res!=1) assert(false, "SQRT does not exists");
|
||||
if (res!=1) return 0;
|
||||
|
||||
var m = 28;
|
||||
var c = 19103219067921713944291392827692070036145651957329286315305642004821462161904;
|
||||
var t = n ** 81540058820840996586704275553141814055101440848469862132140264610111;
|
||||
var r = n ** ((81540058820840996586704275553141814055101440848469862132140264610111+1)>>1);
|
||||
var sq;
|
||||
var i;
|
||||
var b;
|
||||
var j;
|
||||
|
||||
while ((r != 0)&&(t != 1)) {
|
||||
sq = t*t;
|
||||
i = 1;
|
||||
while (sq!=1) {
|
||||
i++;
|
||||
sq = sq*sq;
|
||||
}
|
||||
|
||||
// b = c ^ m-i-1
|
||||
b = c;
|
||||
for (j=0; j< m-i-1; j ++) b = b*b;
|
||||
|
||||
m = i;
|
||||
c = b*b;
|
||||
t = t*c;
|
||||
r = r*b;
|
||||
}
|
||||
|
||||
if (r > ((-1) >> 1)) {
|
||||
r = -r;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
template Bits2Point() {
|
||||
signal input in[256];
|
||||
signal output out[2];
|
||||
}
|
||||
|
||||
template Bits2Point_Strict() {
|
||||
signal input in[256];
|
||||
signal output out[2];
|
||||
|
||||
var i;
|
||||
|
||||
// Check aliasing
|
||||
component aliasCheckY = AliasCheck();
|
||||
for (i=0; i<254; i++) {
|
||||
aliasCheckY.in[i] <== in[i];
|
||||
}
|
||||
in[254] === 0;
|
||||
|
||||
component b2nY = Bits2Num(254);
|
||||
for (i=0; i<254; i++) {
|
||||
b2nY.in[i] <== in[i];
|
||||
}
|
||||
|
||||
out[1] <== b2nY.out;
|
||||
|
||||
var a = 168700;
|
||||
var d = 168696;
|
||||
|
||||
var y2 = out[1] * out[1];
|
||||
|
||||
var x = sqrt( (1-y2)/(a - d*y2) );
|
||||
|
||||
if (in[255] == 1) x = -x;
|
||||
|
||||
out[0] <-- x;
|
||||
|
||||
component babyCheck = BabyCheck();
|
||||
babyCheck.x <== out[0];
|
||||
babyCheck.y <== out[1];
|
||||
|
||||
component n2bX = Num2Bits(254);
|
||||
n2bX.in <== out[0];
|
||||
component aliasCheckX = AliasCheck();
|
||||
for (i=0; i<254; i++) {
|
||||
aliasCheckX.in[i] <== n2bX.out[i];
|
||||
}
|
||||
|
||||
component signCalc = CompConstant(10944121435919637611123202872628637544274182200208017171849102093287904247808);
|
||||
for (i=0; i<254; i++) {
|
||||
signCalc.in[i] <== n2bX.out[i];
|
||||
}
|
||||
|
||||
signCalc.out === in[255];
|
||||
}
|
||||
|
||||
|
||||
template Point2Bits() {
|
||||
signal input in[2];
|
||||
signal output out[256];
|
||||
|
||||
|
||||
}
|
||||
|
||||
template Point2Bits_Strict() {
|
||||
signal input in[2];
|
||||
signal output out[256];
|
||||
|
||||
var i;
|
||||
|
||||
component n2bX = Num2Bits(254);
|
||||
n2bX.in <== in[0];
|
||||
component n2bY = Num2Bits(254);
|
||||
n2bY.in <== in[1];
|
||||
|
||||
component aliasCheckX = AliasCheck();
|
||||
component aliasCheckY = AliasCheck();
|
||||
for (i=0; i<254; i++) {
|
||||
aliasCheckX.in[i] <== n2bX.out[i];
|
||||
aliasCheckY.in[i] <== n2bY.out[i];
|
||||
}
|
||||
|
||||
component signCalc = CompConstant(10944121435919637611123202872628637544274182200208017171849102093287904247808);
|
||||
for (i=0; i<254; i++) {
|
||||
signCalc.in[i] <== n2bX.out[i];
|
||||
}
|
||||
|
||||
for (i=0; i<254; i++) {
|
||||
out[i] <== n2bY.out[i];
|
||||
}
|
||||
out[254] <== 0;
|
||||
out[255] <== signCalc.out;
|
||||
}
|
203
@tornado/circomlib/circuits/poseidon.circom
Normal file
203
@tornado/circomlib/circuits/poseidon.circom
Normal file
@ -0,0 +1,203 @@
|
||||
|
||||
template Sigma() {
|
||||
signal input in;
|
||||
signal output out;
|
||||
|
||||
signal in2;
|
||||
signal in4;
|
||||
|
||||
in2 <== in*in;
|
||||
in4 <== in2*in2;
|
||||
|
||||
out <== in4*in;
|
||||
}
|
||||
|
||||
template Ark(t, C) {
|
||||
signal input in[t];
|
||||
signal output out[t];
|
||||
for (var i=0; i<t; i++) {
|
||||
out[i] <== in[i] + C;
|
||||
}
|
||||
}
|
||||
|
||||
template Mix(t, M) {
|
||||
signal input in[t];
|
||||
signal output out[t];
|
||||
var lc;
|
||||
|
||||
for (var i=0; i<t; i++) {
|
||||
lc = 0;
|
||||
for (var j=0; j<t; j++) {
|
||||
lc = lc + M[i][j]*in[j];
|
||||
}
|
||||
out[i] <== lc;
|
||||
}
|
||||
}
|
||||
|
||||
// var nRoundsF = 8;
|
||||
// var nRoundsP = 57;
|
||||
// var t = 6;
|
||||
|
||||
template Poseidon(nInputs, t, nRoundsF, nRoundsP) {
|
||||
|
||||
var C = [
|
||||
14397397413755236225575615486459253198602422701513067526754101844196324375522,
|
||||
10405129301473404666785234951972711717481302463898292859783056520670200613128,
|
||||
5179144822360023508491245509308555580251733042407187134628755730783052214509,
|
||||
9132640374240188374542843306219594180154739721841249568925550236430986592615,
|
||||
20360807315276763881209958738450444293273549928693737723235350358403012458514,
|
||||
17933600965499023212689924809448543050840131883187652471064418452962948061619,
|
||||
3636213416533737411392076250708419981662897009810345015164671602334517041153,
|
||||
2008540005368330234524962342006691994500273283000229509835662097352946198608,
|
||||
16018407964853379535338740313053768402596521780991140819786560130595652651567,
|
||||
20653139667070586705378398435856186172195806027708437373983929336015162186471,
|
||||
17887713874711369695406927657694993484804203950786446055999405564652412116765,
|
||||
4852706232225925756777361208698488277369799648067343227630786518486608711772,
|
||||
8969172011633935669771678412400911310465619639756845342775631896478908389850,
|
||||
20570199545627577691240476121888846460936245025392381957866134167601058684375,
|
||||
16442329894745639881165035015179028112772410105963688121820543219662832524136,
|
||||
20060625627350485876280451423010593928172611031611836167979515653463693899374,
|
||||
16637282689940520290130302519163090147511023430395200895953984829546679599107,
|
||||
15599196921909732993082127725908821049411366914683565306060493533569088698214,
|
||||
16894591341213863947423904025624185991098788054337051624251730868231322135455,
|
||||
1197934381747032348421303489683932612752526046745577259575778515005162320212,
|
||||
6172482022646932735745595886795230725225293469762393889050804649558459236626,
|
||||
21004037394166516054140386756510609698837211370585899203851827276330669555417,
|
||||
15262034989144652068456967541137853724140836132717012646544737680069032573006,
|
||||
15017690682054366744270630371095785995296470601172793770224691982518041139766,
|
||||
15159744167842240513848638419303545693472533086570469712794583342699782519832,
|
||||
11178069035565459212220861899558526502477231302924961773582350246646450941231,
|
||||
21154888769130549957415912997229564077486639529994598560737238811887296922114,
|
||||
20162517328110570500010831422938033120419484532231241180224283481905744633719,
|
||||
2777362604871784250419758188173029886707024739806641263170345377816177052018,
|
||||
15732290486829619144634131656503993123618032247178179298922551820261215487562,
|
||||
6024433414579583476444635447152826813568595303270846875177844482142230009826,
|
||||
17677827682004946431939402157761289497221048154630238117709539216286149983245,
|
||||
10716307389353583413755237303156291454109852751296156900963208377067748518748,
|
||||
14925386988604173087143546225719076187055229908444910452781922028996524347508,
|
||||
8940878636401797005293482068100797531020505636124892198091491586778667442523,
|
||||
18911747154199663060505302806894425160044925686870165583944475880789706164410,
|
||||
8821532432394939099312235292271438180996556457308429936910969094255825456935,
|
||||
20632576502437623790366878538516326728436616723089049415538037018093616927643,
|
||||
71447649211767888770311304010816315780740050029903404046389165015534756512,
|
||||
2781996465394730190470582631099299305677291329609718650018200531245670229393,
|
||||
12441376330954323535872906380510501637773629931719508864016287320488688345525,
|
||||
2558302139544901035700544058046419714227464650146159803703499681139469546006,
|
||||
10087036781939179132584550273563255199577525914374285705149349445480649057058,
|
||||
4267692623754666261749551533667592242661271409704769363166965280715887854739,
|
||||
4945579503584457514844595640661884835097077318604083061152997449742124905548,
|
||||
17742335354489274412669987990603079185096280484072783973732137326144230832311,
|
||||
6266270088302506215402996795500854910256503071464802875821837403486057988208,
|
||||
2716062168542520412498610856550519519760063668165561277991771577403400784706,
|
||||
19118392018538203167410421493487769944462015419023083813301166096764262134232,
|
||||
9386595745626044000666050847309903206827901310677406022353307960932745699524,
|
||||
9121640807890366356465620448383131419933298563527245687958865317869840082266,
|
||||
3078975275808111706229899605611544294904276390490742680006005661017864583210,
|
||||
7157404299437167354719786626667769956233708887934477609633504801472827442743,
|
||||
14056248655941725362944552761799461694550787028230120190862133165195793034373,
|
||||
14124396743304355958915937804966111851843703158171757752158388556919187839849,
|
||||
11851254356749068692552943732920045260402277343008629727465773766468466181076,
|
||||
9799099446406796696742256539758943483211846559715874347178722060519817626047,
|
||||
10156146186214948683880719664738535455146137901666656566575307300522957959544,
|
||||
19908645952733301583346063785055921934459499091029406575311417879963332475861,
|
||||
11766105336238068471342414351862472329437473380853789942065610694000443387471,
|
||||
11002137593249972174092192767251572171769044073555430468487809799220351297047,
|
||||
284136377911685911941431040940403846843630064858778505937392780738953624163,
|
||||
19448733709802908339787967270452055364068697565906862913410983275341804035680,
|
||||
14423660424692802524250720264041003098290275890428483723270346403986712981505,
|
||||
10635360132728137321700090133109897687122647659471659996419791842933639708516
|
||||
];
|
||||
|
||||
var M = [
|
||||
[
|
||||
19167410339349846567561662441069598364702008768579734801591448511131028229281,
|
||||
14183033936038168803360723133013092560869148726790180682363054735190196956789,
|
||||
9067734253445064890734144122526450279189023719890032859456830213166173619761,
|
||||
16378664841697311562845443097199265623838619398287411428110917414833007677155,
|
||||
12968540216479938138647596899147650021419273189336843725176422194136033835172,
|
||||
3636162562566338420490575570584278737093584021456168183289112789616069756675
|
||||
],[
|
||||
17034139127218860091985397764514160131253018178110701196935786874261236172431,
|
||||
2799255644797227968811798608332314218966179365168250111693473252876996230317,
|
||||
2482058150180648511543788012634934806465808146786082148795902594096349483974,
|
||||
16563522740626180338295201738437974404892092704059676533096069531044355099628,
|
||||
10468644849657689537028565510142839489302836569811003546969773105463051947124,
|
||||
3328913364598498171733622353010907641674136720305714432354138807013088636408
|
||||
],[
|
||||
18985203040268814769637347880759846911264240088034262814847924884273017355969,
|
||||
8652975463545710606098548415650457376967119951977109072274595329619335974180,
|
||||
970943815872417895015626519859542525373809485973005165410533315057253476903,
|
||||
19406667490568134101658669326517700199745817783746545889094238643063688871948,
|
||||
17049854690034965250221386317058877242629221002521630573756355118745574274967,
|
||||
4964394613021008685803675656098849539153699842663541444414978877928878266244
|
||||
],[
|
||||
19025623051770008118343718096455821045904242602531062247152770448380880817517,
|
||||
9077319817220936628089890431129759976815127354480867310384708941479362824016,
|
||||
4770370314098695913091200576539533727214143013236894216582648993741910829490,
|
||||
4298564056297802123194408918029088169104276109138370115401819933600955259473,
|
||||
6905514380186323693285869145872115273350947784558995755916362330070690839131,
|
||||
4783343257810358393326889022942241108539824540285247795235499223017138301952
|
||||
],[
|
||||
16205238342129310687768799056463408647672389183328001070715567975181364448609,
|
||||
8303849270045876854140023508764676765932043944545416856530551331270859502246,
|
||||
20218246699596954048529384569730026273241102596326201163062133863539137060414,
|
||||
1712845821388089905746651754894206522004527237615042226559791118162382909269,
|
||||
13001155522144542028910638547179410124467185319212645031214919884423841839406,
|
||||
16037892369576300958623292723740289861626299352695838577330319504984091062115
|
||||
],[
|
||||
15162889384227198851506890526431746552868519326873025085114621698588781611738,
|
||||
13272957914179340594010910867091459756043436017766464331915862093201960540910,
|
||||
9416416589114508529880440146952102328470363729880726115521103179442988482948,
|
||||
8035240799672199706102747147502951589635001418759394863664434079699838251138,
|
||||
21642389080762222565487157652540372010968704000567605990102641816691459811717,
|
||||
20261355950827657195644012399234591122288573679402601053407151083849785332516
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
signal input inputs[nInputs];
|
||||
signal output out;
|
||||
|
||||
component ark[nRoundsF + nRoundsP];
|
||||
component sigmaF[nRoundsF][t];
|
||||
component sigmaP[nRoundsP];
|
||||
component mix[nRoundsF + nRoundsP];
|
||||
|
||||
var k;
|
||||
|
||||
for (var i=0; i<(nRoundsF + nRoundsP); i++) {
|
||||
ark[i] = Ark(t, C[i]);
|
||||
mix[i] = Mix(t, M);
|
||||
|
||||
for (var j=0; j<t; j++) {
|
||||
if (i==0) {
|
||||
if (j<nInputs) {
|
||||
ark[i].in[j] <== inputs[j];
|
||||
} else {
|
||||
ark[i].in[j] <== 0;
|
||||
}
|
||||
} else {
|
||||
ark[i].in[j] <== mix[i-1].out[j];
|
||||
}
|
||||
}
|
||||
|
||||
if ((i<(nRoundsF/2)) || (i>= (nRoundsP + nRoundsF/2))) {
|
||||
k= i<nRoundsF/2 ? i : (i-nRoundsP);
|
||||
for (var j=0; j<t; j++) {
|
||||
sigmaF[k][j] = Sigma();
|
||||
sigmaF[k][j].in <== ark[i].out[j];
|
||||
mix[i].in[j] <== sigmaF[k][j].out;
|
||||
}
|
||||
} else {
|
||||
k= i-nRoundsF/2;
|
||||
sigmaP[k] = Sigma();
|
||||
sigmaP[k].in <== ark[i].out[0];
|
||||
mix[i].in[0] <== sigmaP[k].out;
|
||||
for (var j=1; j<t; j++) {
|
||||
mix[i].in[j] <== ark[i].out[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out <== mix[nRoundsF + nRoundsP -1].out[0];
|
||||
}
|
46
@tornado/circomlib/circuits/sha256/ch.circom
Normal file
46
@tornado/circomlib/circuits/sha256/ch.circom
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Ch
|
||||
|
||||
000 0
|
||||
001 1
|
||||
010 0
|
||||
011 1
|
||||
100 0
|
||||
101 0
|
||||
110 1
|
||||
111 1
|
||||
|
||||
out = a&b ^ (!a)&c =>
|
||||
|
||||
out = a*(b-c) + c
|
||||
|
||||
*/
|
||||
|
||||
template Ch(n) {
|
||||
signal input a[n];
|
||||
signal input b[n];
|
||||
signal input c[n];
|
||||
signal output out[n];
|
||||
|
||||
for (var k=0; k<n; k++) {
|
||||
out[k] <== a[k] * (b[k]-c[k]) + c[k];
|
||||
}
|
||||
}
|
52
@tornado/circomlib/circuits/sha256/constants.circom
Normal file
52
@tornado/circomlib/circuits/sha256/constants.circom
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
template H(x) {
|
||||
signal output out[32];
|
||||
var c = [0x6a09e667,
|
||||
0xbb67ae85,
|
||||
0x3c6ef372,
|
||||
0xa54ff53a,
|
||||
0x510e527f,
|
||||
0x9b05688c,
|
||||
0x1f83d9ab,
|
||||
0x5be0cd19];
|
||||
|
||||
for (var i=0; i<32; i++) {
|
||||
out[i] <== (c[x] >> i) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
template K(x) {
|
||||
signal output out[32];
|
||||
var c = [
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
];
|
||||
|
||||
for (var i=0; i<32; i++) {
|
||||
out[i] <== (c[x] >> i) & 1;
|
||||
}
|
||||
}
|
34
@tornado/circomlib/circuits/sha256/main.circom
Normal file
34
@tornado/circomlib/circuits/sha256/main.circom
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "sha256_2.jaz";
|
||||
|
||||
template Main() {
|
||||
signal private input a;
|
||||
signal private input b;
|
||||
signal output out;
|
||||
|
||||
component sha256_2 = SHA256_2();
|
||||
|
||||
sha256_2.a <== a;
|
||||
sha256_2.b <== a;
|
||||
out <== sha256_2.out;
|
||||
}
|
||||
|
||||
component main = Main();
|
44
@tornado/circomlib/circuits/sha256/maj.circom
Normal file
44
@tornado/circomlib/circuits/sha256/maj.circom
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Maj function for sha256
|
||||
|
||||
out = a&b ^ a&c ^ b&c =>
|
||||
|
||||
out = a*b + a*c + b*c - 2*a*b*c =>
|
||||
|
||||
out = a*( b + c - 2*b*c ) + b*c =>
|
||||
|
||||
mid = b*c
|
||||
out = a*( b + c - 2*mid ) + mid
|
||||
|
||||
*/
|
||||
|
||||
template Maj(n) {
|
||||
signal input a[n];
|
||||
signal input b[n];
|
||||
signal input c[n];
|
||||
signal output out[n];
|
||||
signal mid[n];
|
||||
|
||||
for (var k=0; k<n; k++) {
|
||||
mid[k] <== b[k]*c[k];
|
||||
out[k] <== a[k] * (b[k]+c[k]-2*mid[k]) + mid[k];
|
||||
}
|
||||
}
|
27
@tornado/circomlib/circuits/sha256/rotate.circom
Normal file
27
@tornado/circomlib/circuits/sha256/rotate.circom
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
template RotR(n, r) {
|
||||
signal input in[n];
|
||||
signal output out[n];
|
||||
|
||||
for (var i=0; i<n; i++) {
|
||||
out[i] <== in[ (i+r)%n ];
|
||||
}
|
||||
}
|
81
@tornado/circomlib/circuits/sha256/sha256.circom
Normal file
81
@tornado/circomlib/circuits/sha256/sha256.circom
Normal file
@ -0,0 +1,81 @@
|
||||
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
}
|
90
@tornado/circomlib/circuits/sha256/sha256_2.circom
Normal file
90
@tornado/circomlib/circuits/sha256/sha256_2.circom
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "constants.circom";
|
||||
include "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;
|
||||
}
|
156
@tornado/circomlib/circuits/sha256/sha256compression.circom
Normal file
156
@tornado/circomlib/circuits/sha256/sha256compression.circom
Normal file
@ -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/>.
|
||||
*/
|
||||
|
||||
include "constants.circom";
|
||||
include "t1.circom";
|
||||
include "t2.circom";
|
||||
include "../binsum.circom";
|
||||
include "sigmaplus.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 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];
|
||||
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];
|
||||
}
|
||||
}
|
32
@tornado/circomlib/circuits/sha256/shift.circom
Normal file
32
@tornado/circomlib/circuits/sha256/shift.circom
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
template ShR(n, r) {
|
||||
signal input in[n];
|
||||
signal output out[n];
|
||||
|
||||
for (var i=0; i<n; i++) {
|
||||
if (i+r >= n) {
|
||||
out[i] <== 0;
|
||||
} else {
|
||||
out[i] <== in[ i+r ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
68
@tornado/circomlib/circuits/sha256/sigma.circom
Normal file
68
@tornado/circomlib/circuits/sha256/sigma.circom
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "xor3.circom";
|
||||
include "rotate.circom";
|
||||
include "shift.circom";
|
||||
|
||||
template SmallSigma(ra, rb, rc) {
|
||||
signal input in[32];
|
||||
signal output out[32];
|
||||
|
||||
component xor3 = Xor3(32);
|
||||
|
||||
component rota = RotR(32, ra);
|
||||
component rotb = RotR(32, rb);
|
||||
component shrc = ShR(32, rc);
|
||||
|
||||
for (var k=0; k<32; k++) {
|
||||
rota.in[k] <== in[k];
|
||||
rotb.in[k] <== in[k];
|
||||
shrc.in[k] <== in[k];
|
||||
|
||||
xor3.a[k] <== rota.out[k];
|
||||
xor3.b[k] <== rotb.out[k];
|
||||
xor3.c[k] <== shrc.out[k];
|
||||
|
||||
out[k] <== xor3.out[k];
|
||||
}
|
||||
}
|
||||
|
||||
template BigSigma(ra, rb, rc) {
|
||||
signal input in[32];
|
||||
signal output out[32];
|
||||
|
||||
component xor3 = Xor3(32);
|
||||
|
||||
component rota = RotR(32, ra);
|
||||
component rotb = RotR(32, rb);
|
||||
component rotc = RotR(32, rc);
|
||||
|
||||
for (var k=0; k<32; k++) {
|
||||
rota.in[k] <== in[k];
|
||||
rotb.in[k] <== in[k];
|
||||
rotc.in[k] <== in[k];
|
||||
|
||||
xor3.a[k] <== rota.out[k];
|
||||
xor3.b[k] <== rotb.out[k];
|
||||
xor3.c[k] <== rotc.out[k];
|
||||
|
||||
out[k] <== xor3.out[k];
|
||||
}
|
||||
}
|
45
@tornado/circomlib/circuits/sha256/sigmaplus.circom
Normal file
45
@tornado/circomlib/circuits/sha256/sigmaplus.circom
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "../binsum.circom"
|
||||
include "sigma.circom"
|
||||
|
||||
template SigmaPlus() {
|
||||
signal input in2[32];
|
||||
signal input in7[32];
|
||||
signal input in15[32];
|
||||
signal input in16[32];
|
||||
signal output out[32];
|
||||
|
||||
component sum = BinSum(32, 4);
|
||||
component sigma1 = SmallSigma(17,19,10);
|
||||
component sigma0 = SmallSigma(7, 18, 3);
|
||||
|
||||
for (var k=0; k<32; k++) {
|
||||
sigma1.in[k] <== in2[k];
|
||||
sigma0.in[k] <== in15[k];
|
||||
|
||||
sum.in[0][k] <== sigma1.out[k];
|
||||
sum.in[1][k] <== in7[k];
|
||||
sum.in[2][k] <== sigma0.out[k];
|
||||
sum.in[3][k] <== in16[k];
|
||||
|
||||
out[k] <== sum.out[k];
|
||||
}
|
||||
}
|
52
@tornado/circomlib/circuits/sha256/t1.circom
Normal file
52
@tornado/circomlib/circuits/sha256/t1.circom
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "../binsum.circom";
|
||||
include "sigma.circom";
|
||||
include "ch.circom";
|
||||
|
||||
template T1() {
|
||||
signal input h[32];
|
||||
signal input e[32];
|
||||
signal input f[32];
|
||||
signal input g[32];
|
||||
signal input k[32];
|
||||
signal input w[32];
|
||||
signal output out[32];
|
||||
|
||||
component sum = BinSum(32, 5);
|
||||
component ch = Ch(32);
|
||||
|
||||
component bigsigma1 = BigSigma(6, 11, 25);
|
||||
|
||||
for (var ki=0; ki<32; ki++) {
|
||||
bigsigma1.in[ki] <== e[ki];
|
||||
ch.a[ki] <== e[ki];
|
||||
ch.b[ki] <== f[ki];
|
||||
ch.c[ki] <== g[ki]
|
||||
|
||||
sum.in[0][ki] <== h[ki];
|
||||
sum.in[1][ki] <== bigsigma1.out[ki];
|
||||
sum.in[2][ki] <== ch.out[ki];
|
||||
sum.in[3][ki] <== k[ki];
|
||||
sum.in[4][ki] <== w[ki];
|
||||
|
||||
out[ki] <== sum.out[ki];
|
||||
}
|
||||
}
|
47
@tornado/circomlib/circuits/sha256/t2.circom
Normal file
47
@tornado/circomlib/circuits/sha256/t2.circom
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "../binsum.circom";
|
||||
include "sigma.circom";
|
||||
include "maj.circom"
|
||||
|
||||
template T2() {
|
||||
signal input a[32];
|
||||
signal input b[32];
|
||||
signal input c[32];
|
||||
signal output out[32];
|
||||
|
||||
component sum = BinSum(32, 2);
|
||||
|
||||
component bigsigma0 = BigSigma(2, 13, 22);
|
||||
component maj = Maj(32);
|
||||
|
||||
for (var k=0; k<32; k++) {
|
||||
|
||||
bigsigma0.in[k] <== a[k];
|
||||
maj.a[k] <== a[k];
|
||||
maj.b[k] <== b[k];
|
||||
maj.c[k] <== c[k];
|
||||
|
||||
sum.in[0][k] <== bigsigma0.out[k];
|
||||
sum.in[1][k] <== maj.out[k];
|
||||
|
||||
out[k] <== sum.out[k];
|
||||
}
|
||||
}
|
44
@tornado/circomlib/circuits/sha256/xor3.circom
Normal file
44
@tornado/circomlib/circuits/sha256/xor3.circom
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Xor3 function for sha256
|
||||
|
||||
out = a ^ b ^ c =>
|
||||
|
||||
out = a+b+c - 2*a*b - 2*a*c - 2*b*c + 4*a*b*c =>
|
||||
|
||||
out = a*( 1 - 2*b - 2*c + 4*b*c ) + b + c - 2*b*c =>
|
||||
|
||||
mid = b*c
|
||||
out = a*( 1 - 2*b -2*c + 4*mid ) + b + c - 2 * mid
|
||||
|
||||
*/
|
||||
|
||||
template Xor3(n) {
|
||||
signal input a[n];
|
||||
signal input b[n];
|
||||
signal input c[n];
|
||||
signal output out[n];
|
||||
signal mid[n];
|
||||
|
||||
for (var k=0; k<n; k++) {
|
||||
mid[k] <== b[k]*c[k];
|
||||
out[k] <== a[k] * (1 -2*b[k] -2*c[k] +4*mid[k]) + b[k] + c[k] -2*mid[k];
|
||||
}
|
||||
}
|
35
@tornado/circomlib/circuits/sign.circom
Normal file
35
@tornado/circomlib/circuits/sign.circom
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "compconstant.circom";
|
||||
|
||||
template Sign() {
|
||||
signal input in[254];
|
||||
signal output sign;
|
||||
|
||||
component comp = CompConstant(10944121435919637611123202872628637544274182200208017171849102093287904247808);
|
||||
|
||||
var i;
|
||||
|
||||
for (i=0; i<254; i++) {
|
||||
comp.in[i] <== in[i];
|
||||
}
|
||||
|
||||
sign <== comp.out;
|
||||
}
|
57
@tornado/circomlib/circuits/smt/smthash_mimc.circom
Normal file
57
@tornado/circomlib/circuits/smt/smthash_mimc.circom
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "../mimc.circom";
|
||||
|
||||
|
||||
/*
|
||||
Hash1 = H(1 | key | value)
|
||||
*/
|
||||
|
||||
template SMTHash1() {
|
||||
signal input key;
|
||||
signal input value;
|
||||
signal output out;
|
||||
|
||||
component h = MultiMiMC7(2, 91); // Constant
|
||||
h.in[0] <== key;
|
||||
h.in[1] <== value;
|
||||
h.k <== 1;
|
||||
|
||||
out <== h.out;
|
||||
}
|
||||
|
||||
/*
|
||||
This component is used to create the 2 nodes.
|
||||
|
||||
Hash2 = H(Hl | Hr)
|
||||
*/
|
||||
|
||||
template SMTHash2() {
|
||||
signal input L;
|
||||
signal input R;
|
||||
signal output out;
|
||||
|
||||
component h = MultiMiMC7(2, 91); // Constant
|
||||
h.in[0] <== L;
|
||||
h.in[1] <== R;
|
||||
h.k <== 0;
|
||||
|
||||
out <== h.out;
|
||||
}
|
56
@tornado/circomlib/circuits/smt/smthash_poseidon.circom
Normal file
56
@tornado/circomlib/circuits/smt/smthash_poseidon.circom
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
include "../poseidon.circom";
|
||||
|
||||
|
||||
/*
|
||||
Hash1 = H(1 | key | value)
|
||||
*/
|
||||
|
||||
template SMTHash1() {
|
||||
signal input key;
|
||||
signal input value;
|
||||
signal output out;
|
||||
|
||||
component h = Poseidon(3, 6, 8, 57); // Constant
|
||||
h.inputs[0] <== key;
|
||||
h.inputs[1] <== value;
|
||||
h.inputs[2] <== 1;
|
||||
|
||||
out <== h.out;
|
||||
}
|
||||
|
||||
/*
|
||||
This component is used to create the 2 nodes.
|
||||
|
||||
Hash2 = H(Hl | Hr)
|
||||
*/
|
||||
|
||||
template SMTHash2() {
|
||||
signal input L;
|
||||
signal input R;
|
||||
signal output out;
|
||||
|
||||
component h = Poseidon(2, 6, 8, 57); // Constant
|
||||
h.inputs[0] <== L;
|
||||
h.inputs[1] <== R;
|
||||
|
||||
out <== h.out;
|
||||
}
|
100
@tornado/circomlib/circuits/smt/smtlevins.circom
Normal file
100
@tornado/circomlib/circuits/smt/smtlevins.circom
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
This component finds the level where the oldInsert is done.
|
||||
The rules are:
|
||||
|
||||
levIns[i] == 1 if its level and all the child levels have a sibling of 0 and
|
||||
the parent level has a sibling != 0. Considere that the root level always has
|
||||
a parent with a sibling != 0.
|
||||
|
||||
|
||||
┌──────────────┐
|
||||
│ │
|
||||
│ │───▶ levIns[0] <== (1-done[i])
|
||||
│ │
|
||||
└──────────────┘
|
||||
▲
|
||||
│
|
||||
│
|
||||
done[0]
|
||||
|
||||
|
||||
|
||||
done[i-1] <== levIns[i] + done[i]
|
||||
▲
|
||||
│
|
||||
│
|
||||
┌───────────┐ ┌──────────────┐
|
||||
│ │ │ │
|
||||
sibling[i-1]───▶│IsZero[i-1]│─▶│ │───▶ levIns[i] <== (1-done[i])*(1-isZero[i-1].out)
|
||||
│ │ │ │
|
||||
└───────────┘ └──────────────┘
|
||||
▲
|
||||
│
|
||||
│
|
||||
done[i]
|
||||
|
||||
|
||||
|
||||
done[n-2] <== levIns[n-1]
|
||||
▲
|
||||
│
|
||||
│
|
||||
┌───────────┐ ┌──────────────┐
|
||||
│ │ │ │
|
||||
sibling[n-2]───▶│IsZero[n-2]│─▶│ │────▶ levIns[n-1] <== (1-isZero[n-2].out)
|
||||
│ │ │ │
|
||||
└───────────┘ └──────────────┘
|
||||
|
||||
┌───────────┐
|
||||
│ │
|
||||
sibling[n-1]───▶│IsZero[n-1]│────▶ === 0
|
||||
│ │
|
||||
└───────────┘
|
||||
|
||||
*/
|
||||
|
||||
template SMTLevIns(nLevels) {
|
||||
signal input enabled;
|
||||
signal input siblings[nLevels];
|
||||
signal output levIns[nLevels];
|
||||
signal done[nLevels-1]; // Indicates if the insLevel has aready been detected.
|
||||
|
||||
component isZero[nLevels];
|
||||
|
||||
for (var i=0; i<nLevels; i++) {
|
||||
isZero[i] = IsZero();
|
||||
isZero[i].in <== siblings[i];
|
||||
}
|
||||
|
||||
// The last level must always have a sibling of 0. If not, then it cannot be inserted.
|
||||
(isZero[nLevels-1].out - 1) * enabled === 0;
|
||||
|
||||
levIns[nLevels-1] <== (1-isZero[nLevels-2].out);
|
||||
done[nLevels-2] <== levIns[nLevels-1];
|
||||
for (var i=nLevels-2; i>0; i--) {
|
||||
levIns[i] <== (1-done[i])*(1-isZero[i-1].out)
|
||||
done[i-1] <== levIns[i] + done[i];
|
||||
}
|
||||
|
||||
levIns[0] <== (1-done[0]);
|
||||
}
|
258
@tornado/circomlib/circuits/smt/smtprocessor.circom
Normal file
258
@tornado/circomlib/circuits/smt/smtprocessor.circom
Normal file
@ -0,0 +1,258 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***************************************************************************************************
|
||||
|
||||
SMTProcessor: Sparse Merkle Tree processor is a component to verify an insert/update/delete elements
|
||||
into the Sparse Merkle tree.
|
||||
|
||||
|
||||
Insert to an empty leaf
|
||||
=======================
|
||||
|
||||
STATE OLD STATE NEW STATE
|
||||
===== ========= =========
|
||||
|
||||
oldRoot newRoot
|
||||
▲ ▲
|
||||
│ │
|
||||
┌───────┐ ┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓
|
||||
top │Sibling├────▶┃ Hash ┃◀─┐ │Sibling├────▶┃ Hash ┃◀─┐
|
||||
└───────┘ ┗━━━━━━━┛ │ └───────┘ ┗━━━━━━━┛ │
|
||||
│ │
|
||||
│ │
|
||||
┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓ ┌───────┐
|
||||
top ┌─────▶┃ Hash ┃◀──┤Sibling│ ┌─────▶┃ Hash ┃◀──┤Sibling│
|
||||
│ ┗━━━━━━━┛ └───────┘ │ ┗━━━━━━━┛ └───────┘
|
||||
│ │
|
||||
│ │
|
||||
┌───────┐ ┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓
|
||||
top │Sibling├──▶┃ Hash ┃◀─────┐ │Sibling├──▶┃ Hash ┃◀─────┐
|
||||
└───────┘ ┗━━━━━━━┛ │ └───────┘ ┗━━━━━━━┛ │
|
||||
│ │
|
||||
│ │
|
||||
┌────┴────┐ ┌────┴────┐
|
||||
old0 │ 0 │ │New1Leaf │
|
||||
└─────────┘ └─────────┘
|
||||
|
||||
|
||||
┏━━━━━━━┓ ┏━━━━━━━┓
|
||||
na ┃ Hash ┃ ┃ Hash ┃
|
||||
┗━━━━━━━┛ ┗━━━━━━━┛
|
||||
|
||||
|
||||
┏━━━━━━━┓ ┏━━━━━━━┓
|
||||
na ┃ Hash ┃ ┃ Hash ┃
|
||||
┗━━━━━━━┛ ┗━━━━━━━┛
|
||||
|
||||
|
||||
|
||||
Insert to a used leaf.
|
||||
=====================
|
||||
|
||||
STATE OLD STATE NEW STATE
|
||||
===== ========= =========
|
||||
|
||||
|
||||
oldRoot newRoot
|
||||
▲ ▲
|
||||
│ │
|
||||
┌───────┐ ┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓
|
||||
top │Sibling├────▶┃ Hash ┃◀─┐ │Sibling├────▶┃ Hash ┃◀─┐
|
||||
└───────┘ ┗━━━━━━━┛ │ └───────┘ ┗━━━━━━━┛ │
|
||||
│ │
|
||||
│ │
|
||||
┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓ ┌───────┐
|
||||
top ┌─────▶┃ Hash ┃◀──┤Sibling│ ┌─────▶┃ Hash ┃◀──┤Sibling│
|
||||
│ ┗━━━━━━━┛ └───────┘ │ ┗━━━━━━━┛ └───────┘
|
||||
│ │
|
||||
│ │
|
||||
┌───────┐ ┏━━━┻━━━┓ ┌───────┐ ┏━━━┻━━━┓
|
||||
top │Sibling├──▶┃ Hash ┃◀─────┐ │Sibling├──▶┃ Hash ┃◀─────┐
|
||||
└───────┘ ┗━━━━━━━┛ │ └───────┘ ┗━━━━━━━┛ │
|
||||
│ │
|
||||
│ │
|
||||
┌────┴────┐ ┏━━━┻━━━┓ ┌───────┐
|
||||
bot │Old1Leaf │ ┌─────▶┃ Hash ┃◀──┼─ 0 │
|
||||
└─────────┘ │ ┗━━━━━━━┛ └───────┘
|
||||
│
|
||||
│
|
||||
┏━━━━━━━┓ ┌───────┐ ┏━━━┻━━━┓
|
||||
bot ┃ Hash ┃ │ 0 ─┼──▶┃ Hash ┃◀─────┐
|
||||
┗━━━━━━━┛ └───────┘ ┗━━━━━━━┛ │
|
||||
│
|
||||
│
|
||||
┏━━━━━━━┓ ┏━━━┻━━━┓ ┌───────┐
|
||||
bot ┃ Hash ┃ ┌─────▶┃ Hash ┃◀──│ 0 │
|
||||
┗━━━━━━━┛ │ ┗━━━━━━━┛ └───────┘
|
||||
│
|
||||
│
|
||||
┏━━━━━━━┓ ┌─────────┐ ┏━━━┻━━━┓ ┌─────────┐
|
||||
new1 ┃ Hash ┃ │Old1Leaf ├──▶┃ Hash ┃◀──│New1Leaf │
|
||||
┗━━━━━━━┛ └─────────┘ ┗━━━━━━━┛ └─────────┘
|
||||
|
||||
|
||||
┏━━━━━━━┓ ┏━━━━━━━┓
|
||||
na ┃ Hash ┃ ┃ Hash ┃
|
||||
┗━━━━━━━┛ ┗━━━━━━━┛
|
||||
|
||||
|
||||
┏━━━━━━━┓ ┏━━━━━━━┓
|
||||
na ┃ Hash ┃ ┃ Hash ┃
|
||||
┗━━━━━━━┛ ┗━━━━━━━┛
|
||||
|
||||
|
||||
Fnction
|
||||
fnc[0] fnc[1]
|
||||
0 0 NOP
|
||||
0 1 UPDATE
|
||||
1 0 INSERT
|
||||
1 1 DELETE
|
||||
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
include "../gates.circom";
|
||||
include "../bitify.circom";
|
||||
include "../comparators.circom";
|
||||
include "../switcher.circom";
|
||||
include "smtlevins.circom";
|
||||
include "smtprocessorlevel.circom";
|
||||
include "smtprocessorsm.circom";
|
||||
include "smthash_poseidon.circom";
|
||||
|
||||
template SMTProcessor(nLevels) {
|
||||
signal input oldRoot;
|
||||
signal output newRoot;
|
||||
signal input siblings[nLevels];
|
||||
signal input oldKey;
|
||||
signal input oldValue;
|
||||
signal input isOld0;
|
||||
signal input newKey;
|
||||
signal input newValue;
|
||||
signal input fnc[2];
|
||||
|
||||
signal enabled;
|
||||
|
||||
enabled <== fnc[0] + fnc[1] - fnc[0]*fnc[1]
|
||||
|
||||
component hash1Old = SMTHash1();
|
||||
hash1Old.key <== oldKey;
|
||||
hash1Old.value <== oldValue;
|
||||
|
||||
component hash1New = SMTHash1();
|
||||
hash1New.key <== newKey;
|
||||
hash1New.value <== newValue;
|
||||
|
||||
component n2bOld = Num2Bits_strict();
|
||||
component n2bNew = Num2Bits_strict();
|
||||
|
||||
n2bOld.in <== oldKey;
|
||||
n2bNew.in <== newKey;
|
||||
|
||||
component smtLevIns = SMTLevIns(nLevels);
|
||||
for (var i=0; i<nLevels; i++) smtLevIns.siblings[i] <== siblings[i];
|
||||
smtLevIns.enabled <== enabled;
|
||||
|
||||
component xors[nLevels];
|
||||
for (var i=0; i<nLevels; i++) {
|
||||
xors[i] = XOR();
|
||||
xors[i].a <== n2bOld.out[i];
|
||||
xors[i].b <== n2bNew.out[i];
|
||||
}
|
||||
|
||||
component sm[nLevels];
|
||||
for (var i=0; i<nLevels; i++) {
|
||||
sm[i] = SMTProcessorSM();
|
||||
if (i==0) {
|
||||
sm[i].prev_top <== enabled;
|
||||
sm[i].prev_old0 <== 0;
|
||||
sm[i].prev_bot <== 0;
|
||||
sm[i].prev_new1 <== 0;
|
||||
sm[i].prev_na <== 1-enabled;
|
||||
sm[i].prev_upd <== 0;
|
||||
} else {
|
||||
sm[i].prev_top <== sm[i-1].st_top;
|
||||
sm[i].prev_old0 <== sm[i-1].st_old0;
|
||||
sm[i].prev_bot <== sm[i-1].st_bot;
|
||||
sm[i].prev_new1 <== sm[i-1].st_new1;
|
||||
sm[i].prev_na <== sm[i-1].st_na;
|
||||
sm[i].prev_upd <== sm[i-1].st_upd;
|
||||
}
|
||||
sm[i].is0 <== isOld0;
|
||||
sm[i].xor <== xors[i].out;
|
||||
sm[i].fnc[0] <== fnc[0];
|
||||
sm[i].fnc[1] <== fnc[1];
|
||||
sm[i].levIns <== smtLevIns.levIns[i];
|
||||
}
|
||||
sm[nLevels-1].st_na + sm[nLevels-1].st_new1 + sm[nLevels-1].st_old0 +sm[nLevels-1].st_upd === 1;
|
||||
|
||||
component levels[nLevels];
|
||||
for (var i=nLevels-1; i != -1; i--) {
|
||||
levels[i] = SMTProcessorLevel();
|
||||
|
||||
levels[i].st_top <== sm[i].st_top;
|
||||
levels[i].st_old0 <== sm[i].st_old0;
|
||||
levels[i].st_bot <== sm[i].st_bot;
|
||||
levels[i].st_new1 <== sm[i].st_new1;
|
||||
levels[i].st_na <== sm[i].st_na;
|
||||
levels[i].st_upd <== sm[i].st_upd;
|
||||
|
||||
levels[i].sibling <== siblings[i];
|
||||
levels[i].old1leaf <== hash1Old.out;
|
||||
levels[i].new1leaf <== hash1New.out;
|
||||
|
||||
levels[i].newlrbit <== n2bNew.out[i];
|
||||
if (i==nLevels-1) {
|
||||
levels[i].oldChild <== 0;
|
||||
levels[i].newChild <== 0;
|
||||
} else {
|
||||
levels[i].oldChild <== levels[i+1].oldRoot;
|
||||
levels[i].newChild <== levels[i+1].newRoot;
|
||||
}
|
||||
}
|
||||
|
||||
component topSwitcher = Switcher();
|
||||
|
||||
topSwitcher.sel <== fnc[0]*fnc[1];
|
||||
topSwitcher.L <== levels[0].oldRoot;
|
||||
topSwitcher.R <== levels[0].newRoot;
|
||||
|
||||
component checkOldInput = ForceEqualIfEnabled();
|
||||
checkOldInput.enabled <== enabled;
|
||||
checkOldInput.in[0] <== oldRoot;
|
||||
checkOldInput.in[1] <== topSwitcher.outL;
|
||||
|
||||
newRoot <== enabled * (topSwitcher.outR - oldRoot) + oldRoot;
|
||||
|
||||
// topSwitcher.outL === oldRoot*enabled;
|
||||
// topSwitcher.outR === newRoot*enabled;
|
||||
|
||||
// Ckeck keys are equal if updating
|
||||
component areKeyEquals = IsEqual();
|
||||
areKeyEquals.in[0] <== oldKey;
|
||||
areKeyEquals.in[1] <== newKey;
|
||||
|
||||
component keysOk = MultiAND(3);
|
||||
keysOk.in[0] <== 1-fnc[0];
|
||||
keysOk.in[1] <== fnc[1];
|
||||
keysOk.in[2] <== 1-areKeyEquals.out;
|
||||
|
||||
keysOk.out === 0;
|
||||
}
|
94
@tornado/circomlib/circuits/smt/smtprocessorlevel.circom
Normal file
94
@tornado/circomlib/circuits/smt/smtprocessorlevel.circom
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/******
|
||||
|
||||
SMTProcessorLevel
|
||||
|
||||
This circuit has 2 hash
|
||||
|
||||
Outputs according to the state.
|
||||
|
||||
State oldRoot newRoot
|
||||
===== ======= =======
|
||||
top H'(oldChild, sibling) H'(newChild, sibling)
|
||||
old0 0 new1leaf
|
||||
bot old1leaf H'(newChild, 0)
|
||||
new1 old1leaf H'(new1leaf, old1leaf)
|
||||
na 0 0
|
||||
|
||||
upd old1leaf new1leaf
|
||||
|
||||
H' is the Hash function with the inputs shifted acordingly.
|
||||
|
||||
*****/
|
||||
|
||||
|
||||
template SMTProcessorLevel() {
|
||||
signal input st_top;
|
||||
signal input st_old0;
|
||||
signal input st_bot;
|
||||
signal input st_new1;
|
||||
signal input st_na;
|
||||
signal input st_upd;
|
||||
|
||||
signal output oldRoot;
|
||||
signal output newRoot;
|
||||
signal input sibling;
|
||||
signal input old1leaf;
|
||||
signal input new1leaf;
|
||||
signal input newlrbit;
|
||||
signal input oldChild;
|
||||
signal input newChild;
|
||||
|
||||
signal aux[4];
|
||||
|
||||
component oldProofHash = SMTHash2();
|
||||
component newProofHash = SMTHash2();
|
||||
|
||||
component oldSwitcher = Switcher();
|
||||
component newSwitcher = Switcher();
|
||||
|
||||
// Old side
|
||||
|
||||
oldSwitcher.L <== oldChild;
|
||||
oldSwitcher.R <== sibling;
|
||||
|
||||
oldSwitcher.sel <== newlrbit;
|
||||
oldProofHash.L <== oldSwitcher.outL;
|
||||
oldProofHash.R <== oldSwitcher.outR;
|
||||
|
||||
aux[0] <== old1leaf * (st_bot + st_new1 + st_upd);
|
||||
oldRoot <== aux[0] + oldProofHash.out * st_top;
|
||||
|
||||
// New side
|
||||
|
||||
aux[1] <== newChild * ( st_top + st_bot);
|
||||
newSwitcher.L <== aux[1] + new1leaf*st_new1;
|
||||
|
||||
aux[2] <== sibling*st_top;
|
||||
newSwitcher.R <== aux[2] + old1leaf*st_new1;
|
||||
|
||||
newSwitcher.sel <== newlrbit;
|
||||
newProofHash.L <== newSwitcher.outL;
|
||||
newProofHash.R <== newSwitcher.outR;
|
||||
|
||||
aux[3] <== newProofHash.out * (st_top + st_bot + st_new1);
|
||||
newRoot <== aux[3] + new1leaf * (st_old0 + st_upd);
|
||||
}
|
164
@tornado/circomlib/circuits/smt/smtprocessorsm.circom
Normal file
164
@tornado/circomlib/circuits/smt/smtprocessorsm.circom
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***************************************************************************************************
|
||||
Each level on a SMTProcessor has a state.
|
||||
|
||||
The state of the level depends on the state of te botom level and on `xor` and
|
||||
`is0` signals.
|
||||
|
||||
`isOldLev` 1 when is the level where oldLeaf is.
|
||||
|
||||
`xor` signal is 0 if the index bit at the current level is the same in the old
|
||||
and the new index, and 1 if it is different.
|
||||
|
||||
`is0` signal, is 1 if we are inserting/deleting in an empty leaf and 0 if we
|
||||
are inserting/deleting in a leaf that contains an element.
|
||||
|
||||
The states are:
|
||||
|
||||
top: While the index bits of the old and new insex in the top level is the same, whe are in the top state.
|
||||
old0: When the we reach insert level, we go to old0 state
|
||||
if `is0`=1.
|
||||
btn: Once in insert level and `is0` =0 we go to btn or new1 level if xor=1
|
||||
new1: This level is reached when xor=1. Here is where we insert/delete the hash of the
|
||||
old and the new trees with just one element.
|
||||
na: Not appliable. After processing it, we go to the na level.
|
||||
|
||||
|
||||
Fnction
|
||||
fnc[0] fnc[1]
|
||||
0 0 NOP
|
||||
0 1 UPDATE
|
||||
1 0 INSERT
|
||||
1 1 DELETE
|
||||
|
||||
|
||||
###########
|
||||
# #
|
||||
┌────────────────────────────▶# upd #─────────────────────┐
|
||||
│ ## ## │
|
||||
│ ######### │
|
||||
levIns=1 │ │
|
||||
fnc[0]=0 │ │ any
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
│ ########### │
|
||||
│ levIns=1 # # │
|
||||
levIns=0 │ is0=1 ┌────────────▶# old0 #────────┐ │ any
|
||||
┌─────┐ │ fnc[0]=1│ ## ## │ │ ┌──────┐
|
||||
│ │ │ │ ######### │ any │ │ │
|
||||
│ ▼ │ │ │ ▼ ▼ │
|
||||
│ ########### │ │ ########### │
|
||||
│ # # ────────────┘ └────────▶# #│
|
||||
└──# top # # na #
|
||||
## ## ───────────────────┐ levIns=1 ┌──▶## ##
|
||||
######### │ is0=0 │ #########
|
||||
│ │ fnc[0]=1 │
|
||||
│ │ xor=1 ########### │ any
|
||||
│ └──────────────────▶# # │
|
||||
│ # new1 #──┘
|
||||
│ ## ##
|
||||
└────────────────────────────────┐ #########
|
||||
levIns=1 │ ▲
|
||||
is0=0 │ ┌─────┘
|
||||
fnc[0]=1 │ ###########│ xor=1
|
||||
xor=0 │ # #
|
||||
▼# btn #
|
||||
## ##
|
||||
#########◀───────┐
|
||||
│ │
|
||||
│ │
|
||||
└────────────┘
|
||||
xor=0
|
||||
|
||||
***************************************************************************************************/
|
||||
|
||||
template SMTProcessorSM() {
|
||||
signal input xor;
|
||||
signal input is0;
|
||||
signal input levIns;
|
||||
signal input fnc[2];
|
||||
|
||||
signal input prev_top;
|
||||
signal input prev_old0;
|
||||
signal input prev_bot;
|
||||
signal input prev_new1;
|
||||
signal input prev_na;
|
||||
signal input prev_upd;
|
||||
|
||||
signal output st_top;
|
||||
signal output st_old0;
|
||||
signal output st_bot;
|
||||
signal output st_new1;
|
||||
signal output st_na;
|
||||
signal output st_upd;
|
||||
|
||||
signal aux1;
|
||||
signal aux2;
|
||||
|
||||
aux1 <== prev_top * levIns;
|
||||
aux2 <== aux1*fnc[0]; // prev_top * levIns * fnc[0]
|
||||
|
||||
// st_top = prev_top*(1-levIns)
|
||||
// = + prev_top
|
||||
// - prev_top * levIns = aux1
|
||||
|
||||
st_top <== prev_top - aux1;
|
||||
|
||||
// st_old0 = prev_top * levIns * is0 * fnc[0]
|
||||
// = + prev_top * levIns * is0 * fnc[0] = aux2 * is0
|
||||
|
||||
st_old0 <== aux2 * is0; // prev_top * levIns * is0 * fnc[0]
|
||||
|
||||
// st_new1 = prev_top * levIns * (1-is0)*fnc[0] * xor + prev_bot*xor =
|
||||
// = + prev_top * levIns * fnc[0] * xor = aux2 * xor
|
||||
// - prev_top * levIns * is0 * fnc[0] * xor = st_old0 * xor
|
||||
// + prev_bot * xor = prev_bot * xor
|
||||
|
||||
st_new1 <== (aux2 - st_old0 + prev_bot)*xor;
|
||||
|
||||
|
||||
// st_bot = prev_top * levIns * (1-is0)*fnc[0] * (1-xor) + prev_bot*(1-xor);
|
||||
// = + prev_top * levIns * fnc[0]
|
||||
// - prev_top * levIns * is0 * fnc[0]
|
||||
// - prev_top * levIns * fnc[0] * xor
|
||||
// + prev_top * levIns * is0 * fnc[0] * xor
|
||||
// + prev_bot
|
||||
// - prev_bot * xor
|
||||
|
||||
st_bot <== (1-xor) * (aux2 - st_old0 + prev_bot)
|
||||
|
||||
|
||||
// st_upd = prev_top * (1-fnc[0]) *levIns;
|
||||
// = + prev_top * levIns
|
||||
// - prev_top * levIns * fnc[0]
|
||||
|
||||
st_upd <== aux1 - aux2
|
||||
|
||||
// st_na = prev_new1 + prev_old0 + prev_na + prev_upd;
|
||||
// = + prev_new1
|
||||
// + prev_old0
|
||||
// + prev_na
|
||||
// + prev_upd
|
||||
|
||||
st_na <== prev_new1 + prev_old0 + prev_na + prev_upd;
|
||||
|
||||
}
|
135
@tornado/circomlib/circuits/smt/smtverifier.circom
Normal file
135
@tornado/circomlib/circuits/smt/smtverifier.circom
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
SMTVerifier is a component to verify inclusion/exclusion of an element in the tree
|
||||
|
||||
|
||||
fnc: 0 -> VERIFY INCLUSION
|
||||
1 -> VERIFY NOT INCLUSION
|
||||
|
||||
*/
|
||||
|
||||
|
||||
include "../gates.circom";
|
||||
include "../bitify.circom";
|
||||
include "../comparators.circom";
|
||||
include "../switcher.circom";
|
||||
include "smtlevins.circom";
|
||||
include "smtverifierlevel.circom";
|
||||
include "smtverifiersm.circom";
|
||||
include "smthash_poseidon.circom";
|
||||
|
||||
template SMTVerifier(nLevels) {
|
||||
signal input enabled;
|
||||
signal input root;
|
||||
signal input siblings[nLevels];
|
||||
signal input oldKey;
|
||||
signal input oldValue;
|
||||
signal input isOld0;
|
||||
signal input key;
|
||||
signal input value;
|
||||
signal input fnc;
|
||||
|
||||
component hash1Old = SMTHash1();
|
||||
hash1Old.key <== oldKey;
|
||||
hash1Old.value <== oldValue;
|
||||
|
||||
component hash1New = SMTHash1();
|
||||
hash1New.key <== key;
|
||||
hash1New.value <== value;
|
||||
|
||||
component n2bOld = Num2Bits_strict();
|
||||
component n2bNew = Num2Bits_strict();
|
||||
|
||||
n2bOld.in <== oldKey;
|
||||
n2bNew.in <== key;
|
||||
|
||||
component smtLevIns = SMTLevIns(nLevels);
|
||||
for (var i=0; i<nLevels; i++) smtLevIns.siblings[i] <== siblings[i];
|
||||
smtLevIns.enabled <== enabled;
|
||||
|
||||
component sm[nLevels];
|
||||
for (var i=0; i<nLevels; i++) {
|
||||
sm[i] = SMTVerifierSM();
|
||||
if (i==0) {
|
||||
sm[i].prev_top <== enabled;
|
||||
sm[i].prev_i0 <== 0;
|
||||
sm[i].prev_inew <== 0;
|
||||
sm[i].prev_iold <== 0;
|
||||
sm[i].prev_na <== 1-enabled;
|
||||
} else {
|
||||
sm[i].prev_top <== sm[i-1].st_top;
|
||||
sm[i].prev_i0 <== sm[i-1].st_i0;
|
||||
sm[i].prev_inew <== sm[i-1].st_inew;
|
||||
sm[i].prev_iold <== sm[i-1].st_iold;
|
||||
sm[i].prev_na <== sm[i-1].st_na;
|
||||
}
|
||||
sm[i].is0 <== isOld0;
|
||||
sm[i].fnc <== fnc;
|
||||
sm[i].levIns <== smtLevIns.levIns[i];
|
||||
}
|
||||
sm[nLevels-1].st_na + sm[nLevels-1].st_iold + sm[nLevels-1].st_inew + sm[nLevels-1].st_i0 === 1;
|
||||
|
||||
component levels[nLevels];
|
||||
for (var i=nLevels-1; i != -1; i--) {
|
||||
levels[i] = SMTVerifierLevel();
|
||||
|
||||
levels[i].st_top <== sm[i].st_top;
|
||||
levels[i].st_i0 <== sm[i].st_i0;
|
||||
levels[i].st_inew <== sm[i].st_inew;
|
||||
levels[i].st_iold <== sm[i].st_iold;
|
||||
levels[i].st_na <== sm[i].st_na;
|
||||
|
||||
levels[i].sibling <== siblings[i];
|
||||
levels[i].old1leaf <== hash1Old.out;
|
||||
levels[i].new1leaf <== hash1New.out;
|
||||
|
||||
levels[i].lrbit <== n2bNew.out[i];
|
||||
if (i==nLevels-1) {
|
||||
levels[i].child <== 0;
|
||||
} else {
|
||||
levels[i].child <== levels[i+1].root;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check that if checking for non inclussuin and isOld0==0 then key!=old
|
||||
component areKeyEquals = IsEqual();
|
||||
areKeyEquals.in[0] <== oldKey;
|
||||
areKeyEquals.in[1] <== key;
|
||||
|
||||
component keysOk = MultiAND(4);
|
||||
keysOk.in[0] <== fnc;
|
||||
keysOk.in[1] <== 1-isOld0;
|
||||
keysOk.in[2] <== areKeyEquals.out;
|
||||
keysOk.in[3] <== enabled;
|
||||
|
||||
keysOk.out === 0;
|
||||
|
||||
// Check the root
|
||||
component checkRoot = ForceEqualIfEnabled();
|
||||
checkRoot.enabled <== enabled;
|
||||
checkRoot.in[0] <== levels[0].root;
|
||||
checkRoot.in[1] <== root;
|
||||
|
||||
// levels[0].root === root;
|
||||
|
||||
}
|
71
@tornado/circomlib/circuits/smt/smtverifierlevel.circom
Normal file
71
@tornado/circomlib/circuits/smt/smtverifierlevel.circom
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/******
|
||||
|
||||
SMTVerifierLevel
|
||||
|
||||
This circuit has 1 hash
|
||||
|
||||
Outputs according to the state.
|
||||
|
||||
State root
|
||||
===== =======
|
||||
top H'(child, sibling)
|
||||
i0 0
|
||||
iold old1leaf
|
||||
inew new1leaf
|
||||
na 0
|
||||
|
||||
H' is the Hash function with the inputs shifted acordingly.
|
||||
|
||||
*****/
|
||||
|
||||
|
||||
template SMTVerifierLevel() {
|
||||
signal input st_top;
|
||||
signal input st_i0;
|
||||
signal input st_iold;
|
||||
signal input st_inew;
|
||||
signal input st_na;
|
||||
|
||||
signal output root;
|
||||
signal input sibling;
|
||||
signal input old1leaf;
|
||||
signal input new1leaf;
|
||||
signal input lrbit;
|
||||
signal input child;
|
||||
|
||||
signal aux[2];
|
||||
|
||||
component proofHash = SMTHash2();
|
||||
component switcher = Switcher();
|
||||
|
||||
switcher.L <== child;
|
||||
switcher.R <== sibling;
|
||||
|
||||
switcher.sel <== lrbit;
|
||||
proofHash.L <== switcher.outL;
|
||||
proofHash.R <== switcher.outR;
|
||||
|
||||
aux[0] <== proofHash.out * st_top;
|
||||
aux[1] <== old1leaf*st_iold;
|
||||
|
||||
root <== aux[0] + aux[1] + new1leaf*st_inew;
|
||||
}
|
105
@tornado/circomlib/circuits/smt/smtverifiersm.circom
Normal file
105
@tornado/circomlib/circuits/smt/smtverifiersm.circom
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
Each level in the SMTVerifier has a state.
|
||||
|
||||
This is the state machine.
|
||||
|
||||
The signals are
|
||||
|
||||
levIns: 1 if we are in the level where the insertion should happen
|
||||
xor: 1 if the bitKey of the old and new keys are different in this level
|
||||
is0: Input that indicates that the oldKey is 0
|
||||
fnc: 0 -> VERIFY INCLUSION
|
||||
1 -> VERIFY NOT INCLUSION
|
||||
|
||||
err state is not a state itself. It's a lack of state.
|
||||
|
||||
The end of the last level will have to be `na`
|
||||
|
||||
levIns=0 any
|
||||
┌────┐ ┌────┐
|
||||
│ │ │ │
|
||||
│ ▼ levIns=1 ▼ │
|
||||
│ ########### is0=1 ########### ########### │
|
||||
│ # # fnc=1 # # any # # │
|
||||
└──# top # ─────────────────────▶# i0 #───────────────▶# na #──┘
|
||||
## ## ──────────┐ ## ## ┌───────▶## ##
|
||||
########─────────────┐│ ######### │┌────────▶#########
|
||||
││ levIns=1 ││
|
||||
││ is0=0 ########### ││
|
||||
││ fnc=1 # # any│
|
||||
│└──────────▶ # iold #────────┘│
|
||||
│ ## ## │
|
||||
│ ######### │
|
||||
│ │
|
||||
│ levIns=1 ########### │
|
||||
│ fnc=0 # # any
|
||||
└────────────▶# inew #─────────┘
|
||||
## ##
|
||||
#########
|
||||
|
||||
*/
|
||||
|
||||
|
||||
template SMTVerifierSM() {
|
||||
signal input is0;
|
||||
signal input levIns;
|
||||
signal input fnc;
|
||||
|
||||
signal input prev_top;
|
||||
signal input prev_i0;
|
||||
signal input prev_iold;
|
||||
signal input prev_inew;
|
||||
signal input prev_na;
|
||||
|
||||
signal output st_top;
|
||||
signal output st_i0;
|
||||
signal output st_iold;
|
||||
signal output st_inew;
|
||||
signal output st_na;
|
||||
|
||||
signal prev_top_lev_ins;
|
||||
signal prev_top_lev_ins_fnc;
|
||||
|
||||
prev_top_lev_ins <== prev_top * levIns;
|
||||
prev_top_lev_ins_fnc <== prev_top_lev_ins*fnc; // prev_top * levIns * fnc
|
||||
|
||||
// st_top = prev_top * (1-levIns)
|
||||
// = + prev_top
|
||||
// - prev_top * levIns
|
||||
st_top <== prev_top - prev_top_lev_ins;
|
||||
|
||||
// st_inew = prev_top * levIns * (1-fnc)
|
||||
// = + prev_top * levIns
|
||||
// - prev_top * levIns * fnc
|
||||
st_inew <== prev_top_lev_ins - prev_top_lev_ins_fnc;
|
||||
|
||||
// st_iold = prev_top * levIns * (1-is0)*fnc
|
||||
// = + prev_top * levIns * fnc
|
||||
// - prev_top * levIns * fnc * is0
|
||||
st_iold <== prev_top_lev_ins_fnc * (1 - is0);
|
||||
|
||||
// st_i0 = prev_top * levIns * is0
|
||||
// = + prev_top * levIns * is0
|
||||
st_i0 <== prev_top_lev_ins * is0;
|
||||
|
||||
st_na <== prev_na + prev_inew + prev_iold + prev_i0;
|
||||
}
|
40
@tornado/circomlib/circuits/switcher.circom
Normal file
40
@tornado/circomlib/circuits/switcher.circom
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of circom (Zero Knowledge Circuit Compiler).
|
||||
|
||||
circom is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
circom is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
Assume sel is binary.
|
||||
|
||||
If sel == 0 then outL = L and outR=R
|
||||
If sel == 1 then outL = R and outR=L
|
||||
|
||||
*/
|
||||
|
||||
template Switcher() {
|
||||
signal input sel;
|
||||
signal input L;
|
||||
signal input R;
|
||||
signal output outL;
|
||||
signal output outR;
|
||||
|
||||
signal aux;
|
||||
|
||||
aux <== (R-L)*sel; // We create aux in order to have only one multiplication
|
||||
outL <== aux + L;
|
||||
outR <== -aux + R;
|
||||
}
|
BIN
@tornado/circomlib/doc/root_transfer.monopic
Normal file
BIN
@tornado/circomlib/doc/root_transfer.monopic
Normal file
Binary file not shown.
BIN
@tornado/circomlib/doc/smt_diagram_0.monopic
Normal file
BIN
@tornado/circomlib/doc/smt_diagram_0.monopic
Normal file
Binary file not shown.
BIN
@tornado/circomlib/doc/smt_diagram_1.monopic
Normal file
BIN
@tornado/circomlib/doc/smt_diagram_1.monopic
Normal file
Binary file not shown.
BIN
@tornado/circomlib/doc/smt_hash.monopic
Normal file
BIN
@tornado/circomlib/doc/smt_hash.monopic
Normal file
Binary file not shown.
BIN
@tornado/circomlib/doc/smt_levins.monopic
Normal file
BIN
@tornado/circomlib/doc/smt_levins.monopic
Normal file
Binary file not shown.
BIN
@tornado/circomlib/doc/smt_sm.monopic
Normal file
BIN
@tornado/circomlib/doc/smt_sm.monopic
Normal file
Binary file not shown.
BIN
@tornado/circomlib/doc/smt_verifier_sm.monopic
Normal file
BIN
@tornado/circomlib/doc/smt_verifier_sm.monopic
Normal file
Binary file not shown.
BIN
@tornado/circomlib/doc/voting.monopic
Normal file
BIN
@tornado/circomlib/doc/voting.monopic
Normal file
Binary file not shown.
BIN
@tornado/circomlib/doc/window.monopic
Normal file
BIN
@tornado/circomlib/doc/window.monopic
Normal file
Binary file not shown.
BIN
@tornado/circomlib/doc/window_chain.monopic
Normal file
BIN
@tornado/circomlib/doc/window_chain.monopic
Normal file
Binary file not shown.
328
@tornado/circomlib/index.d.ts
vendored
Normal file
328
@tornado/circomlib/index.d.ts
vendored
Normal file
@ -0,0 +1,328 @@
|
||||
declare module "circomlib/src/babyjub" {
|
||||
export const Generator: any[];
|
||||
export const Base8: any[];
|
||||
export const order: any;
|
||||
export const subOrder: any;
|
||||
export const A: any;
|
||||
export const D: any;
|
||||
export function addPoint(a: any, b: any): any[];
|
||||
export function mulPointEscalar(base: any, e: any): any[];
|
||||
export function inCurve(P: any): boolean;
|
||||
export function inSubgroup(P: any): any;
|
||||
export function packPoint(P: any): any;
|
||||
export function unpackPoint(_buff: any): any[];
|
||||
export { unknown as p };
|
||||
}
|
||||
declare module "circomlib/src/pedersenHash" {
|
||||
function pedersenHash(msg: any): any;
|
||||
export function getBasePoint(pointIdx: any): any;
|
||||
export { pedersenHash as hash };
|
||||
}
|
||||
declare module "circomlib/src/mimc7" {
|
||||
export function getIV(seed: any): any;
|
||||
export function getConstants(seed: any, nRounds: any): any[];
|
||||
export function hash(_x_in: any, _k: any): any;
|
||||
export function multiHash(arr: any, key: any): any;
|
||||
}
|
||||
declare module "circomlib/src/poseidon" {
|
||||
export function getMatrix(t: any, seed: any, nRounds: any): any[];
|
||||
export function getConstants(t: any, seed: any, nRounds: any): any[];
|
||||
export function createHash(t: any, nRoundsF: any, nRoundsP: any, seed: any): (inputs: any) => any;
|
||||
}
|
||||
declare module "circomlib/src/mimcsponge" {
|
||||
export function getIV(seed: any): any;
|
||||
export function getConstants(seed: any, nRounds: any): any[];
|
||||
export function hash(_xL_in: any, _xR_in: any, _k: any): {
|
||||
xL: any;
|
||||
xR: any;
|
||||
};
|
||||
export function multiHash(arr: any, key: any, numOutputs: any): any;
|
||||
}
|
||||
declare module "circomlib/src/eddsa" {
|
||||
export function prv2pub(prv: any): any[];
|
||||
export function sign(prv: any, msg: any): {
|
||||
R8: any[];
|
||||
S: any;
|
||||
};
|
||||
export function signMiMC(prv: any, msg: any): {
|
||||
R8: any[];
|
||||
S: any;
|
||||
};
|
||||
export function signPoseidon(prv: any, msg: any): {
|
||||
R8: any[];
|
||||
S: any;
|
||||
};
|
||||
export function signMiMCSponge(prv: any, msg: any): {
|
||||
R8: any[];
|
||||
S: any;
|
||||
};
|
||||
export function verify(msg: any, sig: any, A: any): boolean;
|
||||
export function verifyMiMC(msg: any, sig: any, A: any): boolean;
|
||||
export function verifyPoseidon(msg: any, sig: any, A: any): boolean;
|
||||
export function verifyMiMCSponge(msg: any, sig: any, A: any): boolean;
|
||||
export function packSignature(sig: any): Buffer;
|
||||
export function unpackSignature(sigBuff: any): {
|
||||
R8: any[];
|
||||
S: any;
|
||||
};
|
||||
export function pruneBuffer(_buff: any): Buffer;
|
||||
}
|
||||
declare module "circomlib/src/evmasm" {
|
||||
export = Contract;
|
||||
export class Contract {
|
||||
code: any[];
|
||||
labels: {};
|
||||
pendingLabels: {};
|
||||
createTxData(): string;
|
||||
stop(): void;
|
||||
add(): void;
|
||||
mul(): void;
|
||||
sub(): void;
|
||||
div(): void;
|
||||
sdiv(): void;
|
||||
mod(): void;
|
||||
smod(): void;
|
||||
addmod(): void;
|
||||
mulmod(): void;
|
||||
exp(): void;
|
||||
signextend(): void;
|
||||
lt(): void;
|
||||
gt(): void;
|
||||
slt(): void;
|
||||
sgt(): void;
|
||||
eq(): void;
|
||||
iszero(): void;
|
||||
and(): void;
|
||||
or(): void;
|
||||
shor(): void;
|
||||
not(): void;
|
||||
byte(): void;
|
||||
keccak(): void;
|
||||
sha3(): void;
|
||||
address(): void;
|
||||
balance(): void;
|
||||
origin(): void;
|
||||
caller(): void;
|
||||
callvalue(): void;
|
||||
calldataload(): void;
|
||||
calldatasize(): void;
|
||||
calldatacopy(): void;
|
||||
codesize(): void;
|
||||
codecopy(): void;
|
||||
gasprice(): void;
|
||||
extcodesize(): void;
|
||||
extcodecopy(): void;
|
||||
returndatasize(): void;
|
||||
returndatacopy(): void;
|
||||
blockhash(): void;
|
||||
coinbase(): void;
|
||||
timestamp(): void;
|
||||
number(): void;
|
||||
difficulty(): void;
|
||||
gaslimit(): void;
|
||||
pop(): void;
|
||||
mload(): void;
|
||||
mstore(): void;
|
||||
mstore8(): void;
|
||||
sload(): void;
|
||||
sstore(): void;
|
||||
_pushLabel(label: any): void;
|
||||
_fillLabel(label: any): void;
|
||||
jmp(label: any): void;
|
||||
jmpi(label: any): void;
|
||||
pc(): void;
|
||||
msize(): void;
|
||||
gas(): void;
|
||||
label(name: any): void;
|
||||
push(data: any): void;
|
||||
dup(n: any): void;
|
||||
swap(n: any): void;
|
||||
log0(): void;
|
||||
log1(): void;
|
||||
log2(): void;
|
||||
log3(): void;
|
||||
log4(): void;
|
||||
create(): void;
|
||||
call(): void;
|
||||
callcode(): void;
|
||||
return(): void;
|
||||
delegatecall(): void;
|
||||
staticcall(): void;
|
||||
revert(): void;
|
||||
invalid(): void;
|
||||
selfdestruct(): void;
|
||||
}
|
||||
}
|
||||
declare module "circomlib/src/g2_gencontract" {
|
||||
export const abi: {
|
||||
constant: boolean;
|
||||
inputs: {
|
||||
name: string;
|
||||
type: string;
|
||||
}[];
|
||||
name: string;
|
||||
outputs: {
|
||||
name: string;
|
||||
type: string;
|
||||
}[];
|
||||
payable: boolean;
|
||||
stateMutability: string;
|
||||
type: string;
|
||||
}[];
|
||||
export function createCode(P: any, w: any): string;
|
||||
}
|
||||
declare module "circomlib/src/mimc_gencontract" {
|
||||
export const abi: {
|
||||
constant: boolean;
|
||||
inputs: {
|
||||
name: string;
|
||||
type: string;
|
||||
}[];
|
||||
name: string;
|
||||
outputs: {
|
||||
name: string;
|
||||
type: string;
|
||||
}[];
|
||||
payable: boolean;
|
||||
stateMutability: string;
|
||||
type: string;
|
||||
}[];
|
||||
export function createCode(seed: any, n: any): string;
|
||||
}
|
||||
declare module "circomlib/src/mimc_print_iv" {
|
||||
export {};
|
||||
}
|
||||
declare module "circomlib/src/mimc_printconstants" {
|
||||
export {};
|
||||
}
|
||||
declare module "circomlib/src/mimc_printcontract" {
|
||||
export {};
|
||||
}
|
||||
declare module "circomlib/src/mimcsponge_gencontract" {
|
||||
export const abi: {
|
||||
constant: boolean;
|
||||
inputs: {
|
||||
name: string;
|
||||
type: string;
|
||||
}[];
|
||||
name: string;
|
||||
outputs: {
|
||||
name: string;
|
||||
type: string;
|
||||
}[];
|
||||
payable: boolean;
|
||||
stateMutability: string;
|
||||
type: string;
|
||||
}[];
|
||||
export function createCode(seed: any, n: any): string;
|
||||
}
|
||||
declare module "circomlib/src/mimcsponge_printconstants" {
|
||||
export {};
|
||||
}
|
||||
declare module "circomlib/src/mimcsponge_printcontract" {
|
||||
export {};
|
||||
}
|
||||
declare module "circomlib/src/pedersen_printbases" {
|
||||
export {};
|
||||
}
|
||||
declare module "circomlib/src/poseidon_gencontract" {
|
||||
export const abi: {
|
||||
constant: boolean;
|
||||
inputs: {
|
||||
name: string;
|
||||
type: string;
|
||||
}[];
|
||||
name: string;
|
||||
outputs: {
|
||||
name: string;
|
||||
type: string;
|
||||
}[];
|
||||
payable: boolean;
|
||||
stateMutability: string;
|
||||
type: string;
|
||||
}[];
|
||||
export function createCode(t: any, nRoundsF: any, nRoundsP: any, seed: any): string;
|
||||
}
|
||||
declare module "circomlib/src/poseidon_printconstants" {
|
||||
export {};
|
||||
}
|
||||
declare module "circomlib/src/poseidon_printcontract" {
|
||||
export {};
|
||||
}
|
||||
declare module "circomlib/src/poseidon_printmatrix" {
|
||||
export {};
|
||||
}
|
||||
declare module "circomlib/src/smt_memdb" {
|
||||
export = SMTMemDb;
|
||||
export class SMTMemDb {
|
||||
nodes: {};
|
||||
root: any;
|
||||
getRoot(): Promise<any>;
|
||||
_key2str(k: any): any;
|
||||
_normalize(n: any): void;
|
||||
get(key: any): Promise<any>;
|
||||
multiGet(keys: any): Promise<any[]>;
|
||||
setRoot(rt: any): Promise<void>;
|
||||
multiIns(inserts: any): Promise<void>;
|
||||
multiDel(dels: any): Promise<void>;
|
||||
}
|
||||
}
|
||||
declare module "circomlib/src/smt_hashes_poseidon" {
|
||||
export function hash0(left: any, right: any): any;
|
||||
export function hash1(key: any, value: any): any;
|
||||
}
|
||||
declare module "circomlib/src/smt" {
|
||||
export function loadFromFile(fileName: any): Promise<void>;
|
||||
export function newMemEmptyTrie(): Promise<SMT>;
|
||||
export class SMT {
|
||||
constructor(db: any, root: any);
|
||||
db: any;
|
||||
root: any;
|
||||
_splitBits(_key: any): boolean[];
|
||||
update(_key: any, _newValue: any): Promise<{
|
||||
oldRoot: any;
|
||||
oldKey: any;
|
||||
oldValue: any;
|
||||
newKey: any;
|
||||
newValue: any;
|
||||
siblings: any;
|
||||
newRoot: any;
|
||||
}>;
|
||||
delete(_key: any): Promise<{
|
||||
siblings: any[];
|
||||
delKey: any;
|
||||
delValue: any;
|
||||
}>;
|
||||
insert(_key: any, _value: any): Promise<{
|
||||
oldRoot: any;
|
||||
siblings: any;
|
||||
oldKey: any;
|
||||
oldValue: any;
|
||||
newRoot: any;
|
||||
isOld0: any;
|
||||
}>;
|
||||
find(key: any): Promise<any>;
|
||||
_find(key: any, keyBits: any, root: any, level: any): any;
|
||||
}
|
||||
import SMTMemDB = require("circomlib/src/smt_memdb");
|
||||
export { SMTMemDB };
|
||||
}
|
||||
declare module "circomlib/src/smt_hashes_mimc" {
|
||||
export function hash0(left: any, right: any): any;
|
||||
export function hash1(key: any, value: any): any;
|
||||
}
|
||||
declare module "circomlib/calcpedersenbases/calcpedersenbases" {
|
||||
export {};
|
||||
}
|
||||
declare module "circomlib" {
|
||||
export const smt: typeof import("circomlib/src/smt");
|
||||
export const eddsa: typeof import("circomlib/src/eddsa");
|
||||
export const mimc7: typeof import("circomlib/src/mimc7");
|
||||
export const mimcsponge: typeof import("circomlib/src/mimcsponge");
|
||||
export const babyJub: typeof import("circomlib/src/babyjub");
|
||||
export const pedersenHash: typeof import("circomlib/src/pedersenHash");
|
||||
export const SMT: typeof import("circomlib/src/smt").SMT;
|
||||
export const SMTMemDB: typeof import("circomlib/src/smt_memdb");
|
||||
export const poseidon: typeof import("circomlib/src/poseidon");
|
||||
}
|
||||
//# sourceMappingURL=index.d.ts.map
|
1
@tornado/circomlib/index.d.ts.map
Normal file
1
@tornado/circomlib/index.d.ts.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/babyjub.js","src/pedersenHash.js","src/mimc7.js","src/poseidon.js","src/mimcsponge.js","src/eddsa.js","src/evmasm.js","src/g2_gencontract.js","src/mimc_gencontract.js","src/mimc_print_iv.js","src/mimc_printconstants.js","src/mimc_printcontract.js","src/mimcsponge_gencontract.js","src/mimcsponge_printconstants.js","src/mimcsponge_printcontract.js","src/pedersen_printbases.js","src/poseidon_gencontract.js","src/poseidon_printconstants.js","src/poseidon_printcontract.js","src/poseidon_printmatrix.js","src/smt_memdb.js","src/smt_hashes_poseidon.js","src/smt.js","src/smt_hashes_mimc.js","calcpedersenbases/calcpedersenbases.js","index.js"],"names":[],"mappings":";;;;;;;IAwBA,gDAaC;IAED,0DAcC;IAQD,yCAWC;IAjBD,wCAIC;IAeD,uCAMC;IAED,+CA0BC;;;;IChGD,qCA4CC;IAID,iDAoBC;;;;ICxEe,sCAMf;IAEsB,6DActB;IAIe,+CAUf;IAEmB,mDAiBnB;;;IC7BmB,kEAoBnB;IAEsB,qEAMtB;IAuBoB,kGA4BpB;;;ICzGe,sCAMf;IAEsB,6DAetB;IAIc;;;MAmBd;IAEmB,oEA6BnB;;;ICvDD,yCAKC;IAED;;;MAmBC;IAED;;;MAiBC;IAqBD;;;MAkBC;IArCD;;;MAiBC;IAsBD,4DAuBC;IAED,gEAoBC;IAGD,oEAqBC;IAED,sEAoBC;IAED,gDAIC;IAED;;;MAKC;IAtMD,gDAMC;;;;ICrBD;QAEQ,YAAc;QACd,WAAgB;QAChB,kBAAuB;QAG3B,uBA2BC;QAED,aAAgC;QAChC,YAAgC;QAChC,YAAgC;QAChC,YAAgC;QAChC,YAAgC;QAChC,aAAgC;QAChC,YAAgC;QAChC,aAAiC;QACjC,eAAmC;QACnC,eAAmC;QACnC,YAAgC;QAChC,mBAAuC;QAEvC,WAAgC;QAChC,WAAgC;QAChC,YAAgC;QAChC,YAAgC;QAChC,WAAgC;QAChC,eAAmC;QACnC,YAAgC;QAChC,WAA+B;QAC/B,aAAiC;QACjC,YAAgC;QAChC,aAAiC;QAEjC,eAAkC;QAClC,aAAgC;QAEhC,gBAAoC;QACpC,gBAAoC;QACpC,eAAmC;QACnC,eAAmC;QACnC,kBAAsC;QACtC,qBAAyC;QACzC,qBAAyC;QACzC,qBAAyC;QACzC,iBAAqC;QACrC,iBAAqC;QACrC,iBAAqC;QACrC,oBAAwC;QACxC,oBAAwC;QACxC,uBAA2C;QAC3C,uBAA2C;QAE3C,kBAAsC;QACtC,iBAAqC;QACrC,kBAAsC;QACtC,eAAmC;QACnC,mBAAuC;QACvC,iBAAqC;QAErC,YAAgC;QAChC,cAAkC;QAClC,eAAmC;QACnC,gBAAoC;QACpC,cAAkC;QAClC,eAAmC;QAEnC,6BAQC;QAED,6BAcC;QAGD,sBAKC;QAED,uBAKC;QAED,WAA+B;QAC/B,cAAkC;QAClC,YAAgC;QAChC,uBAQC;QAED,sBAMC;QAED,kBAKC;QAED,mBAKC;QAED,aAAiC;QACjC,aAAiC;QACjC,aAAiC;QACjC,aAAiC;QACjC,aAAiC;QAEjC,eAAmC;QACnC,aAAiC;QACjC,iBAAqC;QACrC,eAAmC;QACnC,qBAAyC;QAEzC,mBAAuC;QACvC,eAAmC;QACnC,gBAAoC;QACpC,qBAAyC;KAC5C;;;;;;;;;;;;;;;;;;IClLD,mDA2hBC;;;;;;;;;;;;;;;;;;ICliBD,sDA2EC;;;;;;;;;;;;;;;;;;;;;;;;;;;II3ED,sDAyEC;;;;;;;;;;;;;;;;;;;;;;;;;;;II9DD,oFAsIC;;;;;;;;;;;;;IIvJD;QAEQ,UAAe;QACf,UAAqB;QAGzB,wBAEC;QAED,sBAIC;QAED,yBAIC;QAED,4BAGC;QAED,oCAMC;QAED,gCAEC;QAED,sCAMC;QAED,mCAKC;KACJ;;;IClDe,kDAEf;IAEe,iDAEf;;;IC+RD,2DAEC;IAED,gDAKC;IA9SD;QAEI,gCAGC;QAFG,QAAY;QACZ,UAAgB;QAGpB,iCAiBC;QAED;;;;;;;;WA+CC;QAED;;;;WAmFC;QAED;;;;;;;WA+EC;QAED,6BAGC;QAED,0DA4CC;KACJ;;;;;ICrSe,kDAEf;IAEe,iDAEf"}
|
9
@tornado/circomlib/index.js
Normal file
9
@tornado/circomlib/index.js
Normal file
@ -0,0 +1,9 @@
|
||||
exports.smt = require("./src/smt");
|
||||
exports.eddsa = require("./src/eddsa");
|
||||
exports.mimc7 = require("./src/mimc7");
|
||||
exports.mimcsponge = require("./src/mimcsponge");
|
||||
exports.babyJub = require("./src/babyjub");
|
||||
exports.pedersenHash = require("./src/pedersenHash");
|
||||
exports.SMT = require("./src/smt").SMT;
|
||||
exports.SMTMemDB = require("./src/smt_memdb");
|
||||
exports.poseidon = require("./src/poseidon");
|
41
@tornado/circomlib/package.json
Normal file
41
@tornado/circomlib/package.json
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "@tornado/circomlib",
|
||||
"version": "0.0.20-p2",
|
||||
"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://development.tornadocash.community/tornadocash/circomlib"
|
||||
},
|
||||
"author": "0Kims",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@tornado/snarkjs": "workspace:*",
|
||||
"blake-hash": "^1.1.0",
|
||||
"blake2b": "^2.1.3",
|
||||
"typedarray-to-buffer": "^3.1.5",
|
||||
"web3": "^1.9.0",
|
||||
"web3-utils": "^1.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"circom": "0.0.35",
|
||||
"eslint-plugin-mocha": "^5.2.0",
|
||||
"ganache-cli": "^6.4.4",
|
||||
"mocha": "^5.2.0",
|
||||
"typescript": "^5.0.2"
|
||||
}
|
||||
}
|
109
@tornado/circomlib/src/babyjub.js
Normal file
109
@tornado/circomlib/src/babyjub.js
Normal file
@ -0,0 +1,109 @@
|
||||
const bn128 = require("@tornado/snarkjs").bn128;
|
||||
const bigInt = require("@tornado/snarkjs").bigInt;
|
||||
|
||||
exports.addPoint = addPoint;
|
||||
exports.mulPointEscalar = mulPointEscalar;
|
||||
exports.inCurve = inCurve;
|
||||
exports.inSubgroup = inSubgroup;
|
||||
exports.packPoint = packPoint;
|
||||
exports.unpackPoint = unpackPoint;
|
||||
exports.Generator = [
|
||||
bigInt("995203441582195749578291179787384436505546430278305826713579947235728471134"),
|
||||
bigInt("5472060717959818805561601436314318772137091100104008585924551046643952123905")
|
||||
];
|
||||
exports.Base8 = [
|
||||
bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
|
||||
bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")
|
||||
];
|
||||
exports.order = bigInt("21888242871839275222246405745257275088614511777268538073601725287587578984328");
|
||||
exports.subOrder = exports.order.shr(3);
|
||||
exports.p = bn128.r;
|
||||
exports.A = bigInt("168700");
|
||||
exports.D = bigInt("168696");
|
||||
|
||||
|
||||
function addPoint(a,b) {
|
||||
const q = bn128.r;
|
||||
|
||||
const res = [];
|
||||
|
||||
/* does the equivalent of:
|
||||
res[0] = bigInt((a[0]*b[1] + b[0]*a[1]) * bigInt(bigInt("1") + d*a[0]*b[0]*a[1]*b[1]).inverse(q)).affine(q);
|
||||
res[1] = bigInt((a[1]*b[1] - cta*a[0]*b[0]) * bigInt(bigInt("1") - d*a[0]*b[0]*a[1]*b[1]).inverse(q)).affine(q);
|
||||
*/
|
||||
res[0] = bigInt((bigInt(a[0]).mul(b[1]).add(bigInt(b[0]).mul(a[1]))).mul(bigInt(bigInt("1").add(exports.D.mul(a[0]).mul(b[0]).mul(a[1]).mul(b[1]))).inverse(q))).affine(q);
|
||||
res[1] = bigInt((bigInt(a[1]).mul(b[1]).sub(exports.A.mul(a[0]).mul(b[0]))).mul(bigInt(bigInt("1").sub(exports.D.mul(a[0]).mul(b[0]).mul(a[1]).mul(b[1]))).inverse(q))).affine(q);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
function mulPointEscalar(base, e) {
|
||||
let res = [bigInt("0"),bigInt("1")];
|
||||
let rem = bigInt(e);
|
||||
let exp = base;
|
||||
|
||||
while (! rem.isZero()) {
|
||||
if (rem.isOdd()) {
|
||||
res = addPoint(res, exp);
|
||||
}
|
||||
exp = addPoint(exp, exp);
|
||||
rem = rem.shr(1);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
function inSubgroup(P) {
|
||||
if (!inCurve(P)) return false;
|
||||
const res= mulPointEscalar(P, exports.subOrder);
|
||||
return (res[0].equals(bigInt(0))) && (res[1].equals(bigInt(1)));
|
||||
}
|
||||
|
||||
function inCurve(P) {
|
||||
const F = bn128.Fr;
|
||||
|
||||
const x2 = F.square(P[0]);
|
||||
const y2 = F.square(P[1]);
|
||||
|
||||
if (!F.equals(
|
||||
F.add(F.mul(exports.A, x2), y2),
|
||||
F.add(F.one, F.mul(F.mul(x2, y2), exports.D)))) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function packPoint(P) {
|
||||
const buff = bigInt.leInt2Buff(P[1], 32);
|
||||
if (P[0].greater(exports.p.shr(1))) {
|
||||
buff[31] = buff[31] | 0x80;
|
||||
}
|
||||
return buff;
|
||||
}
|
||||
|
||||
function unpackPoint(_buff) {
|
||||
const F = bn128.Fr;
|
||||
|
||||
const buff = Buffer.from(_buff);
|
||||
let sign = false;
|
||||
const P = new Array(2);
|
||||
if (buff[31] & 0x80) {
|
||||
sign = true;
|
||||
buff[31] = buff[31] & 0x7F;
|
||||
}
|
||||
P[1] = bigInt.leBuff2int(buff);
|
||||
if (P[1].greaterOrEquals(exports.p)) return null;
|
||||
|
||||
const y2 = F.square(P[1]);
|
||||
|
||||
let x = F.sqrt(F.div(
|
||||
F.sub(F.one, y2),
|
||||
F.sub(exports.A, F.mul(exports.D, y2))));
|
||||
|
||||
if (x == null) return null;
|
||||
|
||||
if (sign) x = F.neg(x);
|
||||
|
||||
P[0] = F.affine(x);
|
||||
|
||||
return P;
|
||||
}
|
223
@tornado/circomlib/src/eddsa.js
Normal file
223
@tornado/circomlib/src/eddsa.js
Normal file
@ -0,0 +1,223 @@
|
||||
const createBlakeHash = require("blake-hash");
|
||||
const bigInt = require("@tornado/snarkjs").bigInt;
|
||||
const babyJub = require("./babyjub");
|
||||
const pedersenHash = require("./pedersenHash").hash;
|
||||
const mimc7 = require("./mimc7");
|
||||
const poseidon = require("./poseidon.js");
|
||||
const mimcsponge = require("./mimcsponge");
|
||||
|
||||
exports.prv2pub= prv2pub;
|
||||
exports.sign = sign;
|
||||
exports.signMiMC = signMiMC;
|
||||
exports.signPoseidon = signPoseidon;
|
||||
exports.signMiMCSponge = signMiMCSponge;
|
||||
exports.verify = verify;
|
||||
exports.verifyMiMC = verifyMiMC;
|
||||
exports.verifyPoseidon = verifyPoseidon;
|
||||
exports.verifyMiMCSponge = verifyMiMCSponge;
|
||||
exports.packSignature = packSignature;
|
||||
exports.unpackSignature = unpackSignature;
|
||||
exports.pruneBuffer = pruneBuffer;
|
||||
|
||||
|
||||
function pruneBuffer(_buff) {
|
||||
const buff = Buffer.from(_buff);
|
||||
buff[0] = buff[0] & 0xF8;
|
||||
buff[31] = buff[31] & 0x7F;
|
||||
buff[31] = buff[31] | 0x40;
|
||||
return buff;
|
||||
}
|
||||
|
||||
function prv2pub(prv) {
|
||||
const sBuff = pruneBuffer(createBlakeHash("blake512").update(prv).digest().slice(0,32));
|
||||
let s = bigInt.leBuff2int(sBuff);
|
||||
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
|
||||
return A;
|
||||
}
|
||||
|
||||
function sign(prv, msg) {
|
||||
const h1 = createBlakeHash("blake512").update(prv).digest();
|
||||
const sBuff = pruneBuffer(h1.slice(0,32));
|
||||
const s = bigInt.leBuff2int(sBuff);
|
||||
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
|
||||
|
||||
const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msg])).digest();
|
||||
let r = bigInt.leBuff2int(rBuff);
|
||||
r = r.mod(babyJub.subOrder);
|
||||
const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
|
||||
const R8p = babyJub.packPoint(R8);
|
||||
const Ap = babyJub.packPoint(A);
|
||||
const hmBuff = pedersenHash(Buffer.concat([R8p, Ap, msg]));
|
||||
const hm = bigInt.leBuff2int(hmBuff);
|
||||
const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
|
||||
return {
|
||||
R8: R8,
|
||||
S: S
|
||||
};
|
||||
}
|
||||
|
||||
function signMiMC(prv, msg) {
|
||||
const h1 = createBlakeHash("blake512").update(prv).digest();
|
||||
const sBuff = pruneBuffer(h1.slice(0,32));
|
||||
const s = bigInt.leBuff2int(sBuff);
|
||||
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
|
||||
|
||||
const msgBuff = bigInt.leInt2Buff(msg, 32);
|
||||
const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
|
||||
let r = bigInt.leBuff2int(rBuff);
|
||||
r = r.mod(babyJub.subOrder);
|
||||
const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
|
||||
const hm = mimc7.multiHash([R8[0], R8[1], A[0], A[1], msg]);
|
||||
const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
|
||||
return {
|
||||
R8: R8,
|
||||
S: S
|
||||
};
|
||||
}
|
||||
|
||||
function signMiMCSponge(prv, msg) {
|
||||
const h1 = createBlakeHash("blake512").update(prv).digest();
|
||||
const sBuff = pruneBuffer(h1.slice(0,32));
|
||||
const s = bigInt.leBuff2int(sBuff);
|
||||
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
|
||||
|
||||
const msgBuff = bigInt.leInt2Buff(msg, 32);
|
||||
const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
|
||||
let r = bigInt.leBuff2int(rBuff);
|
||||
r = r.mod(babyJub.subOrder);
|
||||
const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
|
||||
const hm = mimcsponge.multiHash([R8[0], R8[1], A[0], A[1], msg]);
|
||||
const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
|
||||
return {
|
||||
R8: R8,
|
||||
S: S
|
||||
};
|
||||
}
|
||||
|
||||
function signPoseidon(prv, msg) {
|
||||
const h1 = createBlakeHash("blake512").update(prv).digest();
|
||||
const sBuff = pruneBuffer(h1.slice(0,32));
|
||||
const s = bigInt.leBuff2int(sBuff);
|
||||
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
|
||||
|
||||
const msgBuff = bigInt.leInt2Buff(msg, 32);
|
||||
const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest();
|
||||
let r = bigInt.leBuff2int(rBuff);
|
||||
r = r.mod(babyJub.subOrder);
|
||||
const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
|
||||
const hash = poseidon.createHash(6, 8, 57);
|
||||
const hm = hash([R8[0], R8[1], A[0], A[1], msg]);
|
||||
const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
|
||||
return {
|
||||
R8: R8,
|
||||
S: S
|
||||
};
|
||||
}
|
||||
|
||||
function verify(msg, sig, A) {
|
||||
// Check parameters
|
||||
if (typeof sig != "object") return false;
|
||||
if (!Array.isArray(sig.R8)) return false;
|
||||
if (sig.R8.length!= 2) return false;
|
||||
if (!babyJub.inCurve(sig.R8)) return false;
|
||||
if (!Array.isArray(A)) return false;
|
||||
if (A.length!= 2) return false;
|
||||
if (!babyJub.inCurve(A)) return false;
|
||||
if (sig.S>= babyJub.subOrder) return false;
|
||||
|
||||
const R8p = babyJub.packPoint(sig.R8);
|
||||
const Ap = babyJub.packPoint(A);
|
||||
const hmBuff = pedersenHash(Buffer.concat([R8p, Ap, msg]));
|
||||
const hm = bigInt.leBuff2int(hmBuff);
|
||||
|
||||
const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
|
||||
let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
|
||||
Pright = babyJub.addPoint(sig.R8, Pright);
|
||||
|
||||
if (!Pleft[0].equals(Pright[0])) return false;
|
||||
if (!Pleft[1].equals(Pright[1])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function verifyMiMC(msg, sig, A) {
|
||||
// Check parameters
|
||||
if (typeof sig != "object") return false;
|
||||
if (!Array.isArray(sig.R8)) return false;
|
||||
if (sig.R8.length!= 2) return false;
|
||||
if (!babyJub.inCurve(sig.R8)) return false;
|
||||
if (!Array.isArray(A)) return false;
|
||||
if (A.length!= 2) return false;
|
||||
if (!babyJub.inCurve(A)) return false;
|
||||
if (sig.S>= babyJub.subOrder) return false;
|
||||
|
||||
const hm = mimc7.multiHash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
|
||||
|
||||
const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
|
||||
let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
|
||||
Pright = babyJub.addPoint(sig.R8, Pright);
|
||||
|
||||
if (!Pleft[0].equals(Pright[0])) return false;
|
||||
if (!Pleft[1].equals(Pright[1])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function verifyPoseidon(msg, sig, A) {
|
||||
// Check parameters
|
||||
if (typeof sig != "object") return false;
|
||||
if (!Array.isArray(sig.R8)) return false;
|
||||
if (sig.R8.length!= 2) return false;
|
||||
if (!babyJub.inCurve(sig.R8)) return false;
|
||||
if (!Array.isArray(A)) return false;
|
||||
if (A.length!= 2) return false;
|
||||
if (!babyJub.inCurve(A)) return false;
|
||||
if (sig.S>= babyJub.subOrder) return false;
|
||||
|
||||
const hash = poseidon.createHash(6, 8, 57);
|
||||
const hm = hash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
|
||||
|
||||
const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
|
||||
let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
|
||||
Pright = babyJub.addPoint(sig.R8, Pright);
|
||||
|
||||
if (!Pleft[0].equals(Pright[0])) return false;
|
||||
if (!Pleft[1].equals(Pright[1])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function verifyMiMCSponge(msg, sig, A) {
|
||||
// Check parameters
|
||||
if (typeof sig != "object") return false;
|
||||
if (!Array.isArray(sig.R8)) return false;
|
||||
if (sig.R8.length!= 2) return false;
|
||||
if (!babyJub.inCurve(sig.R8)) return false;
|
||||
if (!Array.isArray(A)) return false;
|
||||
if (A.length!= 2) return false;
|
||||
if (!babyJub.inCurve(A)) return false;
|
||||
if (sig.S>= babyJub.subOrder) return false;
|
||||
|
||||
const hm = mimcsponge.multiHash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
|
||||
|
||||
const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
|
||||
let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
|
||||
Pright = babyJub.addPoint(sig.R8, Pright);
|
||||
|
||||
if (!Pleft[0].equals(Pright[0])) return false;
|
||||
if (!Pleft[1].equals(Pright[1])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function packSignature(sig) {
|
||||
const R8p = babyJub.packPoint(sig.R8);
|
||||
const Sp = bigInt.leInt2Buff(sig.S, 32);
|
||||
return Buffer.concat([R8p, Sp]);
|
||||
}
|
||||
|
||||
function unpackSignature(sigBuff) {
|
||||
return {
|
||||
R8: babyJub.unpackPoint(sigBuff.slice(0,32)),
|
||||
S: bigInt.leBuff2int(sigBuff.slice(32,64))
|
||||
};
|
||||
}
|
||||
|
||||
|
197
@tornado/circomlib/src/evmasm.js
Normal file
197
@tornado/circomlib/src/evmasm.js
Normal file
@ -0,0 +1,197 @@
|
||||
// Copyright (c) 2018 Jordi Baylina
|
||||
// License: LGPL-3.0+
|
||||
//
|
||||
|
||||
|
||||
const Web3Utils = require("web3-utils");
|
||||
|
||||
class Contract {
|
||||
constructor() {
|
||||
this.code = [];
|
||||
this.labels = {};
|
||||
this.pendingLabels = {};
|
||||
}
|
||||
|
||||
createTxData() {
|
||||
let C;
|
||||
|
||||
// Check all labels are defined
|
||||
const pendingLabels = Object.keys(this.pendingLabels);
|
||||
if (pendingLabels.length>0) {
|
||||
throw new Error("Lables not defined: "+ pendingLabels.join(", "));
|
||||
}
|
||||
|
||||
let setLoaderLength = 0;
|
||||
let genLoadedLength = -1;
|
||||
|
||||
while (genLoadedLength!=setLoaderLength) {
|
||||
setLoaderLength = genLoadedLength;
|
||||
C = new module.exports();
|
||||
C.codesize();
|
||||
C.push(setLoaderLength);
|
||||
C.push(0);
|
||||
C.codecopy();
|
||||
|
||||
C.push(this.code.length);
|
||||
C.push(0);
|
||||
C.return();
|
||||
genLoadedLength = C.code.length;
|
||||
}
|
||||
|
||||
return Web3Utils.bytesToHex(C.code.concat(this.code));
|
||||
}
|
||||
|
||||
stop() { this.code.push(0x00); }
|
||||
add() { this.code.push(0x01); }
|
||||
mul() { this.code.push(0x02); }
|
||||
sub() { this.code.push(0x03); }
|
||||
div() { this.code.push(0x04); }
|
||||
sdiv() { this.code.push(0x05); }
|
||||
mod() { this.code.push(0x06); }
|
||||
smod() { this.code.push(0x07); }
|
||||
addmod() { this.code.push(0x08); }
|
||||
mulmod() { this.code.push(0x09); }
|
||||
exp() { this.code.push(0x0a); }
|
||||
signextend() { this.code.push(0x0b); }
|
||||
|
||||
lt() { this.code.push(0x10); }
|
||||
gt() { this.code.push(0x11); }
|
||||
slt() { this.code.push(0x12); }
|
||||
sgt() { this.code.push(0x13); }
|
||||
eq() { this.code.push(0x14); }
|
||||
iszero() { this.code.push(0x15); }
|
||||
and() { this.code.push(0x16); }
|
||||
or() { this.code.push(0x17); }
|
||||
shor() { this.code.push(0x18); }
|
||||
not() { this.code.push(0x19); }
|
||||
byte() { this.code.push(0x1a); }
|
||||
|
||||
keccak() { this.code.push(0x20); }
|
||||
sha3() { this.code.push(0x20); } // alias
|
||||
|
||||
address() { this.code.push(0x30); }
|
||||
balance() { this.code.push(0x31); }
|
||||
origin() { this.code.push(0x32); }
|
||||
caller() { this.code.push(0x33); }
|
||||
callvalue() { this.code.push(0x34); }
|
||||
calldataload() { this.code.push(0x35); }
|
||||
calldatasize() { this.code.push(0x36); }
|
||||
calldatacopy() { this.code.push(0x37); }
|
||||
codesize() { this.code.push(0x38); }
|
||||
codecopy() { this.code.push(0x39); }
|
||||
gasprice() { this.code.push(0x3a); }
|
||||
extcodesize() { this.code.push(0x3b); }
|
||||
extcodecopy() { this.code.push(0x3c); }
|
||||
returndatasize() { this.code.push(0x3d); }
|
||||
returndatacopy() { this.code.push(0x3e); }
|
||||
|
||||
blockhash() { this.code.push(0x40); }
|
||||
coinbase() { this.code.push(0x41); }
|
||||
timestamp() { this.code.push(0x42); }
|
||||
number() { this.code.push(0x43); }
|
||||
difficulty() { this.code.push(0x44); }
|
||||
gaslimit() { this.code.push(0x45); }
|
||||
|
||||
pop() { this.code.push(0x50); }
|
||||
mload() { this.code.push(0x51); }
|
||||
mstore() { this.code.push(0x52); }
|
||||
mstore8() { this.code.push(0x53); }
|
||||
sload() { this.code.push(0x54); }
|
||||
sstore() { this.code.push(0x55); }
|
||||
|
||||
_pushLabel(label) {
|
||||
if (typeof this.labels[label] != "undefined") {
|
||||
this.push(this.labels[label]);
|
||||
} else {
|
||||
this.pendingLabels[label] = this.pendingLabels[label] || [];
|
||||
this.pendingLabels[label].push(this.code.length);
|
||||
this.push("0x000000");
|
||||
}
|
||||
}
|
||||
|
||||
_fillLabel(label) {
|
||||
if (!this.pendingLabels[label]) return;
|
||||
|
||||
let dst = this.labels[label];
|
||||
|
||||
const dst3 = [dst >> 16, (dst >> 8) & 0xFF, dst & 0xFF];
|
||||
|
||||
this.pendingLabels[label].forEach((p) => {
|
||||
for (let i=0; i<3; i++) {
|
||||
this.code[p+i+1] = dst3[i];
|
||||
}
|
||||
});
|
||||
|
||||
delete this.pendingLabels[label];
|
||||
}
|
||||
|
||||
|
||||
jmp(label) {
|
||||
if (typeof label !== "undefined") {
|
||||
this._pushLabel(label);
|
||||
}
|
||||
this.code.push(0x56);
|
||||
}
|
||||
|
||||
jmpi(label) {
|
||||
if (typeof label !== "undefined") {
|
||||
this._pushLabel(label);
|
||||
}
|
||||
this.code.push(0x57);
|
||||
}
|
||||
|
||||
pc() { this.code.push(0x58); }
|
||||
msize() { this.code.push(0x59); }
|
||||
gas() { this.code.push(0x5a); }
|
||||
label(name) {
|
||||
if (typeof this.labels[name] != "undefined") {
|
||||
throw new Error("Label already defined");
|
||||
}
|
||||
this.labels[name] = this.code.length;
|
||||
this.code.push(0x5b);
|
||||
|
||||
this._fillLabel(name);
|
||||
}
|
||||
|
||||
push(data) {
|
||||
const d = Web3Utils.hexToBytes(Web3Utils.toHex(data));
|
||||
if (d.length == 0 || d.length > 32) {
|
||||
throw new Error("Assertion failed");
|
||||
}
|
||||
this.code = this.code.concat([0x5F + d.length], d);
|
||||
}
|
||||
|
||||
dup(n) {
|
||||
if (n < 0 || n >= 16) {
|
||||
throw new Error("Assertion failed");
|
||||
}
|
||||
this.code.push(0x80 + n);
|
||||
}
|
||||
|
||||
swap(n) {
|
||||
if (n < 1 || n > 16) {
|
||||
throw new Error("Assertion failed");
|
||||
}
|
||||
this.code.push(0x8f + n);
|
||||
}
|
||||
|
||||
log0() { this.code.push(0xa0); }
|
||||
log1() { this.code.push(0xa1); }
|
||||
log2() { this.code.push(0xa2); }
|
||||
log3() { this.code.push(0xa3); }
|
||||
log4() { this.code.push(0xa4); }
|
||||
|
||||
create() { this.code.push(0xf0); }
|
||||
call() { this.code.push(0xf1); }
|
||||
callcode() { this.code.push(0xf2); }
|
||||
return() { this.code.push(0xf3); }
|
||||
delegatecall() { this.code.push(0xf4); }
|
||||
|
||||
staticcall() { this.code.push(0xfa); }
|
||||
revert() { this.code.push(0xfd); }
|
||||
invalid() { this.code.push(0xfe); }
|
||||
selfdestruct() { this.code.push(0xff); }
|
||||
}
|
||||
|
||||
module.exports = Contract;
|
||||
|
583
@tornado/circomlib/src/g2_gencontract.js
Normal file
583
@tornado/circomlib/src/g2_gencontract.js
Normal file
@ -0,0 +1,583 @@
|
||||
// Copyright (c) 2018 Jordi Baylina
|
||||
// License: LGPL-3.0+
|
||||
//
|
||||
|
||||
const Contract = require("./evmasm");
|
||||
const G2 = require("@tornado/snarkjs").bn128.G2;
|
||||
const bigInt = require("@tornado/snarkjs").bigInt;
|
||||
|
||||
|
||||
function toHex256(a) {
|
||||
let S = a.toString(16);
|
||||
while (S.length < 64) S="0"+S;
|
||||
return "0x" + S;
|
||||
}
|
||||
|
||||
function createCode(P, w) {
|
||||
|
||||
const C = new Contract();
|
||||
|
||||
const NPOINTS = 1 << (w-1);
|
||||
|
||||
const VAR_POS = C.allocMem(32);
|
||||
const VAR_POINTS = C.allocMem( (NPOINTS)*4*32);
|
||||
const savedP = C.allocMem(32);
|
||||
const savedZ3 = C.allocMem(32);
|
||||
|
||||
// Check selector
|
||||
C.push("0x0100000000000000000000000000000000000000000000000000000000");
|
||||
C.push(0);
|
||||
C.calldataload();
|
||||
C.div();
|
||||
C.push("b65c7c74"); // mulexp(uint256)
|
||||
C.eq();
|
||||
C.jmpi("start");
|
||||
C.invalid();
|
||||
|
||||
C.label("start");
|
||||
|
||||
storeVals();
|
||||
|
||||
C.push( Math.floor(255/w)*w ); // pos := 255
|
||||
C.push(VAR_POS);
|
||||
C.mstore();
|
||||
|
||||
C.push("21888242871839275222246405745257275088696311157297823662689037894645226208583");
|
||||
C.push(0);
|
||||
C.push(0);
|
||||
C.push(0);
|
||||
C.push(0);
|
||||
C.push(0);
|
||||
C.push(0);
|
||||
|
||||
C.label("begin_loop"); // ACC_X ACC_Y ACC_Z q
|
||||
|
||||
C.internalCall("double");
|
||||
|
||||
// g = (e>>pos)&MASK
|
||||
C.push(4);
|
||||
C.calldataload(); // e ACC_X ACC_Y ACC_Z q
|
||||
|
||||
C.push(VAR_POS);
|
||||
C.mload(); // pos e ACC_X ACC_Y ACC_Z q
|
||||
C.shr();
|
||||
|
||||
C.push(NPOINTS-1);
|
||||
C.and(); // g ACC_X ACC_Y ACC_Z q
|
||||
|
||||
C.internalCall("add"); // acc_x acc_y acc_z
|
||||
|
||||
C.push(VAR_POS);
|
||||
C.mload(); // pos acc_x acc_y acc_z
|
||||
C.dup(0); // pos pos acc_x acc_y acc_z
|
||||
C.push(0); // 0 pos pos acc_x acc_y acc_z
|
||||
C.eq(); // eq pos acc_x acc_y acc_z
|
||||
C.jmpi("after_loop"); // pos acc_x acc_y acc_z
|
||||
C.push(w); // 5 pos acc_x acc_y acc_z
|
||||
C.sub(); // pos acc_x acc_y acc_z
|
||||
C.push(VAR_POS);
|
||||
C.mstore(); // acc_x acc_y acc_z
|
||||
C.jmp("begin_loop");
|
||||
C.label("after_loop"); // pos acc_x acc_y acc_z
|
||||
C.pop(); // acc_x acc_y acc_z
|
||||
|
||||
C.internalCall("affine"); // acc_x acc_y
|
||||
|
||||
C.push(0);
|
||||
C.mstore();
|
||||
C.push(20);
|
||||
C.mstore();
|
||||
C.push(40);
|
||||
C.mstore();
|
||||
C.push(60);
|
||||
C.mstore();
|
||||
|
||||
C.push("0x80");
|
||||
C.push("0x00");
|
||||
C.return();
|
||||
|
||||
|
||||
double();
|
||||
addPoint();
|
||||
affine();
|
||||
|
||||
return C.createTxData();
|
||||
|
||||
function add(a,b,q) {
|
||||
C.dup(q);
|
||||
C.dup(a+1 + 1);
|
||||
C.dup(b+1 + 2);
|
||||
C.addmod();
|
||||
C.dup(q + 1);
|
||||
C.dup(a + 2);
|
||||
C.dup(b + 3);
|
||||
C.addmod();
|
||||
}
|
||||
|
||||
function sub(a,b,q) {
|
||||
C.dup(q); // q
|
||||
C.dup(a+1 + 1); // ai q
|
||||
C.dub(q + 2); // q ai q
|
||||
C.dup(b+1 + 3); // bi q ai q
|
||||
C.sub(); // -bi ai q
|
||||
C.addmod(); // ci
|
||||
C.dup(q + 1); // q ci
|
||||
C.dup(a + 2); // ar q ci
|
||||
C.dup(q + 3); // q ar q ci
|
||||
C.dup(b + 4); // br q ar q ci
|
||||
C.sub(); // -br ar q ci
|
||||
C.addmod(); // cr ci
|
||||
}
|
||||
|
||||
function mul(a, b, q) {
|
||||
C.dup(q); // q
|
||||
C.dup(q + 1); // q q
|
||||
C.dup(a + 2); // ar q q
|
||||
C.dup(b+1 + 3); // bi ar q q
|
||||
C.mulmod(); // ci1 q
|
||||
C.dup(q + 2); // q ci1 q
|
||||
C.dup(a+1 + 3); // ai q ci1 q
|
||||
C.dup(b + 4); // ar ai q ci1 q
|
||||
C.mulmod(); // ci2 ci1 q
|
||||
C.addmod(); // ci
|
||||
C.dup(q + 1); // q ci
|
||||
C.dup(q + 2); // q q ci
|
||||
C.dup(q + 3); // q q q ci
|
||||
C.dup(a+1 + 4); // ai q q ci
|
||||
C.dup(b+1 + 5); // bi ai q q ci
|
||||
C.mulmod(); // cr2 q q ci
|
||||
C.sub(); // -cr2 q ci
|
||||
C.dup(q + 3); // q -cr2 q ci
|
||||
C.dup(a + 4); // ar q -cr2 q ci
|
||||
C.dup(b + 5); // br ar q -cr2 q ci
|
||||
C.mulmod(); // cr1 -cr2 q ci
|
||||
C.addmod(); // cr ci
|
||||
}
|
||||
|
||||
function square(a, q) {
|
||||
C.dup(q); // q
|
||||
C.dup(q + 1); // q q
|
||||
C.dup(a + 2); // ar q q
|
||||
C.dup(a+1 + 3); // ai ar q q
|
||||
C.mulmod(); // arai q
|
||||
C.dup(0); // arai arai q
|
||||
C.addmod(); // ci
|
||||
C.dup(q + 1); // q ci
|
||||
C.dup(q + 2); // q q ci
|
||||
C.dup(q + 3); // q q q ci
|
||||
C.dup(a+1 + 4); // ai q q ci
|
||||
C.dup(a+1 + 5); // ai ai q q ci
|
||||
C.mulmod(); // cr2 q q ci
|
||||
C.sub(); // -cr2 q ci
|
||||
C.dup(q + 3); // q -cr2 q ci
|
||||
C.dup(a + 4); // ar q -cr2 q ci
|
||||
C.dup(a + 5); // br ar q -cr2 q ci
|
||||
C.mulmod(); // cr1 -cr2 q ci
|
||||
C.addmod(); // cr ci
|
||||
}
|
||||
|
||||
function add1(a, q) {
|
||||
C.dup(a+1); // im
|
||||
C.dup(1 + q); // q
|
||||
C.dup(2 + a); // re q im
|
||||
C.push(1); // 1 re q im
|
||||
C.addmod();
|
||||
}
|
||||
|
||||
function cmp(a, b) {
|
||||
C.dup(a);
|
||||
C.dup(b);
|
||||
C.eq();
|
||||
C.dup(a+1);
|
||||
C.dup(a+1);
|
||||
C.and();
|
||||
}
|
||||
|
||||
function rm(a) {
|
||||
if (a>0) C.swap(a);
|
||||
C.pop();
|
||||
if (a>0) C.swap(a);
|
||||
C.pop();
|
||||
}
|
||||
|
||||
function double() {
|
||||
C.label("double"); // xR, xI, yR, yI, zR zI, q
|
||||
|
||||
C.dup(4);
|
||||
C.iszero();
|
||||
C.dup(6);
|
||||
C.iszero();
|
||||
C.and();
|
||||
C.jumpi("enddouble"); // X Y Z q
|
||||
|
||||
|
||||
// Z3 = 2*Y*Z // Remove Z
|
||||
mul(2, 4, 6); // yz X Y Z q
|
||||
rm(6); // X Y yz q
|
||||
|
||||
add(4, 4, 6); // 2yz X Y yz q
|
||||
rm(6); // X Y Z3 q
|
||||
|
||||
// A = X^2
|
||||
square(0,6); // A X Y Z3 q
|
||||
|
||||
// B = Y^2 // Remove Y
|
||||
square(4,8); // B A X Y Z3 q
|
||||
rm(6); // A X B Z3 q
|
||||
|
||||
// C = B^2
|
||||
square(4,8); // C A X B Z3 q
|
||||
|
||||
// D = (X+B)^2-A-C // Remove X, Remove B
|
||||
add(4,6, 10); // X+B C A X B Z3 q
|
||||
rm(6); // C A X+B B Z3 q
|
||||
rm(6); // A X+B C Z3 q
|
||||
square(2,8); // (X+B)^2 A X+B C Z3 q
|
||||
rm(4); // A (X+B)^2 C Z3 q
|
||||
sub(2, 0, 8); // (X+B)^2-A A (X+B)^2 C Z3 q
|
||||
rm(4); // A (X+B)^2-A C Z3 q
|
||||
sub(2, 4, 8); // (X+B)^2-A-C A (X+B)^2-A C Z3 q
|
||||
rm(4); // A D C Z3 q
|
||||
|
||||
// D = D+D
|
||||
add(2,2, 8); // D+D A D C Z3 q
|
||||
rm(4); // A D C Z3 q
|
||||
|
||||
// E=A+A+A
|
||||
add(0, 0, 8); // 2A A D C Z3 q
|
||||
add(0, 2, 10); // 3A 2A A D C Z3 q
|
||||
rm(4); // 2A 3A D C Z3 q
|
||||
rm(0); // E D C Z3 q
|
||||
|
||||
// F=E^2
|
||||
square(0, 8); // F E D C Z3 q
|
||||
|
||||
// X3= F - 2*D // Remove F
|
||||
add(4, 4, 10); // 2D F E D C Z3 q
|
||||
sub(2, 0, 12); // F-2D 2D F E D C Z3 q
|
||||
rm(4); // 2D X3 E D C Z3 q
|
||||
rm(0); // X3 E D C Z3 q
|
||||
|
||||
// Y3 = E * (D - X3) - 8 * C // Remove D C E
|
||||
|
||||
sub(4, 0, 10); // D-X3 X3 E D C Z3 q
|
||||
rm(6); // X3 E D-X3 C Z3 q
|
||||
mul(2, 4, 10); // E*(D-X3) X3 E D-X3 C Z3 q
|
||||
rm(6); // X3 E E*(D-X3) C Z3 q
|
||||
rm(2); // X3 E*(D-X3) C Z3 q
|
||||
add(4, 4, 8); // 2C X3 E*(D-X3) C Z3 q
|
||||
rm(6); // X3 E*(D-X3) 2C Z3 q
|
||||
add(4, 4, 8); // 4C X3 E*(D-X3) 2C Z3 q
|
||||
rm(6); // X3 E*(D-X3) 4C Z3 q
|
||||
add(4, 4, 8); // 8C X3 E*(D-X3) 4C Z3 q
|
||||
rm(6); // X3 E*(D-X3) 8C Z3 q
|
||||
sub(2, 4, 8); // E*(D-X3)-8C X3 E*(D-X3) 8C Z3 q
|
||||
rm(6); // X3 E*(D-X3) Y3 Z3 q
|
||||
rm(2); // X3 Y3 Z3 q
|
||||
|
||||
C.label("enddouble");
|
||||
C.returnCall();
|
||||
}
|
||||
|
||||
function addPoint() { // p, xR, xI, yR, yI, zR zI, q
|
||||
|
||||
|
||||
C.dup(0); // p p X2 Y2 Z2 q
|
||||
|
||||
C.push(savedP);
|
||||
C.mstore();
|
||||
|
||||
C.iszero(); // X2 Y2 Z2 q
|
||||
C.jumpi("endpadd");
|
||||
|
||||
|
||||
C.dup(4);
|
||||
C.iszero();
|
||||
C.dup(6);
|
||||
C.iszero();
|
||||
C.and();
|
||||
C.jumpi("returnP"); // X2 Y2 Z2 q
|
||||
|
||||
|
||||
|
||||
// lastZ3 = (Z2+1)^2 - Z2^2
|
||||
add1(4, 6); // Z2+1 X2 Y2 Z2 q
|
||||
square(0, 8); // (Z2+1)^2 Z2+1 X2 Y2 Z2 q
|
||||
rm(2); // (Z2+1)^2 X2 Y2 Z2 q
|
||||
square(6, 8); // Z2^2 (Z2+1)^2 X2 Y2 Z2 q
|
||||
|
||||
|
||||
sub(2, 0, 10); // (Z2+1)^2-Z2^2 Z2^2 (Z2+1)^2 X2 Y2 Z2 q
|
||||
|
||||
saveZ3(); // Z2^2 (Z2+1)^2 X2 Y2 Z2 q
|
||||
rm(2); // Z2^2 X2 Y2 Z2 q
|
||||
|
||||
// U2 = X2
|
||||
// S2 = Y2 // Z2^2 U2 S2 Z2 q
|
||||
|
||||
|
||||
// U1 = X1 * Z2^2
|
||||
loadX(); // X1 Z2^2 U2 S2 Z2 q
|
||||
mul(0, 2, 10); // X1*Z2^2 X1 Z2^2 U2 S2 Z2 q
|
||||
rm(2); // X1*Z2^2 Z2^2 U2 S2 Z2 q
|
||||
|
||||
|
||||
mul(2, 8, 10); // Z2^3 U1 Z2^2 U2 S2 Z2 q
|
||||
rm(4); // U1 Z2^3 U2 S2 Z2 q
|
||||
rm(8); // Z2^3 U2 S2 U1 q
|
||||
|
||||
// S1 = Y1 * Z1^3
|
||||
loadY(); // Y1 Z2^3 U2 S2 U1 q
|
||||
mul(0, 2, 10); // S1 Y1 Z2^3 U2 S2 U1 q
|
||||
rm(4); // Y1 S1 U2 S2 U1 q
|
||||
rm(0); // S1 U2 S2 U1 q
|
||||
|
||||
cmp(0, 4); // c1 S1 U2 S2 U1 q
|
||||
cmp(3, 7); // c2 c1 S1 U2 S2 U1 q
|
||||
C.and(); // c2&c1 S1 U2 S2 U1 q
|
||||
C.jumpi("double1"); // S1 U2 S2 U1 q
|
||||
|
||||
|
||||
// Returns the double
|
||||
|
||||
// H = U2-U1 // Remove U2
|
||||
C.sub(4, 8, 10); // H S1 U2 S2 U1 q
|
||||
rm(4); // S1 H S2 U1 q
|
||||
|
||||
// // r = 2 * (S2-S1) // Remove S2
|
||||
C.sub(4, 4, 8); // S1-S2 S1 H S2 U1 q
|
||||
rm(6); // S1 H S1-S2 U1 q
|
||||
C.add(4, 4, 8); // 2*(S1-S2) S1 H S1-S2 U1 q
|
||||
rm(6); // S1 H r U1 q
|
||||
|
||||
// I = (2 * H)^2
|
||||
C.add(2, 2, 8); // 2*H S1 H r U1 q
|
||||
C.square(0, 10); // (2*H)^2 2*H S1 H r U1 q
|
||||
rm(2); // I S1 H r U1 q
|
||||
|
||||
// V = U1 * I
|
||||
mul(8, 0, 10); // V I S1 H r U1 q
|
||||
rm(10); // I S1 H r V q
|
||||
|
||||
// J = H * I // Remove I
|
||||
mul(4, 0, 10); // J I S1 H r V q
|
||||
rm(2); // J S1 H r V q
|
||||
|
||||
// X3 = r^2 - J - 2 * V
|
||||
|
||||
// S1J2 = (S1*J)*2 // Remove S1
|
||||
mul(2, 0, 10); // S1*J J S1 H r V q
|
||||
rm(4); // J S1*J H r V q
|
||||
add(2,2, 10); // (S1*J)*2 J S1*J H r V q
|
||||
rm(4); // J S1J2 H r V q
|
||||
|
||||
// X3 = r^2 - J - 2 * V
|
||||
square(6, 10); // r^2 J S1J2 H r V q
|
||||
sub(0, 2, 12); // r^2-J r^2 J S1J2 H r V q
|
||||
rm(2); // r^2-J J S1J2 H r V q
|
||||
rm(2); // r^2-J S1J2 H r V q
|
||||
add(8, 8, 10); // 2*V r^2-J S1J2 H r V q
|
||||
sub(2, 0, 12); // r^2-J-2*V 2*V r^2-J S1J2 H r V q
|
||||
rm(4); // 2*V X3 S1J2 H r V q
|
||||
rm(0); // X3 S1J2 H r V q
|
||||
|
||||
// Y3 = r * (V-X3)-S1J2
|
||||
|
||||
sub(8, 0, 10); // V-X3 X3 S1J2 H r V q
|
||||
rm(10); // X3 S1J2 H r V-X3 q
|
||||
mul(6, 8, 10); // r*(V-X3) X3 S1J2 H r V-X3 q
|
||||
rm(8); // X3 S1J2 H r*(V-X3) V-X3 q
|
||||
rm(8); // S1J2 H r*(V-X3) X3 q
|
||||
sub(4, 0, 8); // Y3 S1J2 H r*(V-X3) X3 q
|
||||
rm(6); // S1J2 H Y3 X3 q
|
||||
rm(0); // H Y3 X3 q
|
||||
|
||||
// Z3 = lastZ * H
|
||||
loadZ3(); // lastZ3 H Y3 X3 q
|
||||
mul(0, 2, 8); // Z3 lastZ3 H Y3 X3 q
|
||||
rm(4); // lastZ3 Z3 Y3 X3 q
|
||||
rm(0); // Z3 Y3 X3 q
|
||||
|
||||
C.swap(1);
|
||||
C.swap(5);
|
||||
C.swap(1);
|
||||
C.swap(4); // X3 Y3 Z3 q
|
||||
|
||||
// returns the point in memory
|
||||
C.label("returnP"); // X Y Z q
|
||||
rm(0);
|
||||
rm(0);
|
||||
rm(0);
|
||||
C.push(0);
|
||||
C.push(1);
|
||||
loadX();
|
||||
loadY();
|
||||
C.jump("endpadd");
|
||||
|
||||
C.label("double1"); // S1 U2 S2 U1 q
|
||||
rm(0);
|
||||
rm(0);
|
||||
rm(0);
|
||||
rm(0);
|
||||
C.push(0);
|
||||
C.push(1);
|
||||
loadX();
|
||||
loadY();
|
||||
C.jump("double");
|
||||
|
||||
C.label("endpadd");
|
||||
C.returnCall();
|
||||
|
||||
function loadX() {
|
||||
C.push(savedP);
|
||||
C.mload(); // p
|
||||
C.push(32);
|
||||
C.mul(); // P*32
|
||||
C.push(VAR_POINTS+32);
|
||||
C.add(); // P*32+32
|
||||
C.dup(); // P*32+32 P*32+32
|
||||
C.mload(); // im P*32+32
|
||||
C.swap(1); // P*32+32 im
|
||||
C.push(0x20); // 32 P*32+32 im
|
||||
C.sub(); // P*32 im
|
||||
C.mload(); // re im
|
||||
}
|
||||
|
||||
function loadY() {
|
||||
C.push(savedP);
|
||||
C.mload(); // p
|
||||
C.push(32);
|
||||
C.mul(); // P*32
|
||||
C.push(VAR_POINTS+32*3);
|
||||
C.add(); // P*32+32
|
||||
C.dup(); // P*32+32 P*32+32
|
||||
C.mload(); // im P*32+32
|
||||
C.swap(1); // P*32+32 im
|
||||
C.push(0x20); // 32 P*32+32 im
|
||||
C.sub(); // P*32 im
|
||||
C.mload(); // re im
|
||||
}
|
||||
|
||||
function loadZ3() {
|
||||
C.push(savedZ3+32);
|
||||
C.mload(); // p
|
||||
C.push(savedZ3);
|
||||
C.mload();
|
||||
}
|
||||
|
||||
function saveZ3() {
|
||||
C.push(savedZ3);
|
||||
C.mstore();
|
||||
C.push(savedZ3+32);
|
||||
C.mstore();
|
||||
}
|
||||
}
|
||||
|
||||
function affine() { // X Y Z q
|
||||
// If Z2=0 return 0
|
||||
C.label("affine");
|
||||
C.dup(4);
|
||||
C.dup(5 + 1);
|
||||
C.or();
|
||||
C.jumpi("notZero"); // X Y Z q
|
||||
rm(0);
|
||||
rm(0);
|
||||
C.push(0);
|
||||
C.push(0);
|
||||
|
||||
C.jmp("endAffine");
|
||||
C.label("notZero");
|
||||
|
||||
inverse2(4,6); // Z_inv X Y Z q
|
||||
square(2, 8); // Z2_inv Z_inv X Y Z q
|
||||
mul(0, 2, 10); // Z3_inv Z2_inv Z_inv X Y Z q
|
||||
rm(4); // Z2_inv Z3_inv X Y Z q
|
||||
C.push(1);
|
||||
C.push(0); // 1 Z2_inv Z3_inv X Y Z q
|
||||
rm(10); // Z2_inv Z3_inv X Y 1 q
|
||||
mul(2, 6, 10); // YI Z2_inv Z3_inv X Y 1 q
|
||||
rm(8); // Z2_inv Z3_inv X YI 1 q
|
||||
mul(0, 4, 10); // XI Z2_inv Z3_inv X YI 1 q
|
||||
rm(6); // Z2_inv Z3_inv XI YI 1 q
|
||||
rm(0); // Z3_inv XI YI 1 q
|
||||
rm(0); // XI YI 1 q
|
||||
C.label("endAffine");
|
||||
C.returnCall();
|
||||
}
|
||||
|
||||
function inverse2(a, q) {
|
||||
C.dup(q); // q
|
||||
C.dup(q + 1); // q q
|
||||
C.push(2); // 2 q q
|
||||
C.sub(); // q-2 q
|
||||
C.dup(q + 2); // q q-2 q
|
||||
C.dup(q + 3); // q q q-2 q
|
||||
C.dup(a + 4); // ar q q q-2 q
|
||||
C.dup(a + 5); // ar ar q q q-2 q
|
||||
C.mulmod(); // t0 q q-2 q
|
||||
|
||||
C.dup(q + 4); // q t0 q q-2 q
|
||||
C.dup(a+1 + 5); // ai q t0 q q-2 q
|
||||
C.dup(a+1 + 6); // ai ai q t0 q q-2 q
|
||||
C.mulmod(); // t1 t0 q q-2 q
|
||||
|
||||
C.addmod(); // t2 q-2 q
|
||||
C.expmod(); // t3
|
||||
|
||||
C.dup(q + 1); // q t3
|
||||
C.dup(q + 2); // q q t3
|
||||
C.dup(q + 3); // q q q t3
|
||||
C.dup(1); // t3 q q q t3
|
||||
C.sub(); // -t3 q q t3
|
||||
C.dup(a+1 + 3); // ai -t3 q q t3
|
||||
C.mulmod(); // ii q t3
|
||||
C.swap(2); // t3 q ii
|
||||
C.dup(a + 3); // ar t3 q ii
|
||||
C.mulmod(); // ir ii
|
||||
}
|
||||
|
||||
function storeVals() {
|
||||
C.push(VAR_POINTS); // p
|
||||
for (let i=0; i<NPOINTS; i++) {
|
||||
const MP = G2.affine(G2.mulScalar(P, bigInt(i)));
|
||||
for (let j=0; j<2; j++) {
|
||||
for (let k=0; k<2; k++) {
|
||||
C.push(toHex256(MP[j][k])); // MP[0][0] p
|
||||
C.dup(1); // p MP[0][0] p
|
||||
C.mstore(); // p
|
||||
C.push(32); // 32 p
|
||||
C.add(); // p+32
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports.abi = [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "escalar",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "mulexp",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "pure",
|
||||
"type": "function"
|
||||
}
|
||||
];
|
||||
|
||||
module.exports.createCode = createCode;
|
64
@tornado/circomlib/src/mimc7.js
Normal file
64
@tornado/circomlib/src/mimc7.js
Normal file
@ -0,0 +1,64 @@
|
||||
const bn128 = require("@tornado/snarkjs").bn128;
|
||||
const bigInt = require("@tornado/snarkjs").bigInt;
|
||||
const Web3Utils = require("web3-utils");
|
||||
const F = bn128.Fr;
|
||||
|
||||
const SEED = "mimc";
|
||||
const NROUNDS = 91;
|
||||
|
||||
exports.getIV = (seed) => {
|
||||
if (typeof seed === "undefined") seed = SEED;
|
||||
const c = Web3Utils.keccak256(seed+"_iv");
|
||||
const cn = bigInt(Web3Utils.toBN(c).toString());
|
||||
const iv = cn.mod(F.q);
|
||||
return iv;
|
||||
};
|
||||
|
||||
exports.getConstants = (seed, nRounds) => {
|
||||
if (typeof seed === "undefined") seed = SEED;
|
||||
if (typeof nRounds === "undefined") nRounds = NROUNDS;
|
||||
const cts = new Array(nRounds);
|
||||
let c = Web3Utils.keccak256(SEED);
|
||||
for (let i=1; i<nRounds; i++) {
|
||||
c = Web3Utils.keccak256(c);
|
||||
|
||||
const n1 = Web3Utils.toBN(c).mod(Web3Utils.toBN(F.q.toString()));
|
||||
const c2 = Web3Utils.padLeft(Web3Utils.toHex(n1), 64);
|
||||
cts[i] = bigInt(Web3Utils.toBN(c2).toString());
|
||||
}
|
||||
cts[0] = bigInt(0);
|
||||
return cts;
|
||||
};
|
||||
|
||||
const cts = exports.getConstants(SEED, 91);
|
||||
|
||||
exports.hash = (_x_in, _k) =>{
|
||||
const x_in = bigInt(_x_in);
|
||||
const k = bigInt(_k);
|
||||
let r;
|
||||
for (let i=0; i<NROUNDS; i++) {
|
||||
const c = cts[i];
|
||||
const t = (i==0) ? F.add(x_in, k) : F.add(F.add(r, k), c);
|
||||
r = F.exp(t, 7);
|
||||
}
|
||||
return F.affine(F.add(r, k));
|
||||
};
|
||||
|
||||
exports.multiHash = (arr, key) => {
|
||||
let r;
|
||||
if (typeof(key) === "undefined") {
|
||||
r = F.zero;
|
||||
} else {
|
||||
r = key;
|
||||
}
|
||||
for (let i=0; i<arr.length; i++) {
|
||||
r = F.add(
|
||||
F.add(
|
||||
r,
|
||||
arr[i]
|
||||
),
|
||||
exports.hash(bigInt(arr[i]), r)
|
||||
);
|
||||
}
|
||||
return F.affine(r);
|
||||
};
|
114
@tornado/circomlib/src/mimc_gencontract.js
Normal file
114
@tornado/circomlib/src/mimc_gencontract.js
Normal file
@ -0,0 +1,114 @@
|
||||
// Copyright (c) 2018 Jordi Baylina
|
||||
// License: LGPL-3.0+
|
||||
//
|
||||
|
||||
const Web3Utils = require("web3-utils");
|
||||
|
||||
const Contract = require("./evmasm");
|
||||
|
||||
function createCode(seed, n) {
|
||||
|
||||
let ci = Web3Utils.keccak256(seed);
|
||||
|
||||
const C = new Contract();
|
||||
|
||||
C.push(0x44);
|
||||
C.push("0x00");
|
||||
C.push("0x00");
|
||||
C.calldatacopy();
|
||||
C.push("0x0100000000000000000000000000000000000000000000000000000000");
|
||||
C.push("0x00");
|
||||
C.mload();
|
||||
C.div();
|
||||
C.push("0xd15ca109"); // MiMCpe7(uint256,uint256)
|
||||
// C.push("0x8c42199e"); // MiMCpe7(uint256,uint256,uint256)
|
||||
C.eq();
|
||||
C.jmpi("start");
|
||||
C.invalid();
|
||||
|
||||
C.label("start");
|
||||
C.push("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"); // q
|
||||
C.push("0x24");
|
||||
C.mload(); // k q
|
||||
|
||||
|
||||
C.dup(1); // q k q
|
||||
C.dup(0); // q q k q
|
||||
C.push("0x04");
|
||||
C.mload(); // x q q k q
|
||||
C.dup(3); // k x q q k q
|
||||
C.addmod(); // t=x+k q k q
|
||||
C.dup(1); // q t q k q
|
||||
C.dup(0); // q q t q k q
|
||||
C.dup(2); // t q q t q k q
|
||||
C.dup(0); // t t q q t q k q
|
||||
C.mulmod(); // a=t^2 q t q k q
|
||||
C.dup(1); // q a q t q k q
|
||||
C.dup(1); // a q a q t q k q
|
||||
C.dup(0); // a a q a q t q k q
|
||||
C.mulmod(); // b=t^4 a q t q k q
|
||||
C.mulmod(); // c=t^6 t q k q
|
||||
C.mulmod(); // r=t^7 k q
|
||||
|
||||
for (let i=0; i<n-1; i++) {
|
||||
ci = Web3Utils.keccak256(ci);
|
||||
C.dup(2); // q r k q
|
||||
C.dup(0); // q q r k q
|
||||
C.dup(0); // q q q r k q
|
||||
C.swap(3); // r q q q k q
|
||||
C.push(ci); // c r q q k q
|
||||
C.addmod(); // s=c+r q q k q
|
||||
C.dup(3); // k s q q k q
|
||||
C.addmod(); // t=s+k q k q
|
||||
C.dup(1); // q t q k q
|
||||
C.dup(0); // q q t q k q
|
||||
C.dup(2); // t q q t q k q
|
||||
C.dup(0); // t t q q t q k q
|
||||
C.mulmod(); // a=t^2 q t q k q
|
||||
C.dup(1); // q a q t q k q
|
||||
C.dup(1); // a q a q t q k q
|
||||
C.dup(0); // a a q a q t q k q
|
||||
C.mulmod(); // b=t^4 a q t q k q
|
||||
C.mulmod(); // c=t^6 t q k q
|
||||
C.mulmod(); // r=t^7 k q
|
||||
}
|
||||
|
||||
C.addmod(); // res=t^7+k
|
||||
C.push("0x00");
|
||||
C.mstore(); // Save it to pos 0;
|
||||
C.push("0x20");
|
||||
C.push("0x00");
|
||||
C.return();
|
||||
|
||||
return C.createTxData();
|
||||
}
|
||||
|
||||
module.exports.abi = [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "in_x",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "in_k",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "MiMCpe7",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "out_x",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "pure",
|
||||
"type": "function"
|
||||
}
|
||||
];
|
||||
|
||||
module.exports.createCode = createCode;
|
||||
|
||||
|
3
@tornado/circomlib/src/mimc_print_iv.js
Normal file
3
@tornado/circomlib/src/mimc_print_iv.js
Normal file
@ -0,0 +1,3 @@
|
||||
const mimc7 = require("./mimc7.js");
|
||||
|
||||
console.log("IV: "+mimc7.getIV().toString());
|
13
@tornado/circomlib/src/mimc_printconstants.js
Normal file
13
@tornado/circomlib/src/mimc_printconstants.js
Normal file
@ -0,0 +1,13 @@
|
||||
const mimc7 = require("./mimc7.js");
|
||||
|
||||
const nRounds = 91;
|
||||
let S = "[\n";
|
||||
const cts = mimc7.getConstants();
|
||||
for (let i=0; i<nRounds; i++) {
|
||||
S = S + cts[i].toString();
|
||||
if (i<nRounds-1) S = S + ",";
|
||||
S=S+"\n";
|
||||
}
|
||||
S = S + "]\n";
|
||||
|
||||
console.log(S);
|
13
@tornado/circomlib/src/mimc_printcontract.js
Normal file
13
@tornado/circomlib/src/mimc_printcontract.js
Normal file
@ -0,0 +1,13 @@
|
||||
const mimcGenContract = require("./mimc_gencontract");
|
||||
|
||||
const SEED = "mimc";
|
||||
|
||||
let nRounds;
|
||||
if (typeof process.argv[2] != "undefined") {
|
||||
nRounds = parseInt(process.argv[2]);
|
||||
} else {
|
||||
nRounds = 91;
|
||||
}
|
||||
|
||||
console.log(mimcGenContract.createCode(SEED, nRounds));
|
||||
|
86
@tornado/circomlib/src/mimcsponge.js
Normal file
86
@tornado/circomlib/src/mimcsponge.js
Normal file
@ -0,0 +1,86 @@
|
||||
const bn128 = require("@tornado/snarkjs").bn128;
|
||||
const bigInt = require("@tornado/snarkjs").bigInt;
|
||||
const Web3Utils = require("web3-utils");
|
||||
const F = bn128.Fr;
|
||||
|
||||
const SEED = "mimcsponge";
|
||||
const NROUNDS = 220;
|
||||
|
||||
exports.getIV = (seed) => {
|
||||
if (typeof seed === "undefined") seed = SEED;
|
||||
const c = Web3Utils.keccak256(seed+"_iv");
|
||||
const cn = bigInt(Web3Utils.toBN(c).toString());
|
||||
const iv = cn.mod(F.q);
|
||||
return iv;
|
||||
};
|
||||
|
||||
exports.getConstants = (seed, nRounds) => {
|
||||
if (typeof seed === "undefined") seed = SEED;
|
||||
if (typeof nRounds === "undefined") nRounds = NROUNDS;
|
||||
const cts = new Array(nRounds);
|
||||
let c = Web3Utils.keccak256(SEED);
|
||||
for (let i=1; i<nRounds; i++) {
|
||||
c = Web3Utils.keccak256(c);
|
||||
|
||||
const n1 = Web3Utils.toBN(c).mod(Web3Utils.toBN(F.q.toString()));
|
||||
const c2 = Web3Utils.padLeft(Web3Utils.toHex(n1), 64);
|
||||
cts[i] = bigInt(Web3Utils.toBN(c2).toString());
|
||||
}
|
||||
cts[0] = bigInt(0);
|
||||
cts[cts.length - 1] = bigInt(0);
|
||||
return cts;
|
||||
};
|
||||
|
||||
const cts = exports.getConstants(SEED, NROUNDS);
|
||||
|
||||
exports.hash = (_xL_in, _xR_in, _k) =>{
|
||||
let xL = bigInt(_xL_in);
|
||||
let xR = bigInt(_xR_in);
|
||||
const k = bigInt(_k);
|
||||
for (let i=0; i<NROUNDS; i++) {
|
||||
const c = cts[i];
|
||||
const t = (i==0) ? F.add(xL, k) : F.add(F.add(xL, k), c);
|
||||
const xR_tmp = bigInt(xR);
|
||||
if (i < (NROUNDS - 1)) {
|
||||
xR = xL;
|
||||
xL = F.add(xR_tmp, F.exp(t, 5));
|
||||
} else {
|
||||
xR = F.add(xR_tmp, F.exp(t, 5));
|
||||
}
|
||||
}
|
||||
return {
|
||||
xL: F.affine(xL),
|
||||
xR: F.affine(xR),
|
||||
};
|
||||
};
|
||||
|
||||
exports.multiHash = (arr, key, numOutputs) => {
|
||||
if (typeof(numOutputs) === "undefined") {
|
||||
numOutputs = 1;
|
||||
}
|
||||
if (typeof(key) === "undefined") {
|
||||
key = F.zero;
|
||||
}
|
||||
|
||||
let R = F.zero;
|
||||
let C = F.zero;
|
||||
|
||||
for (let i=0; i<arr.length; i++) {
|
||||
R = F.add(R, bigInt(arr[i]));
|
||||
const S = exports.hash(R, C, key);
|
||||
R = S.xL;
|
||||
C = S.xR;
|
||||
}
|
||||
let outputs = [R];
|
||||
for (let i=1; i < numOutputs; i++) {
|
||||
const S = exports.hash(R, C, key);
|
||||
R = S.xL;
|
||||
C = S.xR;
|
||||
outputs.push(R);
|
||||
}
|
||||
if (numOutputs == 1) {
|
||||
return F.affine(outputs[0]);
|
||||
} else {
|
||||
return outputs.map(x => F.affine(x));
|
||||
}
|
||||
};
|
116
@tornado/circomlib/src/mimcsponge_gencontract.js
Normal file
116
@tornado/circomlib/src/mimcsponge_gencontract.js
Normal file
@ -0,0 +1,116 @@
|
||||
// Copyright (c) 2018 Jordi Baylina
|
||||
// License: LGPL-3.0+
|
||||
//
|
||||
|
||||
const Web3Utils = require("web3-utils");
|
||||
|
||||
const Contract = require("./evmasm");
|
||||
|
||||
function createCode(seed, n) {
|
||||
|
||||
let ci = Web3Utils.keccak256(seed);
|
||||
|
||||
const C = new Contract();
|
||||
|
||||
C.push(0x64);
|
||||
C.push("0x00");
|
||||
C.push("0x00");
|
||||
C.calldatacopy();
|
||||
C.push("0x0100000000000000000000000000000000000000000000000000000000");
|
||||
C.push("0x00");
|
||||
C.mload();
|
||||
C.div();
|
||||
C.push("0xf47d33b5"); // MiMCSponge(uint256,uint256)
|
||||
C.eq();
|
||||
C.jmpi("start");
|
||||
C.invalid();
|
||||
|
||||
C.label("start");
|
||||
C.push("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"); // q
|
||||
C.push("0x04");
|
||||
C.mload(); // xL q
|
||||
C.dup(1); // q xL q
|
||||
C.push("0x24");
|
||||
C.mload(); // xR q xL q
|
||||
C.dup(1); // q xR q xL q
|
||||
C.dup(3); // xL q xR q xL q
|
||||
C.dup(1); // q xL q xR q xL q
|
||||
C.dup(0); // q q xL q xR q xL q
|
||||
C.dup(2); // xL q q xL q xR q xL q
|
||||
C.dup(0); // xL xL q q xL q xR q xL q
|
||||
C.mulmod(); // b=xL^2 q xL q xR q xL q
|
||||
C.dup(0); // b b q xL q xR q xL q
|
||||
C.mulmod(); // c=xL^4 xL q xR q xL q
|
||||
C.mulmod(); // d=xL^5 xR q xL q
|
||||
C.addmod(); // e=xL^5+xR xL q (for next round: xL xR q)
|
||||
|
||||
for (let i=0; i<n-1; i++) {
|
||||
if (i < n-2) {
|
||||
ci = Web3Utils.keccak256(ci);
|
||||
} else {
|
||||
ci = "0x00";
|
||||
}
|
||||
C.swap(1); // xR xL q
|
||||
C.dup(2); // q xR xL q
|
||||
C.dup(2); // xL q xR xL q
|
||||
C.push(ci); // ci xL q xR xL q
|
||||
C.addmod(); // a=ci+xL xR xL q
|
||||
C.dup(3); // q a xR xL q
|
||||
C.swap(1); // a q xR xL q
|
||||
C.dup(1); // q a q xR xL q
|
||||
C.dup(0); // q q a q xR xL q
|
||||
C.dup(2); // a q q a q xR xL q
|
||||
C.dup(0); // a a q q a q xR xL q
|
||||
C.mulmod(); // b=a^2 q a q xR xL q
|
||||
C.dup(0); // b b q a q xR xL q
|
||||
C.mulmod(); // c=a^4 a q xR xL q
|
||||
C.mulmod(); // d=a^5 xR xL q
|
||||
C.dup(3); // q d xR xL q
|
||||
C.swap(2); // xR d q xL q
|
||||
C.addmod(); // e=a^5+xR xL q (for next round: xL xR q)
|
||||
}
|
||||
|
||||
C.push("0x20");
|
||||
C.mstore(); // Save it to pos 0;
|
||||
C.push("0x00");
|
||||
C.mstore(); // Save it to pos 1;
|
||||
C.push("0x40");
|
||||
C.push("0x00");
|
||||
C.return();
|
||||
|
||||
return C.createTxData();
|
||||
}
|
||||
|
||||
module.exports.abi = [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "xL_in",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "xR_in",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "MiMCSponge",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "xL",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"name": "xR",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "pure",
|
||||
"type": "function"
|
||||
}
|
||||
];
|
||||
|
||||
module.exports.createCode = createCode;
|
||||
|
||||
|
13
@tornado/circomlib/src/mimcsponge_printconstants.js
Normal file
13
@tornado/circomlib/src/mimcsponge_printconstants.js
Normal file
@ -0,0 +1,13 @@
|
||||
const mimcsponge = require("./mimcsponge.js");
|
||||
|
||||
const nRounds = 220;
|
||||
let S = "[\n";
|
||||
const cts = mimcsponge.getConstants();
|
||||
for (let i=0; i<nRounds; i++) {
|
||||
S = S + cts[i].toString();
|
||||
if (i<nRounds-1) S = S + ",";
|
||||
S=S+"\n";
|
||||
}
|
||||
S = S + "]\n";
|
||||
|
||||
console.log(S);
|
13
@tornado/circomlib/src/mimcsponge_printcontract.js
Normal file
13
@tornado/circomlib/src/mimcsponge_printcontract.js
Normal file
@ -0,0 +1,13 @@
|
||||
const mimcGenContract = require("./mimcsponge_gencontract");
|
||||
|
||||
const SEED = "mimcsponge";
|
||||
|
||||
let nRounds;
|
||||
if (typeof process.argv[2] != "undefined") {
|
||||
nRounds = parseInt(process.argv[2]);
|
||||
} else {
|
||||
nRounds = 220;
|
||||
}
|
||||
|
||||
console.log(mimcGenContract.createCode(SEED, nRounds));
|
||||
|
111
@tornado/circomlib/src/pedersenHash.js
Normal file
111
@tornado/circomlib/src/pedersenHash.js
Normal file
@ -0,0 +1,111 @@
|
||||
const bn128 = require("@tornado/snarkjs").bn128;
|
||||
const bigInt = require("@tornado/snarkjs").bigInt;
|
||||
const babyJub = require("./babyjub");
|
||||
const createBlakeHash = require("blake-hash");
|
||||
|
||||
const GENPOINT_PREFIX = "PedersenGenerator";
|
||||
const windowSize = 4;
|
||||
const nWindowsPerSegment = 50;
|
||||
|
||||
exports.hash = pedersenHash;
|
||||
exports.getBasePoint = getBasePoint;
|
||||
|
||||
function pedersenHash(msg) {
|
||||
const bitsPerSegment = windowSize*nWindowsPerSegment;
|
||||
const bits = buffer2bits(msg);
|
||||
|
||||
const nSegments = Math.floor((bits.length - 1)/(windowSize*nWindowsPerSegment)) +1;
|
||||
|
||||
let accP = [bigInt.zero,bigInt.one];
|
||||
|
||||
for (let s=0; s<nSegments; s++) {
|
||||
let nWindows;
|
||||
if (s == nSegments-1) {
|
||||
nWindows = Math.floor(((bits.length - (nSegments - 1)*bitsPerSegment) - 1) / windowSize) +1;
|
||||
} else {
|
||||
nWindows = nWindowsPerSegment;
|
||||
}
|
||||
let escalar = bigInt.zero;
|
||||
let exp = bigInt.one;
|
||||
for (let w=0; w<nWindows; w++) {
|
||||
let o = s*bitsPerSegment + w*windowSize;
|
||||
let acc = bigInt.one;
|
||||
for (let b=0; ((b<windowSize-1)&&(o<bits.length)) ; b++) {
|
||||
if (bits[o]) {
|
||||
acc = acc.add( bigInt.one.shl(b) );
|
||||
}
|
||||
o++;
|
||||
}
|
||||
if (o<bits.length) {
|
||||
if (bits[o]) {
|
||||
acc = acc.neg();
|
||||
}
|
||||
o++;
|
||||
}
|
||||
escalar = escalar.add(acc.mul(exp));
|
||||
exp = exp.shl(windowSize+1);
|
||||
}
|
||||
|
||||
if (escalar.lesser(bigInt.zero)) {
|
||||
escalar = babyJub.subOrder.add(escalar);
|
||||
}
|
||||
|
||||
accP = babyJub.addPoint(accP, babyJub.mulPointEscalar(getBasePoint(s), escalar));
|
||||
}
|
||||
|
||||
return babyJub.packPoint(accP);
|
||||
}
|
||||
|
||||
let bases = [];
|
||||
|
||||
function getBasePoint(pointIdx) {
|
||||
if (pointIdx<bases.length) return bases[pointIdx];
|
||||
let p= null;
|
||||
let tryIdx = 0;
|
||||
while (p==null) {
|
||||
const S = GENPOINT_PREFIX + "_" + padLeftZeros(pointIdx, 32) + "_" + padLeftZeros(tryIdx, 32);
|
||||
const h = createBlakeHash("blake256").update(S).digest();
|
||||
h[31] = h[31] & 0xBF; // Set 255th bit to 0 (256th is the signal and 254th is the last possible bit to 1)
|
||||
p = babyJub.unpackPoint(h);
|
||||
tryIdx++;
|
||||
}
|
||||
|
||||
const p8 = babyJub.mulPointEscalar(p, 8);
|
||||
|
||||
if (!babyJub.inSubgroup(p8)) {
|
||||
throw new Error("Point not in curve");
|
||||
}
|
||||
|
||||
bases[pointIdx] = p8;
|
||||
return p8;
|
||||
}
|
||||
|
||||
function padLeftZeros(idx, n) {
|
||||
let sidx = "" + idx;
|
||||
while (sidx.length<n) sidx = "0"+sidx;
|
||||
return sidx;
|
||||
}
|
||||
|
||||
/*
|
||||
Input a buffer
|
||||
Returns an array of booleans. 0 is LSB of first byte and so on.
|
||||
*/
|
||||
function buffer2bits(buff) {
|
||||
const res = new Array(buff.length*8);
|
||||
for (let i=0; i<buff.length; i++) {
|
||||
const b = buff[i];
|
||||
res[i*8] = b & 0x01;
|
||||
res[i*8+1] = b & 0x02;
|
||||
res[i*8+2] = b & 0x04;
|
||||
res[i*8+3] = b & 0x08;
|
||||
res[i*8+4] = b & 0x10;
|
||||
res[i*8+5] = b & 0x20;
|
||||
res[i*8+6] = b & 0x40;
|
||||
res[i*8+7] = b & 0x80;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
13
@tornado/circomlib/src/pedersen_printbases.js
Normal file
13
@tornado/circomlib/src/pedersen_printbases.js
Normal file
@ -0,0 +1,13 @@
|
||||
const pedersenHash = require("./pedersenHash.js");
|
||||
|
||||
let nBases;
|
||||
if (typeof process.argv[2] != "undefined") {
|
||||
nBases = parseInt(process.argv[2]);
|
||||
} else {
|
||||
nBases = 5;
|
||||
}
|
||||
|
||||
for (let i=0; i < nBases; i++) {
|
||||
const p = pedersenHash.getBasePoint(i);
|
||||
console.log(`[${p[0]},${p[1]}]`);
|
||||
}
|
116
@tornado/circomlib/src/poseidon.js
Normal file
116
@tornado/circomlib/src/poseidon.js
Normal file
@ -0,0 +1,116 @@
|
||||
const bn128 = require("@tornado/snarkjs").bn128;
|
||||
const bigInt = require("@tornado/snarkjs").bigInt;
|
||||
const blake2b = require('blake2b');
|
||||
const assert = require("assert");
|
||||
const F = bn128.Fr;
|
||||
|
||||
const SEED = "poseidon";
|
||||
const NROUNDSF = 8;
|
||||
const NROUNDSP = 57;
|
||||
const T = 6;
|
||||
|
||||
function getPseudoRandom(seed, n) {
|
||||
const res = [];
|
||||
let input = Buffer.from(seed);
|
||||
let h = blake2b(32).update(input).digest()
|
||||
while (res.length<n) {
|
||||
const n = F.affine(bigInt.leBuff2int(h));
|
||||
res.push(n);
|
||||
h = blake2b(32).update(h).digest()
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
function allDifferent(v) {
|
||||
for (let i=0; i<v.length; i++) {
|
||||
if (v[i].isZero()) return false;
|
||||
for (let j=i+1; j<v.length; j++) {
|
||||
if (v[i].equals(v[j])) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
exports.getMatrix = (t, seed, nRounds) => {
|
||||
if (typeof seed === "undefined") seed = SEED;
|
||||
if (typeof nRounds === "undefined") nRounds = NROUNDSF + NROUNDSP;
|
||||
if (typeof t === "undefined") t = T;
|
||||
let nonce = "0000";
|
||||
let cmatrix = getPseudoRandom(seed+"_matrix_"+nonce, t*2);
|
||||
while (!allDifferent(cmatrix)) {
|
||||
nonce = (Number(nonce)+1)+"";
|
||||
while(nonce.length<4) nonce = "0"+nonce;
|
||||
cmatrix = getPseudoRandom(seed+"_matrix_"+nonce, t*2);
|
||||
}
|
||||
|
||||
const M = new Array(t);
|
||||
for (let i=0; i<t; i++) {
|
||||
M[i] = new Array(t);
|
||||
for (let j=0; j<t; j++) {
|
||||
M[i][j] = F.affine(F.inverse(F.sub(cmatrix[i], cmatrix[t+j])));
|
||||
}
|
||||
}
|
||||
return M;
|
||||
};
|
||||
|
||||
exports.getConstants = (t, seed, nRounds) => {
|
||||
if (typeof seed === "undefined") seed = SEED;
|
||||
if (typeof nRounds === "undefined") nRounds = NROUNDSF + NROUNDSP;
|
||||
if (typeof t === "undefined") t = T;
|
||||
const cts = getPseudoRandom(seed+"_constants", nRounds);
|
||||
return cts;
|
||||
};
|
||||
|
||||
function ark(state, c) {
|
||||
for (let j=0; j<state.length; j++ ) {
|
||||
state[j] = F.add(state[j], c);
|
||||
}
|
||||
}
|
||||
|
||||
function sigma(a) {
|
||||
return F.mul(a, F.square(F.square(a,a)));
|
||||
}
|
||||
|
||||
function mix(state, M) {
|
||||
const newState = new Array(state.length);
|
||||
for (let i=0; i<state.length; i++) {
|
||||
newState[i] = F.zero;
|
||||
for (let j=0; j<state.length; j++) {
|
||||
newState[i] = F.add(newState[i], F.mul(M[i][j], state[j]) );
|
||||
}
|
||||
}
|
||||
for (let i=0; i<state.length; i++) state[i] = newState[i];
|
||||
}
|
||||
|
||||
exports.createHash = (t, nRoundsF, nRoundsP, seed) => {
|
||||
|
||||
if (typeof seed === "undefined") seed = SEED;
|
||||
if (typeof nRoundsF === "undefined") nRoundsF = NROUNDSF;
|
||||
if (typeof nRoundsP === "undefined") nRoundsP = NROUNDSP;
|
||||
if (typeof t === "undefined") t = T;
|
||||
|
||||
assert(nRoundsF % 2 == 0);
|
||||
const C = exports.getConstants(t, seed, nRoundsF + nRoundsP);
|
||||
const M = exports.getMatrix(t, seed, nRoundsF + nRoundsP);
|
||||
return function(inputs) {
|
||||
let state = [];
|
||||
assert(inputs.length <= t);
|
||||
assert(inputs.length > 0);
|
||||
for (let i=0; i<inputs.length; i++) state[i] = bigInt(inputs[i]);
|
||||
for (let i=inputs.length; i<t; i++) state[i] = F.zero;
|
||||
|
||||
for (let i=0; i< nRoundsF + nRoundsP; i++) {
|
||||
ark(state, C[i]);
|
||||
if ((i<nRoundsF/2) || (i >= nRoundsF/2 + nRoundsP)) {
|
||||
for (let j=0; j<t; j++) state[j] = sigma(state[j]);
|
||||
} else {
|
||||
state[0] = sigma(state[0]);
|
||||
}
|
||||
mix(state, M);
|
||||
}
|
||||
return F.affine(state[0]);
|
||||
};
|
||||
};
|
||||
|
||||
|
180
@tornado/circomlib/src/poseidon_gencontract.js
Normal file
180
@tornado/circomlib/src/poseidon_gencontract.js
Normal file
@ -0,0 +1,180 @@
|
||||
// Copyright (c) 2018 Jordi Baylina
|
||||
// License: LGPL-3.0+
|
||||
//
|
||||
|
||||
const Poseidon = require("./poseidon.js");
|
||||
|
||||
const Contract = require("./evmasm");
|
||||
|
||||
const SEED = "poseidon";
|
||||
const NROUNDSF = 8;
|
||||
const NROUNDSP = 57;
|
||||
const T = 6;
|
||||
|
||||
function toHex256(a) {
|
||||
let S = a.toString(16);
|
||||
while (S.length < 64) S="0"+S;
|
||||
return "0x" + S;
|
||||
}
|
||||
|
||||
function createCode(t, nRoundsF, nRoundsP, seed) {
|
||||
if (typeof seed === "undefined") seed = SEED;
|
||||
if (typeof nRoundsF === "undefined") nRoundsF = NROUNDSF;
|
||||
if (typeof nRoundsP === "undefined") nRoundsP = NROUNDSP;
|
||||
if (typeof t === "undefined") t = T;
|
||||
|
||||
const K = Poseidon.getConstants(t, seed, nRoundsP + nRoundsF);
|
||||
const M = Poseidon.getMatrix(t, seed, nRoundsP + nRoundsF);
|
||||
|
||||
const C = new Contract();
|
||||
|
||||
function saveM() {
|
||||
for (let i=0; i<t; i++) {
|
||||
for (let j=0; j<t; j++) {
|
||||
C.push(toHex256(M[i][j]));
|
||||
C.push((1+i*t+j)*32);
|
||||
C.mstore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ark(r) {
|
||||
C.push(toHex256(K[r])); // K, st, q
|
||||
for (let i=0; i<t; i++) {
|
||||
C.dup(1+t); // q, K, st, q
|
||||
C.dup(1); // K, q, K, st, q
|
||||
C.dup(3+i); // st[i], K, q, K, st, q
|
||||
C.addmod(); // newSt[i], K, st, q
|
||||
C.swap(2 + i); // xx, K, st, q
|
||||
C.pop();
|
||||
}
|
||||
C.pop();
|
||||
}
|
||||
|
||||
function sigma(p) {
|
||||
// sq, q
|
||||
C.dup(t); // q, st, q
|
||||
C.dup(1+p); // st[p] , q , st, q
|
||||
C.dup(1); // q, st[p] , q , st, q
|
||||
C.dup(0); // q, q, st[p] , q , st, q
|
||||
C.dup(2); // st[p] , q, q, st[p] , q , st, q
|
||||
C.dup(0); // st[p] , st[p] , q, q, st[p] , q , st, q
|
||||
C.mulmod(); // st2[p], q, st[p] , q , st, q
|
||||
C.dup(0); // st2[p], st2[p], q, st[p] , q , st, q
|
||||
C.mulmod(); // st4[p], st[p] , q , st, q
|
||||
C.mulmod(); // st5[p], st, q
|
||||
C.swap(1+p);
|
||||
C.pop(); // newst, q
|
||||
}
|
||||
|
||||
function mix() {
|
||||
C.label("mix");
|
||||
for (let i=0; i<t; i++) {
|
||||
for (let j=0; j<t; j++) {
|
||||
if (j==0) {
|
||||
C.dup(i+t); // q, newSt, oldSt, q
|
||||
C.push((1+i*t+j)*32);
|
||||
C.mload(); // M, q, newSt, oldSt, q
|
||||
C.dup(2+i+j); // oldSt[j], M, q, newSt, oldSt, q
|
||||
C.mulmod(); // acc, newSt, oldSt, q
|
||||
} else {
|
||||
C.dup(1+i+t); // q, acc, newSt, oldSt, q
|
||||
C.push((1+i*t+j)*32);
|
||||
C.mload(); // M, q, acc, newSt, oldSt, q
|
||||
C.dup(3+i+j); // oldSt[j], M, q, acc, newSt, oldSt, q
|
||||
C.mulmod(); // aux, acc, newSt, oldSt, q
|
||||
C.dup(2+i+t); // q, aux, acc, newSt, oldSt, q
|
||||
C.swap(2); // acc, aux, q, newSt, oldSt, q
|
||||
C.addmod(); // acc, newSt, oldSt, q
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let i=0; i<t; i++) {
|
||||
C.swap((t -i) + (t -i-1));
|
||||
C.pop();
|
||||
}
|
||||
C.push(0);
|
||||
C.mload();
|
||||
C.jmp();
|
||||
}
|
||||
|
||||
|
||||
// Check selector
|
||||
C.push("0x0100000000000000000000000000000000000000000000000000000000");
|
||||
C.push(0);
|
||||
C.calldataload();
|
||||
C.div();
|
||||
C.push("0xc4420fb4"); // poseidon(uint256[])
|
||||
C.eq();
|
||||
C.jmpi("start");
|
||||
C.invalid();
|
||||
|
||||
C.label("start");
|
||||
|
||||
saveM();
|
||||
|
||||
C.push("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"); // q
|
||||
|
||||
// Load 6 values from the call data.
|
||||
// The function has a single array param param
|
||||
// [Selector (4)] [Pointer (32)][Length (32)] [data1 (32)] ....
|
||||
// We ignore the pointer and the length and just load 6 values to the state
|
||||
// (Stack positions 0-5) If the array is shorter, we just set zeros.
|
||||
for (let i=0; i<t; i++) {
|
||||
C.push(0x44+(0x20*(5-i)));
|
||||
C.calldataload();
|
||||
}
|
||||
|
||||
for (let i=0; i<nRoundsF+nRoundsP; i++) {
|
||||
ark(i);
|
||||
if ((i<nRoundsF/2) || (i>=nRoundsP+nRoundsF/2)) {
|
||||
for (let j=0; j<t; j++) {
|
||||
sigma(j);
|
||||
}
|
||||
} else {
|
||||
sigma(0);
|
||||
}
|
||||
const strLabel = "aferMix"+i;
|
||||
C._pushLabel(strLabel);
|
||||
C.push(0);
|
||||
C.mstore();
|
||||
C.jmp("mix");
|
||||
C.label(strLabel);
|
||||
}
|
||||
|
||||
C.push("0x00");
|
||||
C.mstore(); // Save it to pos 0;
|
||||
C.push("0x20");
|
||||
C.push("0x00");
|
||||
C.return();
|
||||
|
||||
mix();
|
||||
|
||||
return C.createTxData();
|
||||
}
|
||||
|
||||
module.exports.abi = [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "input",
|
||||
"type": "uint256[]"
|
||||
}
|
||||
],
|
||||
"name": "poseidon",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "pure",
|
||||
"type": "function"
|
||||
}
|
||||
];
|
||||
|
||||
module.exports.createCode = createCode;
|
||||
|
||||
|
16
@tornado/circomlib/src/poseidon_printconstants.js
Normal file
16
@tornado/circomlib/src/poseidon_printconstants.js
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
|
||||
const Poseidon = require("./poseidon.js");
|
||||
|
||||
const C = Poseidon.getConstants();
|
||||
|
||||
let S = "[\n";
|
||||
|
||||
for (let i=0; i<C.length; i++) {
|
||||
S = S + " " + C[i].toString();
|
||||
if (i<C.length-1) S = S + ",";
|
||||
S = S + "\n";
|
||||
}
|
||||
S=S+ "]\n";
|
||||
|
||||
console.log(S);
|
5
@tornado/circomlib/src/poseidon_printcontract.js
Normal file
5
@tornado/circomlib/src/poseidon_printcontract.js
Normal file
@ -0,0 +1,5 @@
|
||||
const poseidonGenContract = require("./poseidon_gencontract");
|
||||
|
||||
|
||||
console.log(poseidonGenContract.createCode(6, 8, 57));
|
||||
|
22
@tornado/circomlib/src/poseidon_printmatrix.js
Normal file
22
@tornado/circomlib/src/poseidon_printmatrix.js
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
|
||||
const Poseidon = require("./poseidon.js");
|
||||
|
||||
const M = Poseidon.getMatrix();
|
||||
|
||||
let S = "[\n ";
|
||||
|
||||
for (let i=0; i<M.length; i++) {
|
||||
const LC = M[i];
|
||||
S = S + "[\n";
|
||||
for (let j=0; j<LC.length; j++) {
|
||||
S = S + " " + M[i][j].toString();
|
||||
if (j<LC.length-1) S = S + ",";
|
||||
S = S + "\n";
|
||||
}
|
||||
S = S + " ]";
|
||||
if (i<M.length-1) S = S + ",";
|
||||
}
|
||||
S=S+ "\n]\n";
|
||||
|
||||
console.log(S);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user