66 Commits

Author SHA1 Message Date
Jordi Baylina
5935ac69df 0.3.0 2020-11-26 07:38:39 +01:00
Jordi Baylina
45f190b445 Merge pull request #51 from tornadocash/upstream
pass fixes size array arg in solidity poseidon implementation
2020-11-26 07:35:17 +01:00
Jordi Baylina
8423282b8c Improve performance sha256compressor 2020-11-26 07:29:48 +01:00
Alexey
1e04fc0325 poseidon contract now accepts both selectors: for uint256[n] and bytes32[n] 2020-10-27 21:23:32 +03:00
Alexey
1f9d0bd37f pass fixes size array arg in solidity poseidon implementation 2020-10-26 16:47:07 +03:00
Marta Bellés
411a7d7576 Update README.md 2020-10-05 10:18:06 +02:00
Jordi Baylina
6bcbf3370e 0.2.4 2020-08-31 18:30:11 +02:00
Jordi Baylina
9d876a1b32 deps 2020-08-31 18:30:04 +02:00
Jordi Baylina
d422471b5b Merge pull request #49 from krlosMata/feature/fix-smt-update
fix smt update
2020-08-31 17:14:45 +02:00
Jordi Baylina
01da5f90db Merge pull request #50 from tornadocash/poseidon-pr-2
add poseidon comments and refactorings
2020-08-28 04:29:49 +02:00
poma
fabc586fea add poseidon comments and refactorings 2020-08-27 16:46:49 +03:00
krlosMata
7e93b3fcf8 fix smt update 2020-08-25 13:08:53 +02:00
Jordi Baylina
3f4734d4dd Merge pull request #48 from kobigurk/kobigurk/fix_and_assert_less_than
fix: improve LessThan and adds assert
2020-08-24 11:12:11 +02:00
Kobi Gurkan
1cd3d203c5 fix LessThan and adds assert 2020-08-24 10:46:37 +03:00
Jordi Baylina
01e3f0d680 Poseidon genContract nInputs as parameters 2020-08-09 17:19:53 +02:00
Jordi Baylina
86c6a2a6f5 New Version of Poseidon 2020-08-09 17:13:04 +02:00
Jordi Baylina
5269afee0a 0.2.3 2020-04-20 11:01:20 +02:00
Jordi Baylina
48c721c8af smtdb key string 2020-04-20 11:01:11 +02:00
Jordi Baylina
0efecf16fa 0.2.2 2020-04-19 18:46:11 +02:00
Jordi Baylina
7705fe8339 deps 2020-04-19 18:45:43 +02:00
Jordi Baylina
401c9e0728 0.2.1 2020-04-19 12:24:04 +02:00
Jordi Baylina
d5ed1c3ce4 Go back to blake 2020-04-19 12:23:55 +02:00
Jordi Baylina
6a1efe4820 0.2.0 2020-04-18 22:34:09 +02:00
Jordi Baylina
b2ac4daaa7 Blake to Blake2b and use of native big num 2020-04-18 22:33:59 +02:00
Jordi Baylina
6df6e9cb1c 0.1.2 2020-03-31 15:38:46 +02:00
Jordi Baylina
9c68d4a363 Exporting buffer to int 2020-03-31 15:38:37 +02:00
Jordi Baylina
57be559c44 0.1.1 2020-03-26 22:49:49 +01:00
Jordi Baylina
7bf8325662 deps 2020-03-26 22:49:31 +01:00
Jordi Baylina
899d15f0c2 0.1.0 2020-03-26 19:58:53 +01:00
Jordi Baylina
0bf26ea5ec Merge branch 'c_build' 2020-03-26 19:52:34 +01:00
Jordi Baylina
e240605642 pre 0.5 all working 2020-03-26 19:24:20 +01:00
Jordi Baylina
273ab79665 Negative numbers and fix in comparator 2020-03-16 20:41:11 +01:00
Jordi Baylina
a851d08a46 0.0.21 2020-02-25 05:42:31 -08:00
Jordi Baylina
19bbada388 Poseidon for t=3 2020-02-25 05:41:51 -08:00
Jordi Baylina
cf6d1f0bb1 Test name changed on comparators 2020-02-04 19:19:11 +01:00
Jordi Baylina
2f28fc7002 remove pows and shifts for optimization 2020-01-23 07:23:17 +07:00
Jordi Baylina
4f11565ca4 Adapted circuits to the construction fase refactorization 2019-12-23 19:36:26 +01:00
Jordi Baylina
756f1f51e5 Multithread 2019-12-20 21:59:58 +01:00
Jordi Baylina
bc0fb60f89 SMT test title better explained 2019-12-17 17:12:29 +01:00
Jordi Baylina
7a6b0eda6e All testst finished with c_build 2019-12-16 21:35:52 +01:00
Jordi Baylina
e32460efe1 All tests working 2019-12-14 20:32:45 +01:00
Jordi Baylina
a8107abbe9 pedersen2 adapted 2019-12-13 19:05:20 +01:00
Jordi Baylina
4117ebc64a pedersen working 2019-12-13 18:35:29 +01:00
Jordi Baylina
b4cd3889b6 babyjub.js adapted 2019-12-12 19:46:07 +01:00
Jordi Baylina
30c6cf55b9 Alias Check and Babyjub adapted 2019-12-12 16:49:58 +01:00
Jordi Baylina
d5bca9feb6 sha256 tests updated to c 2019-12-12 13:04:02 +01:00
Jordi Baylina
bdfb0fb928 clean sha256 tests 2019-12-11 21:55:51 +01:00
Jordi Baylina
8bd0fac913 sha256 testing 2019-12-11 21:41:15 +01:00
Jordi Baylina
9941aac2f2 Fix sha256 last 448 test 2019-12-11 06:55:23 +01:00
Jordi Baylina
3c2b566e68 0.0.20 2019-12-04 21:57:32 +01:00
Jordi Baylina
15eadfe50c Merge branch 'master' of github.com:iden3/circomlib 2019-12-04 21:57:08 +01:00
Jordi Baylina
a1d4d1dca7 Convert constant components to functions 2019-12-04 21:57:02 +01:00
Jordi Baylina
d6e6a3b3f4 Fix assigning to signal 2019-12-03 19:16:19 +01:00
arnau
e3eb834322 Merge pull request #23 from kobigurk/fix/mimcsponge_round_constants
MiMCSponge: makes first and last round constants always zero
2019-10-12 14:03:37 +02:00
Kobi Gurkan
01a5530213 MiMCSponge: makes first and last round constants always zero 2019-10-04 17:39:53 +03:00
Jordi Baylina
50a725c174 0.0.19 2019-10-02 09:35:06 +02:00
Jordi Baylina
c4ce4cd946 multiget 2019-10-02 09:34:49 +02:00
Jordi Baylina
5bf52cda57 Merge pull request #20 from bellesmarta/master
Updated README files
2019-09-23 14:58:24 +02:00
Jordi Baylina
95abdd06d5 0.0.18 2019-09-17 07:57:45 +02:00
Jordi Baylina
9f69fab7c6 Merge pull request #22 from kobigurk/fix/mimcsponge_unconstrained
mimcsponge: fixes assignment to outs[0]
2019-09-17 08:55:22 +03:00
Kobi Gurkan
109cdf4056 mimcsponge: fixes assignment to outs[0] 2019-09-17 08:53:02 +03:00
Jordi Baylina
79d30349b4 0.0.17 2019-09-15 10:52:50 +02:00
Jordi Baylina
e3cd0e5aa7 Dependencies and publish smt 2019-09-15 10:52:18 +02:00
Jordi Baylina
86e970b888 0.0.16 2019-09-07 20:23:18 +02:00
Jordi Baylina
29e162383d Allow full poseidnon fix handle enable in the sigposeidon 2019-09-07 20:22:44 +02:00
Marta Belles
97b870b725 Updated README files 2019-09-06 17:14:45 +02:00
93 changed files with 9906 additions and 5372 deletions

View File

@@ -1,7 +1,4 @@
module.exports = {
"plugins": [
"mocha"
],
"env": {
"es6": true,
"node": true,
@@ -27,7 +24,6 @@ module.exports = {
"semi": [
"error",
"always"
],
"mocha/no-exclusive-tests": "error"
]
}
};

View File

@@ -1,4 +1,18 @@
# cirpedersen
# CircomLib
Pedersen Hash and Exponentiation circuits using Baby Jub Curve in circom language
## Description
- This repository contains a library of circuit templates.
- All files are copyrighted under 2018 0KIMS association and part of the free software [circom](https://github.com/iden3/circom) (Zero Knowledge Circuit Compiler).
- You can read more about the circom language in [the circom documentation webpage](https://docs.circom.io/).
## Organisation
This respository contains 5 folders:
- `circuits`: it contains the implementation of different cryptographic primitives in circom language.
- `calcpedersenbases`: set of functions in JavaScript used to find a set of points in [Baby Jubjub](https://github.com/barryWhiteHat/baby_jubjub) elliptic curve that serve as basis for the [Pedersen Hash](https://github.com/zcash/zcash/issues/2234).
- `doc`: it contains some circuit schemes in ASCII (must be opened with Monodraw, an ASCII art editor for Mac).
- `src`: it contains similar implementation of circuits in JavaScript.
- `test`: tests.
A description of the specific circuit templates for the `circuit` folder will be soon updated.

View File

@@ -1,3 +1,19 @@
# 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
@@ -12,3 +28,803 @@
* smt - Sparse Merkle Tree
* https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751
* montgomery https://en.wikipedia.org/wiki/Montgomery_curve
## Circuits
### sha256
Folder containing the implementation of sha256 hash circuit.
### smt
Folder containing the circuit implementation of Sparse Merkle Trees.
### aliascheck
- `AliasCheck()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### babyjub
Arithmetic on [Baby Jubjub elliptic curve](https://github.com/barryWhiteHat/baby_jubjub) in twisted Edwards form. (TODO: Expose here the characteristics of the curve?)
- `BabyAdd()`
- DESCRIPTION
It adds two points on the Baby Jubjub curve. More specifically, given two points P1 = (`x1`, `y1`) and P2 = (`x2`, `y2`) it returns a point P3 = (`xout`, `yout`) such that
(`xout`, `yout`) = (`x1`,`y1`) + (`x2`,`y2`)
= ((`x1y2`+`y1x2`)/(1+`dx1x2y1y2`)),(`y1y2`-`ax1x2`)/(1-`dx1x2y1y2`))
- SCHEMA
```
var a var d
| |
| |
______v_________v_______
input x1 ----> | |
input y1 ----> | BabyAdd() | ----> output xout
input x2 ----> | | ----> output yout
input y2 ----> |________________________|
```
- INPUTS
| Input | Representation | Description | |
| ------------- | ------------- | ------------- | ------------- |
| `x1` | Bigint | Field element of Fp | First coordinate of a point (x1, y1) on E. |
| `y1` | Bigint | Field element of Fp | Second coordinate of a point (x1, y1) on E. |
| `x2` | Bigint | Field element of Fp | First coordinate of a point (x2, y2) on E. |
| `y2` | Bigint | Field element of Fp | Second coordinate of a point (x2, y2) on E. |
Requirement: at least `x1`!=`x2` or `y1`!=`y2`.
- OUTPUT
| Input | Representation | Description | |
| ------------- | ------------- | ------------- | ------------- |
| `xout` | Bigint | Field element of Fp | First coordinate of the addition point (xout, yout) = (x1, y1) + (x2, y2). |
| `yout` | Bigint | Field element of Fp | Second coordinate of the addition point (xout, yout) = (x1, y1) + (x2, y2). |
- BENCHMARKS (constraints)
- EXAMPLE
- `BabyDbl()`
- DESCRIPTION : doubles a point (`xout`,`yout`) = 2*(`x`,`y`).
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `BabyCheck()`
- DESCRIPTION : checks if a given point is in the curve.
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `BabyPbk()`
- DESCRIPTION: : given a private key, it returns the associated public key.
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### binsub
- `BinSub(n)`
- DESCRIPTION: binary substraction.
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### binsum
- `nbits(a)`
- DESCRIPTION : binary sum.
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `BinSum(n, ops)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### bitify
- `Num2Bits()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Num2Bits_strict()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Bits2Num()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Bits2Num_strict()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Num2BitsNeg()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### comparators
- `IsZero() `
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `IsEqual()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `ForceEqualIfEnabled()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `LessThan()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `GreaterThan()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `GreaterEqThan()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### compconstant
- `CompConstant(ct)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### eddsa
Edwards Digital Signature Algorithm in Baby Jubjbub (link a eddsa)
- `EdDSAVerifier(n)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### eddsamimc
- `EdDSAMiMCVerifier()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### eddsamimcsponge
- `EdDSAMiMCSpongeVerifier()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### eddsaposeidon
- `EdDSAPoseidonVerifier()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### escalarmul
- `EscalarMulWindow(base, k)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `EscalarMul(n, base)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### escalarmulany
- `Multiplexor2()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `BitElementMulAny()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `SegmentMulAny(n)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `EscalarMulAny(n)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### escalarmulfix
- `WindowMulFix()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `SegmentMulFix(nWindows)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `EscalarMulFix(n, BASE)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### escalarmulw4table
- `pointAdd`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `EscalarMulW4Table`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### gates
- `XOR`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `AND`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `OR`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `NOT`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `NAND`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `NOR`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `MultiAND`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### mimc
Implementation of MiMC-7 hash in Fp being... (link to description of the hash)
- `MiMC7(nrounds)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `MultiMiMC7(nInputs, nRounds)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### mimcsponge
- `MiMCSponge(nInputs, nRounds, nOutputs)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `MiMCFeistel(nrounds)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### montgomery
- `Edwards2Montgomery()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Montgomery2Edwards()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `MontgomeryAdd()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `MontgomeryDouble()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### multiplexer
- `log2(a)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `EscalarProduct(w)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Decoder(w)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Multiplexer(wIn, nIn)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### mux1
- `MultiMux1(n)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Mux1()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### mux2
- `MultiMux2(n)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Mux2()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### mux3
- `MultiMux3(n)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Mux3()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### mux4
- `MultiMux4(n)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Mux4()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### pedersen_old
Old version of the Pedersen hash (do not use any
more?).
### pedersen
- `Window4()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Segment(nWindows)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Pedersen(n)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### pointbits
- `sqrt(n)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Bits2Point()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Bits2Point_Strict()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Point2Bits`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Point2Bits_Strict`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### poseidon
Implementation of Poseidon hash function (LINK)
- `Sigma()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Ark(t, C, r)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Mix(t, M)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
- `Poseidon(nInputs)`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### sign
- `Sign()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE
### switcher
- `Switcher()`
- DESCRIPTION
- SCHEMA
- INPUT
- OUTPUT
- BENCHMARKS
- EXAMPLE

View File

@@ -87,7 +87,7 @@ template BabyPbk() {
signal output Ax;
signal output Ay;
var BASE8 = [
var BASE8[2] = [
5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203
];

View File

@@ -48,12 +48,14 @@ template BinSub(n) {
var lin = 2**n;
var lout = 0;
for (var i=0; i<n; i++) {
var i;
for (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++) {
for (i=0; i<n; i++) {
out[i] <-- (lin >> i) & 1;
// Ensure out is binary

View File

@@ -72,19 +72,26 @@ template BinSum(n, ops) {
var k;
var j;
var e2;
e2 = 1;
for (k=0; k<n; k++) {
for (j=0; j<ops; j++) {
lin += in[j][k] * 2**k;
lin += in[j][k] * e2;
}
e2 = e2 + e2;
}
e2 = 1;
for (k=0; k<nout; k++) {
out[k] <-- (lin >> k) & 1;
// Ensure out is binary
out[k] * (out[k] - 1) === 0;
lout += out[k] * 2**k;
lout += out[k] * e2;
e2 = e2+e2;
}
// Ensure the sum;

View File

@@ -26,10 +26,12 @@ template Num2Bits(n) {
signal output out[n];
var lc1=0;
var e2=1;
for (var i = 0; i<n; i++) {
out[i] <-- (in >> i) & 1;
out[i] * (out[i] -1 ) === 0;
lc1 += out[i] * 2**i;
lc1 += out[i] * e2;
e2 = e2+e2;
}
lc1 === in;
@@ -54,8 +56,10 @@ template Bits2Num(n) {
signal output out;
var lc1=0;
var e2 = 1;
for (var i = 0; i<n; i++) {
lc1 += in[i] * 2**i;
lc1 += in[i] * e2;
e2 = e2 + e2;
}
lc1 ==> out;

View File

@@ -86,10 +86,11 @@ template LessThan(n) {
*/
template LessThan(n) {
assert(n <= 252);
signal input in[2];
signal output out;
component n2b = Num2Bits(n*2+1);
component n2b = Num2Bits(n+1);
n2b.in <== in[0]+ (1<<n) - in[1];

View File

@@ -46,12 +46,11 @@ template CompConstant(ct) {
slsb = in[i*2];
smsb = in[i*2+1];
if ((cmsb==0)&(clsb==0)) {
if ((cmsb==0)&&(clsb==0)) {
parts[i] <== -b*smsb*slsb + b*smsb + b*slsb;
} else if ((cmsb==0)&(clsb==1)) {
} else if ((cmsb==0)&&(clsb==1)) {
parts[i] <== a*smsb*slsb - a*slsb + b*smsb - a*smsb + a;
} else if ((cmsb==1)&(clsb==0)) {
} else if ((cmsb==1)&&(clsb==0)) {
parts[i] <== b*smsb*slsb - a*smsb + a;
} else {
parts[i] <== -a*smsb*slsb + a;

View File

@@ -122,7 +122,7 @@ template EdDSAVerifier(n) {
// Calculate left side of equation left = S*B8
var BASE8 = [
var BASE8[2] = [
5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203
];

View File

@@ -100,7 +100,7 @@ template EdDSAMiMCVerifier() {
// Calculate left side of equation left = S*B8
var BASE8 = [
var BASE8[2] = [
5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203
];

View File

@@ -100,7 +100,7 @@ template EdDSAMiMCSpongeVerifier() {
// Calculate left side of equation left = S*B8
var BASE8 = [
var BASE8[2] = [
5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203
];

View File

@@ -47,11 +47,11 @@ template EdDSAPoseidonVerifier() {
snum2bits.out[i] ==> compConstant.in[i];
}
compConstant.in[253] <== 0;
compConstant.out === 0;
compConstant.out*enabled === 0;
// Calculate the h = H(R,A, msg)
component hash = Poseidon(5, 6, 8, 57);
component hash = Poseidon(5);
hash.inputs[0] <== R8x;
hash.inputs[1] <== R8y;
@@ -79,7 +79,7 @@ template EdDSAPoseidonVerifier() {
// We check that A is not zero.
component isZero = IsZero();
isZero.in <== dbl3.x;
isZero.out === 0;
isZero.out*enabled === 0;
component mulAny = EscalarMulAny(254);
for (i=0; i<254; i++) {
@@ -99,7 +99,7 @@ template EdDSAPoseidonVerifier() {
// Calculate left side of equation left = S*B8
var BASE8 = [
var BASE8[2] = [
5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203
];

View File

@@ -71,7 +71,7 @@ template EscalarMulWindow(base, k) {
signal input sel[4];
signal output out[2];
component table;
var table[16][2];
component mux;
component adder;
@@ -86,8 +86,8 @@ template EscalarMulWindow(base, k) {
}
for (i=0; i<16; i++) {
table.out[i][0] ==> mux.c[0][i];
table.out[i][1] ==> mux.c[1][i];
mux.c[0][i] <== table[i][0];
mux.c[1][i] <== table[i][1];
}
in[0] ==> adder.x1;

View File

@@ -176,6 +176,9 @@ template SegmentMulFix(nWindows) {
cadders[i].in1[0] <== cadders[i-1].out[0];
cadders[i].in1[1] <== cadders[i-1].out[1];
}
for (j=0; j<3; j++) {
windows[i].in[j] <== e[3*i+j];
}
if (i<nWindows-1) {
cadders[i].in2[0] <== windows[i].out8[0];
cadders[i].in2[1] <== windows[i].out8[1];
@@ -185,9 +188,6 @@ template SegmentMulFix(nWindows) {
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++) {

View File

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

View File

@@ -67,6 +67,7 @@ template NOR() {
template MultiAND(n) {
signal input in[n];
signal output out;
var i;
if (n==1) {
out <== in[0];
} else if (n==2) {
@@ -81,8 +82,8 @@ template MultiAND(n) {
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];
for (i=0; i<n1; i++) ands[0].in[i] <== in[i];
for (i=0; i<n2; i++) ands[1].in[i] <== in[n1+i];
and2.a <== ands[0].out;
and2.b <== ands[1].out;
out <== and2.out;

View File

@@ -22,7 +22,7 @@ template MiMC7(nrounds) {
signal input k;
signal output out;
var c = [
var c[91] = [
0,
20888961410941983456478427210666206549300505294776164667214940546594746570981,
15265126113435022738560151911929040668591755459209400716467504685752745317193,

View File

@@ -6,10 +6,12 @@ template MiMCSponge(nInputs, nRounds, nOutputs) {
signal input k;
signal output outs[nOutputs];
var i;
// S = R||C
component S[nInputs + nOutputs - 1];
for (var i = 0; i < nInputs; i++) {
for (i = 0; i < nInputs; i++) {
S[i] = MiMCFeistel(nRounds);
S[i].k <== k;
if (i == 0) {
@@ -21,9 +23,9 @@ template MiMCSponge(nInputs, nRounds, nOutputs) {
}
}
outs[0] = S[nInputs - 1].xL_out;
outs[0] <== S[nInputs - 1].xL_out;
for (var i = 0; i < nOutputs - 1; i++) {
for (i = 0; i < nOutputs - 1; i++) {
S[nInputs + i] = MiMCFeistel(nRounds);
S[nInputs + i].k <== k;
S[nInputs + i].xL_in <== S[nInputs + i - 1].xL_out;
@@ -39,8 +41,8 @@ template MiMCFeistel(nrounds) {
signal output xL_out;
signal output xR_out;
var c = [
0,
// doesn't contain the first and last round constants, which are always zero
var c_partial[218] = [
7120861356467848435263064379192047478074060781135320967663101236819528304084,
5024705281721889198577876690145313457398658950011302225525409148828000436681,
17980351014018068290387269214713820287804403312720763401943303895585469787384,
@@ -258,8 +260,7 @@ template MiMCFeistel(nrounds) {
18224457394066545825553407391290108485121649197258948320896164404518684305122,
274945154732293792784580363548970818611304339008964723447672490026510689427,
11050822248291117548220126630860474473945266276626263036056336623671308219529,
2119542016932434047340813757208803962484943912710204325088879681995922344971,
0
2119542016932434047340813757208803962484943912710204325088879681995922344971
];
var t;
@@ -268,13 +269,19 @@ template MiMCFeistel(nrounds) {
signal xL[nrounds-1];
signal xR[nrounds-1];
var c;
for (var i=0; i<nrounds; i++) {
t = (i==0) ? k+xL_in : k + xL[i-1] + c[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];
xR[i] <== (i==0) ? xL_in : xL[i-1];
} else {
xR_out <== xR[i-1] + t4[i]*t;
xL_out <== xL[i-1];

View File

@@ -128,6 +128,9 @@ template Segment(nWindows) {
component adders[nWindows-1];
for (i=0; i<nWindows; i++) {
windows[i] = Window4();
for (j=0; j<4; j++) {
windows[i].in[j] <== in[4*i+j];
}
if (i==0) {
windows[i].base[0] <== e2m.out[0];
windows[i].base[1] <== e2m.out[1];
@@ -153,9 +156,6 @@ template Segment(nWindows) {
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();
@@ -176,7 +176,7 @@ template Pedersen(n) {
signal input in[n];
signal output out[2];
var BASE = [
var BASE[10][2] = [
[10457101036533406547632367118273992217979173478358440826365724437999023779287,19824078218392094440610104313265183977899662750282163392862422243483260492317],
[2671756056509184035029146175565761955751135805354291559563293617232983272177,2663205510731142763556352975002641716101654201788071096152948830924149045094],
[5802099305472655231388284418920769829666717045250560929368476121199858275951,5980429700218124965372158798884772646841287887664001482443826541541529227896],
@@ -187,7 +187,8 @@ template Pedersen(n) {
[6814338563135591367010655964669793483652536871717891893032616415581401894627,13660303521961041205824633772157003587453809761793065294055279768121314853695],
[3571615583211663069428808372184817973703476260057504149923239576077102575715,11981351099832644138306422070127357074117642951423551606012551622164230222506],
[18597552580465440374022635246985743886550544261632147935254624835147509493269,6753322320275422086923032033899357299485124665258735666995435957890214041481]
]
];
var nSegments = ((n-1)\200)+1;

View File

@@ -28,7 +28,7 @@ template Pedersen(n) {
component escalarMuls[nexps];
var PBASE = [
var PBASE[10][2] = [
[10457101036533406547632367118273992217979173478358440826365724437999023779287,19824078218392094440610104313265183977899662750282163392862422243483260492317],
[2671756056509184035029146175565761955751135805354291559563293617232983272177,2663205510731142763556352975002641716101654201788071096152948830924149045094],
[5802099305472655231388284418920769829666717045250560929368476121199858275951,5980429700218124965372158798884772646841287887664001482443826541541529227896],
@@ -39,6 +39,7 @@ template Pedersen(n) {
[6814338563135591367010655964669793483652536871717891893032616415581401894627,13660303521961041205824633772157003587453809761793065294055279768121314853695],
[3571615583211663069428808372184817973703476260057504149923239576077102575715,11981351099832644138306422070127357074117642951423551606012551622164230222506],
[18597552580465440374022635246985743886550544261632147935254624835147509493269,6753322320275422086923032033899357299485124665258735666995435957890214041481]
];
var i;

View File

@@ -61,7 +61,7 @@ function sqrt(n) {
r = r*b;
}
if (r > ((-1) >> 1)) {
if (r < 0 ) {
r = -r;
}

View File

@@ -1,3 +1,4 @@
include "./poseidon_constants.circom";
template Sigma() {
signal input in;
@@ -12,163 +13,52 @@ template Sigma() {
out <== in4*in;
}
template Ark(t, C) {
template Ark(t, C, r) {
signal input in[t];
signal output out[t];
for (var i=0; i<t; i++) {
out[i] <== in[i] + C;
out[i] <== in[i] + C[i + r];
}
}
template Mix(t, M) {
signal input in[t];
signal output out[t];
var lc;
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];
lc += M[j][i]*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
]
];
template Poseidon(nInputs) {
signal input inputs[nInputs];
signal output out;
component ark[nRoundsF + nRoundsP];
component sigmaF[nRoundsF][t];
// Using recommended parameters from whitepaper https://eprint.iacr.org/2019/458.pdf (table 2, table 8)
// Generated by https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/calc_round_numbers.py
// And rounded up to nearest integer that divides by t
var N_ROUNDS_P[8] = [56, 57, 56, 60, 60, 63, 64, 63];
var t = nInputs + 1;
var nRoundsF = 8;
var nRoundsP = N_ROUNDS_P[t - 2];
var C[t*(nRoundsF + nRoundsP)] = POSEIDON_C(t);
var M[t][t] = POSEIDON_M(t);
component ark[nRoundsF + nRoundsP - 1];
component sigmaF[nRoundsF - 1][t];
component sigmaP[nRoundsP];
component mix[nRoundsF + nRoundsP];
component mix[nRoundsF + nRoundsP - 1];
var k;
for (var i=0; i<(nRoundsF + nRoundsP); i++) {
ark[i] = Ark(t, C[i]);
mix[i] = Mix(t, M);
for (var i=0; i<nRoundsF + nRoundsP - 1; i++) {
ark[i] = Ark(t, C, t*i);
for (var j=0; j<t; j++) {
if (i==0) {
if (j<nInputs) {
@@ -181,8 +71,9 @@ template Poseidon(nInputs, t, nRoundsF, nRoundsP) {
}
}
if ((i<(nRoundsF/2)) || (i>= (nRoundsP + nRoundsF/2))) {
k= i<nRoundsF/2 ? i : (i-nRoundsP);
if (i < nRoundsF/2 || i >= nRoundsP + nRoundsF/2) {
k = i < nRoundsF/2 ? i : i - nRoundsP;
mix[i] = Mix(t, M);
for (var j=0; j<t; j++) {
sigmaF[k][j] = Sigma();
sigmaF[k][j].in <== ark[i].out[j];
@@ -190,6 +81,7 @@ template Poseidon(nInputs, t, nRoundsF, nRoundsP) {
}
} else {
k = i - nRoundsF/2;
mix[i] = Mix(t, M);
sigmaP[k] = Sigma();
sigmaP[k].in <== ark[i].out[0];
mix[i].in[0] <== sigmaP[k].out;
@@ -199,5 +91,8 @@ template Poseidon(nInputs, t, nRoundsF, nRoundsP) {
}
}
out <== mix[nRoundsF + nRoundsP -1].out[0];
// last round is done only for the first word, so we do it manually to save constraints
component lastSigmaF = Sigma();
lastSigmaF.in <== mix[nRoundsF + nRoundsP - 2].out[0] + C[t*(nRoundsF + nRoundsP - 1)];
out <== lastSigmaF.out;
}

File diff suppressed because one or more lines are too long

View File

@@ -19,7 +19,7 @@
template H(x) {
signal output out[32];
var c = [0x6a09e667,
var c[8] = [0x6a09e667,
0xbb67ae85,
0x3c6ef372,
0xa54ff53a,
@@ -35,7 +35,7 @@ template H(x) {
template K(x) {
signal output out[32];
var c = [
var c[64] = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,

View File

@@ -22,6 +22,8 @@ include "t1.circom";
include "t2.circom";
include "../binsum.circom";
include "sigmaplus.circom";
include "sha256compression_function.circom";
template Sha256compression() {
signal input hin[256];
@@ -37,7 +39,11 @@ template Sha256compression() {
signal h[65][32];
signal w[64][32];
var outCalc[256] = sha256compression(hin, inp);
var i;
for (i=0; i<256; i++) out[i] <-- outCalc[i];
component sigmaPlus[48];
for (i=0; i<48; i++) sigmaPlus[i] = SigmaPlus();
@@ -74,6 +80,9 @@ template Sha256compression() {
sigmaPlus[t-16].in7[k] <== w[t-7][k];
sigmaPlus[t-16].in15[k] <== w[t-15][k];
sigmaPlus[t-16].in16[k] <== w[t-16][k];
}
for (k=0; k<32; k++) {
w[t][k] <== sigmaPlus[t-16].out[k];
}
}
@@ -144,13 +153,13 @@ template Sha256compression() {
}
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];
out[31-k] === fsum[0].out[k];
out[32+31-k] === fsum[1].out[k];
out[64+31-k] === fsum[2].out[k];
out[96+31-k] === fsum[3].out[k];
out[128+31-k] === fsum[4].out[k];
out[160+31-k] === fsum[5].out[k];
out[192+31-k] === fsum[6].out[k];
out[224+31-k] === fsum[7].out[k];
}
}

View File

@@ -0,0 +1,112 @@
// signal input hin[256];
// signal input inp[512];
// signal output out[256];
function rrot(x, n) {
return ((x >> n) | (x << (32-n))) & 0xFFFFFFFF;
}
function bsigma0(x) {
return rrot(x,2) ^ rrot(x,13) ^ rrot(x,22);
}
function bsigma1(x) {
return rrot(x,6) ^ rrot(x,11) ^ rrot(x,25);
}
function ssigma0(x) {
return rrot(x,7) ^ rrot(x,18) ^ (x >> 3);
}
function ssigma1(x) {
return rrot(x,17) ^ rrot(x,19) ^ (x >> 10);
}
function Maj(x, y, z) {
return (x&y) ^ (x&z) ^ (y&z);
}
function Ch(x, y, z) {
return (x & y) ^ ((0xFFFFFFFF ^x) & z);
}
function sha256K(i) {
var k[64] = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
];
return k[i];
}
function sha256compression(hin, inp) {
var H[8];
var a;
var b;
var c;
var d;
var e;
var f;
var g;
var h;
var out[256];
for (var i=0; i<8; i++) {
H[i] = 0;
for (var j=0; j<32; j++) {
H[i] += hin[i*32+j] << j;
}
}
a=H[0];
b=H[1];
c=H[2];
d=H[3];
e=H[4];
f=H[5];
g=H[6];
h=H[7];
var w[64];
var T1;
var T2;
for (var i=0; i<64; i++) {
if (i<16) {
w[i]=0;
for (var j=0; j<32; j++) {
w[i] += inp[i*32+31-j]<<j;
}
} else {
w[i] = (ssigma1(w[i-2]) + w[i-7] + ssigma0(w[i-15]) + w[i-16]) & 0xFFFFFFFF;
}
T1 = (h + bsigma1(e) + Ch(e,f,g) + sha256K(i) + w[i]) & 0xFFFFFFFF;
T2 = (bsigma0(a) + Maj(a,b,c)) & 0xFFFFFFFF;
h=g;
g=f;
f=e;
e=(d+T1) & 0xFFFFFFFF;
d=c;
c=b;
b=a;
a=(T1+T2) & 0xFFFFFFFF;
}
H[0] = H[0] + a;
H[1] = H[1] + b;
H[2] = H[2] + c;
H[3] = H[3] + d;
H[4] = H[4] + e;
H[5] = H[5] + f;
H[6] = H[6] + g;
H[7] = H[7] + h;
for (var i=0; i<8; i++) {
for (var j=0; j<32; j++) {
out[i*32+31-j] = (H[i] >> j) & 1;
}
}
return out;
}

View File

@@ -24,22 +24,26 @@ include "shift.circom";
template SmallSigma(ra, rb, rc) {
signal input in[32];
signal output out[32];
component xor3 = Xor3(32);
var k;
component rota = RotR(32, ra);
component rotb = RotR(32, rb);
component shrc = ShR(32, rc);
for (var k=0; k<32; k++) {
for (k=0; k<32; k++) {
rota.in[k] <== in[k];
rotb.in[k] <== in[k];
shrc.in[k] <== in[k];
}
component xor3 = Xor3(32);
for (k=0; k<32; k++) {
xor3.a[k] <== rota.out[k];
xor3.b[k] <== rotb.out[k];
xor3.c[k] <== shrc.out[k];
}
for (k=0; k<32; k++) {
out[k] <== xor3.out[k];
}
}
@@ -47,22 +51,26 @@ template SmallSigma(ra, rb, rc) {
template BigSigma(ra, rb, rc) {
signal input in[32];
signal output out[32];
component xor3 = Xor3(32);
var k;
component rota = RotR(32, ra);
component rotb = RotR(32, rb);
component rotc = RotR(32, rc);
for (var k=0; k<32; k++) {
for (k=0; k<32; k++) {
rota.in[k] <== in[k];
rotb.in[k] <== in[k];
rotc.in[k] <== in[k];
}
component xor3 = Xor3(32);
for (k=0; k<32; k++) {
xor3.a[k] <== rota.out[k];
xor3.b[k] <== rotb.out[k];
xor3.c[k] <== rotc.out[k];
}
for (k=0; k<32; k++) {
out[k] <== xor3.out[k];
}
}

View File

@@ -26,20 +26,24 @@ template SigmaPlus() {
signal input in15[32];
signal input in16[32];
signal output out[32];
var k;
component sum = BinSum(32, 4);
component sigma1 = SmallSigma(17,19,10);
component sigma0 = SmallSigma(7, 18, 3);
for (var k=0; k<32; k++) {
for (k=0; k<32; k++) {
sigma1.in[k] <== in2[k];
sigma0.in[k] <== in15[k];
}
component sum = BinSum(32, 4);
for (k=0; k<32; k++) {
sum.in[0][k] <== sigma1.out[k];
sum.in[1][k] <== in7[k];
sum.in[2][k] <== sigma0.out[k];
sum.in[3][k] <== in16[k];
}
for (k=0; k<32; k++) {
out[k] <== sum.out[k];
}
}

View File

@@ -30,23 +30,28 @@ template T1() {
signal input w[32];
signal output out[32];
component sum = BinSum(32, 5);
component ch = Ch(32);
var ki;
component ch = Ch(32);
component bigsigma1 = BigSigma(6, 11, 25);
for (var ki=0; ki<32; ki++) {
for (ki=0; ki<32; ki++) {
bigsigma1.in[ki] <== e[ki];
ch.a[ki] <== e[ki];
ch.b[ki] <== f[ki];
ch.c[ki] <== g[ki]
ch.c[ki] <== g[ki];
}
component sum = BinSum(32, 5);
for (ki=0; ki<32; ki++) {
sum.in[0][ki] <== h[ki];
sum.in[1][ki] <== bigsigma1.out[ki];
sum.in[2][ki] <== ch.out[ki];
sum.in[3][ki] <== k[ki];
sum.in[4][ki] <== w[ki];
}
for (ki=0; ki<32; ki++) {
out[ki] <== sum.out[ki];
}
}

View File

@@ -26,22 +26,25 @@ template T2() {
signal input b[32];
signal input c[32];
signal output out[32];
component sum = BinSum(32, 2);
var k;
component bigsigma0 = BigSigma(2, 13, 22);
component maj = Maj(32);
for (var k=0; k<32; k++) {
for (k=0; k<32; k++) {
bigsigma0.in[k] <== a[k];
maj.a[k] <== a[k];
maj.b[k] <== b[k];
maj.c[k] <== c[k];
}
component sum = BinSum(32, 2);
for (k=0; k<32; k++) {
sum.in[0][k] <== bigsigma0.out[k];
sum.in[1][k] <== maj.out[k];
}
for (k=0; k<32; k++) {
out[k] <== sum.out[k];
}
}

View File

@@ -29,7 +29,7 @@ template SMTHash1() {
signal input value;
signal output out;
component h = Poseidon(3, 6, 8, 57); // Constant
component h = Poseidon(3); // Constant
h.inputs[0] <== key;
h.inputs[1] <== value;
h.inputs[2] <== 1;
@@ -48,7 +48,7 @@ template SMTHash2() {
signal input R;
signal output out;
component h = Poseidon(2, 6, 8, 57); // Constant
component h = Poseidon(2); // Constant
h.inputs[0] <== L;
h.inputs[1] <== R;

View File

@@ -79,9 +79,11 @@ template SMTLevIns(nLevels) {
signal output levIns[nLevels];
signal done[nLevels-1]; // Indicates if the insLevel has aready been detected.
var i;
component isZero[nLevels];
for (var i=0; i<nLevels; i++) {
for (i=0; i<nLevels; i++) {
isZero[i] = IsZero();
isZero[i].in <== siblings[i];
}
@@ -91,7 +93,7 @@ template SMTLevIns(nLevels) {
levIns[nLevels-1] <== (1-isZero[nLevels-2].out);
done[nLevels-2] <== levIns[nLevels-1];
for (var i=nLevels-2; i>0; i--) {
for (i=nLevels-2; i>0; i--) {
levIns[i] <== (1-done[i])*(1-isZero[i-1].out)
done[i-1] <== levIns[i] + done[i];
}

View File

@@ -150,6 +150,8 @@ template SMTProcessor(nLevels) {
signal enabled;
var i;
enabled <== fnc[0] + fnc[1] - fnc[0]*fnc[1]
component hash1Old = SMTHash1();
@@ -167,18 +169,18 @@ template SMTProcessor(nLevels) {
n2bNew.in <== newKey;
component smtLevIns = SMTLevIns(nLevels);
for (var i=0; i<nLevels; i++) smtLevIns.siblings[i] <== siblings[i];
for (i=0; i<nLevels; i++) smtLevIns.siblings[i] <== siblings[i];
smtLevIns.enabled <== enabled;
component xors[nLevels];
for (var i=0; i<nLevels; i++) {
for (i=0; i<nLevels; i++) {
xors[i] = XOR();
xors[i].a <== n2bOld.out[i];
xors[i].b <== n2bNew.out[i];
}
component sm[nLevels];
for (var i=0; i<nLevels; i++) {
for (i=0; i<nLevels; i++) {
sm[i] = SMTProcessorSM();
if (i==0) {
sm[i].prev_top <== enabled;
@@ -204,7 +206,7 @@ template SMTProcessor(nLevels) {
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--) {
for (i=nLevels-1; i != -1; i--) {
levels[i] = SMTProcessorLevel();
levels[i].st_top <== sm[i].st_top;

View File

@@ -48,6 +48,8 @@ template SMTVerifier(nLevels) {
signal input value;
signal input fnc;
var i;
component hash1Old = SMTHash1();
hash1Old.key <== oldKey;
hash1Old.value <== oldValue;
@@ -63,11 +65,11 @@ template SMTVerifier(nLevels) {
n2bNew.in <== key;
component smtLevIns = SMTLevIns(nLevels);
for (var i=0; i<nLevels; i++) smtLevIns.siblings[i] <== siblings[i];
for (i=0; i<nLevels; i++) smtLevIns.siblings[i] <== siblings[i];
smtLevIns.enabled <== enabled;
component sm[nLevels];
for (var i=0; i<nLevels; i++) {
for (i=0; i<nLevels; i++) {
sm[i] = SMTVerifierSM();
if (i==0) {
sm[i].prev_top <== enabled;
@@ -89,7 +91,7 @@ template SMTVerifier(nLevels) {
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--) {
for (i=nLevels-1; i != -1; i--) {
levels[i] = SMTVerifierLevel();
levels[i].st_top <== sm[i].st_top;

View File

@@ -4,3 +4,9 @@ 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");

8296
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "circomlib",
"version": "0.0.15",
"version": "0.3.0",
"description": "Basic circuits library for Circom",
"main": "index.js",
"directories": {
@@ -26,14 +26,13 @@
"dependencies": {
"blake-hash": "^1.1.0",
"blake2b": "^2.1.3",
"snarkjs": "^0.1.19",
"typedarray-to-buffer": "^3.1.5",
"web3": "^1.0.0-beta.55"
"circom": "0.5.33",
"ffjavascript": "0.1.0"
},
"devDependencies": {
"circom": "0.0.28",
"eslint-plugin-mocha": "^5.2.0",
"ganache-cli": "^6.4.4",
"mocha": "^5.2.0"
"eslint": "^6.8.0",
"ganache-cli": "^6.12.1",
"mocha": "^7.1.1",
"web3": "^1.3.0"
}
}

View File

@@ -1,5 +1,6 @@
const bn128 = require("snarkjs").bn128;
const bigInt = require("snarkjs").bigInt;
const F1Field = require("ffjavascript").F1Field;
const Scalar = require("ffjavascript").Scalar;
const utils = require("ffjavascript").utils;
exports.addPoint = addPoint;
exports.mulPointEscalar = mulPointEscalar;
@@ -7,23 +8,27 @@ exports.inCurve = inCurve;
exports.inSubgroup = inSubgroup;
exports.packPoint = packPoint;
exports.unpackPoint = unpackPoint;
exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
const F = new F1Field(exports.p);
exports.F = F;
exports.Generator = [
bigInt("995203441582195749578291179787384436505546430278305826713579947235728471134"),
bigInt("5472060717959818805561601436314318772137091100104008585924551046643952123905")
F.e("995203441582195749578291179787384436505546430278305826713579947235728471134"),
F.e("5472060717959818805561601436314318772137091100104008585924551046643952123905")
];
exports.Base8 = [
bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")
F.e("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
F.e("16950150798460657717958625567821834550301663161624707787222815936182638968203")
];
exports.order = bigInt("21888242871839275222246405745257275088614511777268538073601725287587578984328");
exports.subOrder = exports.order.shr(3);
exports.p = bn128.r;
exports.A = bigInt("168700");
exports.D = bigInt("168696");
exports.order = Scalar.fromString("21888242871839275222246405745257275088614511777268538073601725287587578984328");
exports.subOrder = Scalar.shiftRight(exports.order, 3);
exports.A = F.e("168700");
exports.D = F.e("168696");
function addPoint(a,b) {
const q = bn128.r;
const res = [];
@@ -31,23 +36,40 @@ function addPoint(a,b) {
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);
const beta = F.mul(a[0],b[1]);
const gamma = F.mul(a[1],b[0]);
const delta = F.mul(
F.sub(a[1], F.mul(exports.A, a[0])),
F.add(b[0], b[1])
);
const tau = F.mul(beta, gamma);
const dtau = F.mul(exports.D, tau);
res[0] = F.div(
F.add(beta, gamma),
F.add(F.one, dtau)
);
res[1] = F.div(
F.add(delta, F.sub(F.mul(exports.A,beta), gamma)),
F.sub(F.one, dtau)
);
return res;
}
function mulPointEscalar(base, e) {
let res = [bigInt("0"),bigInt("1")];
let rem = bigInt(e);
let res = [F.e("0"),F.e("1")];
let rem = e;
let exp = base;
while (! rem.isZero()) {
if (rem.isOdd()) {
while (! Scalar.isZero(rem)) {
if (Scalar.isOdd(rem)) {
res = addPoint(res, exp);
}
exp = addPoint(exp, exp);
rem = rem.shr(1);
rem = Scalar.shiftRight(rem, 1);
}
return res;
@@ -56,16 +78,15 @@ function mulPointEscalar(base, e) {
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)));
return (F.isZero(res[0]) && F.eq(res[1], F.one));
}
function inCurve(P) {
const F = bn128.Fr;
const x2 = F.square(P[0]);
const y2 = F.square(P[1]);
if (!F.equals(
if (!F.eq(
F.add(F.mul(exports.A, x2), y2),
F.add(F.one, F.mul(F.mul(x2, y2), exports.D)))) return false;
@@ -73,16 +94,14 @@ function inCurve(P) {
}
function packPoint(P) {
const buff = bigInt.leInt2Buff(P[1], 32);
if (P[0].greater(exports.p.shr(1))) {
const buff = utils.leInt2Buff(P[1], 32);
if (F.lt(P[0], F.zero)) {
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);
@@ -90,8 +109,8 @@ function unpackPoint(_buff) {
sign = true;
buff[31] = buff[31] & 0x7F;
}
P[1] = bigInt.leBuff2int(buff);
if (P[1].greaterOrEquals(exports.p)) return null;
P[1] = utils.leBuff2int(buff);
if (Scalar.gt(P[1], exports.p)) return null;
const y2 = F.square(P[1]);
@@ -103,7 +122,7 @@ function unpackPoint(_buff) {
if (sign) x = F.neg(x);
P[0] = F.affine(x);
P[0] = x;
return P;
}

View File

@@ -1,11 +1,14 @@
const createBlakeHash = require("blake-hash");
const bigInt = require("snarkjs").bigInt;
const Scalar = require("ffjavascript").Scalar;
const F1Field = require("ffjavascript").F1Field;
const babyJub = require("./babyjub");
const utils = require("ffjavascript").utils;
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;
@@ -30,26 +33,27 @@ function pruneBuffer(_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));
let s = utils.leBuff2int(sBuff);
const A = babyJub.mulPointEscalar(babyJub.Base8, Scalar.shr(s,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 s = utils.leBuff2int(sBuff);
const A = babyJub.mulPointEscalar(babyJub.Base8, Scalar.shr(s, 3));
const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msg])).digest();
let r = bigInt.leBuff2int(rBuff);
r = r.mod(babyJub.subOrder);
let r = utils.leBuff2int(rBuff);
const Fr = new F1Field(babyJub.subOrder);
r = Fr.e(r);
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);
const hm = utils.leBuff2int(hmBuff);
const S = Fr.add(r , Fr.mul(hm, s));
return {
R8: R8,
S: S
@@ -59,16 +63,17 @@ function sign(prv, msg) {
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 s = utils.leBuff2int(sBuff);
const A = babyJub.mulPointEscalar(babyJub.Base8, Scalar.shr(s, 3));
const msgBuff = bigInt.leInt2Buff(msg, 32);
const msgBuff = utils.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);
let r = utils.leBuff2int(rBuff);
const Fr = new F1Field(babyJub.subOrder);
r = Fr.e(r);
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);
const S = Fr.add(r , Fr.mul(hm, s));
return {
R8: R8,
S: S
@@ -78,16 +83,17 @@ function signMiMC(prv, msg) {
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 s = utils.leBuff2int(sBuff);
const A = babyJub.mulPointEscalar(babyJub.Base8, Scalar.shr(s, 3));
const msgBuff = bigInt.leInt2Buff(msg, 32);
const msgBuff = utils.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);
let r = utils.leBuff2int(rBuff);
const Fr = new F1Field(babyJub.subOrder);
r = Fr.e(r);
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);
const S = Fr.add(r , Fr.mul(hm, s));
return {
R8: R8,
S: S
@@ -97,17 +103,17 @@ function signMiMCSponge(prv, msg) {
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 s = utils.leBuff2int(sBuff);
const A = babyJub.mulPointEscalar(babyJub.Base8, Scalar.shr(s, 3));
const msgBuff = bigInt.leInt2Buff(msg, 32);
const msgBuff = utils.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);
let r = utils.leBuff2int(rBuff);
const Fr = new F1Field(babyJub.subOrder);
r = Fr.e(r);
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);
const hm = poseidon([R8[0], R8[1], A[0], A[1], msg]);
const S = Fr.add(r , Fr.mul(hm, s));
return {
R8: R8,
S: S
@@ -128,14 +134,14 @@ function verify(msg, sig, A) {
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 hm = utils.leBuff2int(hmBuff);
const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
let Pright = babyJub.mulPointEscalar(A, Scalar.mul(hm,8));
Pright = babyJub.addPoint(sig.R8, Pright);
if (!Pleft[0].equals(Pright[0])) return false;
if (!Pleft[1].equals(Pright[1])) return false;
if (!babyJub.F.eq(Pleft[0],Pright[0])) return false;
if (!babyJub.F.eq(Pleft[1],Pright[1])) return false;
return true;
}
@@ -153,11 +159,11 @@ function verifyMiMC(msg, sig, A) {
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")));
let Pright = babyJub.mulPointEscalar(A, Scalar.mul(hm, 8));
Pright = babyJub.addPoint(sig.R8, Pright);
if (!Pleft[0].equals(Pright[0])) return false;
if (!Pleft[1].equals(Pright[1])) return false;
if (!babyJub.F.eq(Pleft[0],Pright[0])) return false;
if (!babyJub.F.eq(Pleft[1],Pright[1])) return false;
return true;
}
@@ -173,15 +179,14 @@ function verifyPoseidon(msg, sig, A) {
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 hm = poseidon([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")));
let Pright = babyJub.mulPointEscalar(A, Scalar.mul(hm, 8));
Pright = babyJub.addPoint(sig.R8, Pright);
if (!Pleft[0].equals(Pright[0])) return false;
if (!Pleft[1].equals(Pright[1])) return false;
if (!babyJub.F.eq(Pleft[0],Pright[0])) return false;
if (!babyJub.F.eq(Pleft[1],Pright[1])) return false;
return true;
}
@@ -199,24 +204,24 @@ function verifyMiMCSponge(msg, sig, A) {
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")));
let Pright = babyJub.mulPointEscalar(A, hm.times(bigInt("8")));
Pright = babyJub.addPoint(sig.R8, Pright);
if (!Pleft[0].equals(Pright[0])) return false;
if (!Pleft[1].equals(Pright[1])) return false;
if (!babyJub.F.eq(Pleft[0],Pright[0])) return false;
if (!babyJub.F.eq(Pleft[1],Pright[1])) return false;
return true;
}
function packSignature(sig) {
const R8p = babyJub.packPoint(sig.R8);
const Sp = bigInt.leInt2Buff(sig.S, 32);
const Sp = utils.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))
S: utils.leBuff2int(sigBuff.slice(32,64))
};
}

View File

@@ -154,6 +154,17 @@ class Contract {
}
push(data) {
if (typeof data === "number") {
let isNeg;
if (data<0) {
isNeg = true;
data = -data;
}
data = data.toString(16);
if (data.length % 2 == 1) data = "0" + data;
data = "0x" + data;
if (isNeg) data = "-"+data;
}
const d = Web3Utils.hexToBytes(Web3Utils.toHex(data));
if (d.length == 0 || d.length > 32) {
throw new Error("Assertion failed");

View File

@@ -4,7 +4,6 @@
const Contract = require("./evmasm");
const G2 = require("snarkjs").bn128.G2;
const bigInt = require("snarkjs").bigInt;
function toHex256(a) {
@@ -539,7 +538,7 @@ function createCode(P, w) {
function storeVals() {
C.push(VAR_POINTS); // p
for (let i=0; i<NPOINTS; i++) {
const MP = G2.affine(G2.mulScalar(P, bigInt(i)));
const MP = G2.affine(G2.mulScalar(P, 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

View File

@@ -1,7 +1,9 @@
const bn128 = require("snarkjs").bn128;
const bigInt = require("snarkjs").bigInt;
const Scalar = require("ffjavascript").Scalar;
const ZqField = require("ffjavascript").ZqField;
const Web3Utils = require("web3-utils");
const F = bn128.Fr;
const F = new ZqField(Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
exports.F = F;
const SEED = "mimc";
const NROUNDS = 91;
@@ -9,8 +11,8 @@ 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);
const cn = Scalar.FromString(Web3Utils.toBN(c).toString());
const iv = cn.mod(F.p);
return iv;
};
@@ -22,26 +24,26 @@ exports.getConstants = (seed, nRounds) => {
for (let i=1; i<nRounds; i++) {
c = Web3Utils.keccak256(c);
const n1 = Web3Utils.toBN(c).mod(Web3Utils.toBN(F.q.toString()));
const n1 = Web3Utils.toBN(c).mod(Web3Utils.toBN(F.p.toString()));
const c2 = Web3Utils.padLeft(Web3Utils.toHex(n1), 64);
cts[i] = bigInt(Web3Utils.toBN(c2).toString());
cts[i] = Scalar.fromString(Web3Utils.toBN(c2).toString());
}
cts[0] = bigInt(0);
cts[0] = F.e(0);
return cts;
};
const cts = exports.getConstants(SEED, 91);
exports.hash = (_x_in, _k) =>{
const x_in = bigInt(_x_in);
const k = bigInt(_k);
const x_in = F.e(_x_in);
const k = F.e(_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);
r = F.pow(t, 7);
}
return F.affine(F.add(r, k));
return F.add(r, k);
};
exports.multiHash = (arr, key) => {
@@ -57,8 +59,8 @@ exports.multiHash = (arr, key) => {
r,
arr[i]
),
exports.hash(bigInt(arr[i]), r)
exports.hash(F.e(arr[i]), r)
);
}
return F.affine(r);
return r;
};

View File

@@ -1,7 +1,7 @@
const bn128 = require("snarkjs").bn128;
const bigInt = require("snarkjs").bigInt;
const Scalar = require("ffjavascript").Scalar
const Web3Utils = require("web3-utils");
const F = bn128.Fr;
const ZqField = require("ffjavascript").ZqField;
const F = new ZqField(Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
const SEED = "mimcsponge";
const NROUNDS = 220;
@@ -9,8 +9,8 @@ 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);
const cn = Scalar.fromString(Web3Utils.toBN(c).toString());
const iv = cn.mod(F.p);
return iv;
};
@@ -22,35 +22,35 @@ exports.getConstants = (seed, nRounds) => {
for (let i=1; i<nRounds; i++) {
c = Web3Utils.keccak256(c);
const n1 = Web3Utils.toBN(c).mod(Web3Utils.toBN(F.q.toString()));
const n1 = Web3Utils.toBN(c).mod(Web3Utils.toBN(F.p.toString()));
const c2 = Web3Utils.padLeft(Web3Utils.toHex(n1), 64);
cts[i] = bigInt(Web3Utils.toBN(c2).toString());
cts[i] = F.e(Web3Utils.toBN(c2).toString());
}
cts[0] = bigInt(0);
cts[cts.length - 1] = bigInt(0);
cts[0] = F.e(0);
cts[cts.length - 1] = F.e(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);
let xL = F.e(_xL_in);
let xR = F.e(_xR_in);
const k = F.e(_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);
const xR_tmp = F.e(xR);
if (i < (NROUNDS - 1)) {
xR = xL;
xL = F.add(xR_tmp, F.exp(t, 5));
xL = F.add(xR_tmp, F.pow(t, 5));
} else {
xR = F.add(xR_tmp, F.exp(t, 5));
xR = F.add(xR_tmp, F.pow(t, 5));
}
}
return {
xL: F.affine(xL),
xR: F.affine(xR),
xL: F.normalize(xL),
xR: F.normalize(xR),
};
};
@@ -66,7 +66,7 @@ exports.multiHash = (arr, key, numOutputs) => {
let C = F.zero;
for (let i=0; i<arr.length; i++) {
R = F.add(R, bigInt(arr[i]));
R = F.add(R, F.e(arr[i]));
const S = exports.hash(R, C, key);
R = S.xL;
C = S.xR;
@@ -79,8 +79,8 @@ exports.multiHash = (arr, key, numOutputs) => {
outputs.push(R);
}
if (numOutputs == 1) {
return F.affine(outputs[0]);
return F.normalize(outputs[0]);
} else {
return outputs.map(x => F.affine(x));
return outputs.map(x => F.normalize(x));
}
};

View File

@@ -1,7 +1,7 @@
const bn128 = require("snarkjs").bn128;
const bigInt = require("snarkjs").bigInt;
const babyJub = require("./babyjub");
const createBlakeHash = require("blake-hash");
const blake2b = require("blake2b");
const Scalar = require("ffjavascript").Scalar;
const GENPOINT_PREFIX = "PedersenGenerator";
const windowSize = 4;
@@ -10,13 +10,23 @@ const nWindowsPerSegment = 50;
exports.hash = pedersenHash;
exports.getBasePoint = getBasePoint;
function pedersenHash(msg) {
function baseHash(type, S) {
if (type == "blake") {
return createBlakeHash("blake256").update(S).digest();
} else if (type == "blake2b") {
return Buffer.from(blake2b(32).update(Buffer.from(S)).digest());
}
}
function pedersenHash(msg, options) {
options = options || {};
options.baseHash = options.baseHash || "blake";
const bitsPerSegment = windowSize*nWindowsPerSegment;
const bits = buffer2bits(msg);
const nSegments = Math.floor((bits.length - 1)/(windowSize*nWindowsPerSegment)) +1;
let accP = [bigInt.zero,bigInt.one];
let accP = [babyJub.F.zero,babyJub.F.one];
for (let s=0; s<nSegments; s++) {
let nWindows;
@@ -25,32 +35,32 @@ function pedersenHash(msg) {
} else {
nWindows = nWindowsPerSegment;
}
let escalar = bigInt.zero;
let exp = bigInt.one;
let escalar = Scalar.e(0);
let exp = Scalar.e(1);
for (let w=0; w<nWindows; w++) {
let o = s*bitsPerSegment + w*windowSize;
let acc = bigInt.one;
let acc = Scalar.e(1);
for (let b=0; ((b<windowSize-1)&&(o<bits.length)) ; b++) {
if (bits[o]) {
acc = acc.add( bigInt.one.shl(b) );
acc = Scalar.add(acc, Scalar.shl(Scalar.e(1), b) );
}
o++;
}
if (o<bits.length) {
if (bits[o]) {
acc = acc.neg();
acc = Scalar.neg(acc);
}
o++;
}
escalar = escalar.add(acc.mul(exp));
exp = exp.shl(windowSize+1);
escalar = Scalar.add(escalar, Scalar.mul(acc, exp));
exp = Scalar.shl(exp, windowSize+1);
}
if (escalar.lesser(bigInt.zero)) {
escalar = babyJub.subOrder.add(escalar);
if (Scalar.lt(escalar, 0)) {
escalar = Scalar.add( escalar, babyJub.subOrder);
}
accP = babyJub.addPoint(accP, babyJub.mulPointEscalar(getBasePoint(s), escalar));
accP = babyJub.addPoint(accP, babyJub.mulPointEscalar(getBasePoint(options.baseHash, s), escalar));
}
return babyJub.packPoint(accP);
@@ -58,13 +68,13 @@ function pedersenHash(msg) {
let bases = [];
function getBasePoint(pointIdx) {
function getBasePoint(baseHashType, 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();
const h = baseHash(baseHashType, S);
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++;

View File

@@ -7,7 +7,15 @@ if (typeof process.argv[2] != "undefined") {
nBases = 5;
}
let baseHash;
if (typeof process.argv[3] != "undefined") {
baseHash = process.argv[3];
} else {
baseHash = "blake";
}
for (let i=0; i < nBases; i++) {
const p = pedersenHash.getBasePoint(i);
const p = pedersenHash.getBasePoint(baseHash, i);
console.log(`[${p[0]},${p[1]}]`);
}

View File

@@ -1,116 +1,49 @@
const bn128 = require("snarkjs").bn128;
const bigInt = require("snarkjs").bigInt;
const blake2b = require('blake2b');
const assert = require("assert");
const F = bn128.Fr;
const Scalar = require("ffjavascript").Scalar;
const ZqField = require("ffjavascript").ZqField;
const { unstringifyBigInts } = require("ffjavascript").utils;
const SEED = "poseidon";
const NROUNDSF = 8;
const NROUNDSP = 57;
const T = 6;
// Prime 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
const F = new ZqField(Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
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()
}
// Parameters are generated by a reference script https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/generate_parameters_grain.sage
// Used like so: sage generate_parameters_grain.sage 1 0 254 2 8 56 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
const { C, M } = unstringifyBigInts(require("./poseidon_constants.json"));
return res;
}
// Using recommended parameters from whitepaper https://eprint.iacr.org/2019/458.pdf (table 2, table 8)
// Generated by https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/calc_round_numbers.py
// And rounded up to nearest integer that divides by t
const N_ROUNDS_F = 8;
const N_ROUNDS_P = [56, 57, 56, 60, 60, 63, 64, 63];
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;
}
const pow5 = a => F.mul(a, F.square(F.square(a, a)));
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);
function poseidon(inputs) {
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;
assert(inputs.length < N_ROUNDS_P.length - 1);
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]);
const t = inputs.length + 1;
const nRoundsF = N_ROUNDS_F;
const nRoundsP = N_ROUNDS_P[t - 2];
let state = [...inputs.map(a => F.e(a)), F.zero];
for (let r = 0; r < nRoundsF + nRoundsP; r++) {
state = state.map((a, i) => F.add(a, C[t - 2][r * t + i]));
if (r < nRoundsF / 2 || r >= nRoundsF / 2 + nRoundsP) {
state = state.map(a => pow5(a));
} else {
state[0] = sigma(state[0]);
state[0] = pow5(state[0]);
}
mix(state, M);
// no matrix multiplication in the last round
if (r < nRoundsF + nRoundsP - 1) {
state = state.map((_, i) =>
state.reduce((acc, a, j) => F.add(acc, F.mul(M[t - 2][j][i], a)), F.zero)
);
}
}
return F.normalize(state[0]);
}
return F.affine(state[0]);
};
};
module.exports = poseidon;

3449
src/poseidon_constants.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2,14 +2,14 @@
// License: LGPL-3.0+
//
const Poseidon = require("./poseidon.js");
const Contract = require("./evmasm");
const { unstringifyBigInts } = require("ffjavascript").utils;
const Web3Utils = require("web3-utils");
const SEED = "poseidon";
const NROUNDSF = 8;
const NROUNDSP = 57;
const T = 6;
const { C:K, M } = unstringifyBigInts(require("./poseidon_constants.json"));
const N_ROUNDS_F = 8;
const N_ROUNDS_P = [56, 57, 56, 60, 60, 63, 64, 63];
function toHex256(a) {
let S = a.toString(16);
@@ -17,38 +17,34 @@ function toHex256(a) {
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;
function createCode(nInputs) {
const K = Poseidon.getConstants(t, seed, nRoundsP + nRoundsF);
const M = Poseidon.getMatrix(t, seed, nRoundsP + nRoundsF);
if (( nInputs<1) || (nInputs>8)) throw new Error("Invalid number of inputs. Must be 1<=nInputs<=8");
const t = nInputs + 1;
const nRoundsF = N_ROUNDS_F;
const nRoundsP = N_ROUNDS_P[t - 2];
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(toHex256(M[t-2][j][i]));
C.push((1+i*t+j)*32);
C.mstore();
}
}
}
function ark(r) {
C.push(toHex256(K[r])); // K, st, q
function ark(r) { // 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.dup(t); // q, st, q
C.push(toHex256(K[t-2][r*t+i])); // K, q, st, q
C.dup(2+i); // st[i], K, q, st, q
C.addmod(); // newSt[i], st, q
C.swap(1 + i); // xx, st, q
C.pop();
}
C.pop();
}
function sigma(p) {
@@ -104,8 +100,13 @@ function createCode(t, nRoundsF, nRoundsP, seed) {
C.push(0);
C.calldataload();
C.div();
C.push("0xc4420fb4"); // poseidon(uint256[])
C.dup(0);
C.push(Web3Utils.keccak256(`poseidon(uint256[${nInputs}])`).slice(0, 10)); // poseidon(uint256[n])
C.eq();
C.swap(1);
C.push(Web3Utils.keccak256(`poseidon(bytes32[${nInputs}])`).slice(0, 10)); // poseidon(bytes32[n])
C.eq();
C.or();
C.jmpi("start");
C.invalid();
@@ -115,17 +116,16 @@ function createCode(t, nRoundsF, nRoundsP, seed) {
C.push("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"); // q
// Load 6 values from the call data.
// Load t 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.
// [Selector (4)] [item1 (32)] [item2 (32)] ....
// Stack positions 0-nInputs.
for (let i=0; i<t; i++) {
C.push(0x44+(0x20*(5-i)));
C.push(0x04+(0x20*(nInputs-i)));
C.calldataload();
}
for (let i=0; i<nRoundsF+nRoundsP; i++) {
for (let i=0; i<nRoundsF+nRoundsP-1; i++) {
ark(i);
if ((i<nRoundsF/2) || (i>=nRoundsP+nRoundsF/2)) {
for (let j=0; j<t; j++) {
@@ -142,6 +142,13 @@ function createCode(t, nRoundsF, nRoundsP, seed) {
C.label(strLabel);
}
C.push(toHex256(K[t-2][(nRoundsF+nRoundsP-1)*t])); // K, st, q
C.dup(t+1); // q, K, st, q
C.swap(2); // st[0], K, q, st\st[0]
C.addmod(); // st q
sigma(0);
C.push("0x00");
C.mstore(); // Save it to pos 0;
C.push("0x20");
@@ -153,18 +160,42 @@ function createCode(t, nRoundsF, nRoundsP, seed) {
return C.createTxData();
}
module.exports.abi = [
function generateABI(nInputs) {
return [
{
"constant": true,
"inputs": [
{
"internalType": `bytes32[${nInputs}]`,
"name": "input",
"type": "uint256[]"
"type": `bytes32[${nInputs}]`
}
],
"name": "poseidon",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"payable": false,
"stateMutability": "pure",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"internalType": `uint256[${nInputs}]`,
"name": "input",
"type": `uint256[${nInputs}]`
}
],
"name": "poseidon",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
@@ -174,7 +205,9 @@ module.exports.abi = [
"type": "function"
}
];
}
module.exports.generateABI = generateABI;
module.exports.createCode = createCode;

View File

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

View File

@@ -1,5 +1,13 @@
const poseidonGenContract = require("./poseidon_gencontract");
if (process.argv.length != 3) {
console.log("Usage: node poseidon_gencontract.js [numberOfInputs]");
process.exit(1);
}
console.log(poseidonGenContract.createCode(6, 8, 57));
const nInputs = Number(process.argv[2]);
console.log(nInputs);
console.log(poseidonGenContract.createCode(nInputs));

View File

@@ -1,7 +1,6 @@
const bigInt = require("snarkjs").bigInt;
const Scalar = require("ffjavascript").Scalar;
const SMTMemDB = require("./smt_memdb");
const {hash0, hash1} = require("./smt_hashes_poseidon");
const {hash0, hash1, F} = require("./smt_hashes_poseidon");
class SMT {
@@ -11,18 +10,7 @@ class SMT {
}
_splitBits(_key) {
let k = bigInt(_key);
const res = [];
while (!k.isZero()) {
if (k.isOdd()) {
res.push(true);
} else {
res.push(false);
}
k = k.shr(1);
}
const res = Scalar.bits(_key);
while (res.length<256) res.push(false);
@@ -30,8 +18,8 @@ class SMT {
}
async update(_key, _newValue) {
const key = bigInt(_key);
const newValue = bigInt(_newValue);
const key = Scalar.e(_key);
const newValue = F.e(_newValue);
const resFind = await this.find(key);
@@ -70,16 +58,16 @@ class SMT {
res.newRoot = rtNew;
await this.db.multiDel(dels);
await this.db.multiIns(ins);
await this.db.setRoot(rtNew);
this.root = rtNew;
await this.db.multiDel(dels);
return res;
}
async delete(_key) {
const key = bigInt(_key);
const key = Scalar.e(_key);
const resFind = await this.find(key);
if (!resFind.found) throw new Error("Key does not exists");
@@ -99,7 +87,7 @@ class SMT {
let mixed;
if (resFind.siblings.length > 0) {
const record = await this.db.get(resFind.siblings[resFind.siblings.length - 1]);
if ((record.length == 3)&&(record[0].equals(bigInt.one))) {
if ((record.length == 3)&&(F.eq(record[0], F.one))) {
mixed = false;
res.oldKey = record[1];
res.oldValue = record[2];
@@ -108,16 +96,16 @@ class SMT {
} else if (record.length == 2) {
mixed = true;
res.oldKey = key;
res.oldValue = bigInt(0);
res.oldValue = F.zero;
res.isOld0 = true;
rtNew = bigInt.zero;
rtNew = F.zero;
} else {
throw new Error("Invalid node. Database corrupted");
}
} else {
rtNew = bigInt.zero;
rtNew = F.zero;
res.oldKey = key;
res.oldValue = bigInt(0);
res.oldValue = F.zero;
res.isOld0 = true;
}
@@ -126,7 +114,7 @@ class SMT {
for (let level = resFind.siblings.length-1; level >=0; level--) {
let newSibling = resFind.siblings[level];
if ((level == resFind.siblings.length-1)&&(!res.isOld0)) {
newSibling = bigInt.zero;
newSibling = F.zero;
}
const oldSibling = resFind.siblings[level];
if (keyBits[level]) {
@@ -135,7 +123,7 @@ class SMT {
rtOld = hash0(rtOld, oldSibling);
}
dels.push(rtOld);
if (!newSibling.isZero()) {
if (!F.isZero(newSibling)) {
mixed = true;
}
@@ -164,8 +152,8 @@ class SMT {
}
async insert(_key, _value) {
const key = bigInt(_key);
const value = bigInt(_value);
const key = Scalar.e(_key);
const value = F.e(_value);
let addedOne = false;
const res = {};
res.oldRoot = this.root;
@@ -183,7 +171,7 @@ class SMT {
if (!resFind.isOld0) {
const oldKeyits = this._splitBits(resFind.notFoundKey);
for (let i= res.siblings.length; oldKeyits[i] == newKeyBits[i]; i++) {
res.siblings.push(bigInt.zero);
res.siblings.push(F.zero);
}
rtOld = hash1(resFind.notFoundKey, resFind.notFoundValue);
res.siblings.push(rtOld);
@@ -191,7 +179,7 @@ class SMT {
mixed = false;
} else if (res.siblings.length >0) {
mixed = true;
rtOld = bigInt.zero;
rtOld = F.zero;
}
const inserts = [];
@@ -201,7 +189,7 @@ class SMT {
inserts.push([rt,[1, key, value]] );
for (let i=res.siblings.length-1; i>=0; i--) {
if ((i<res.siblings.length-1)&&(!res.siblings[i].isZero())) {
if ((i<res.siblings.length-1)&&(!F.isZero(res.siblings[i]))) {
mixed = true;
}
if (mixed) {
@@ -227,7 +215,7 @@ class SMT {
}
if (addedOne) res.siblings.pop();
while ((res.siblings.length>0) && (res.siblings[res.siblings.length-1].isZero())) {
while ((res.siblings.length>0) && (F.isZero(res.siblings[res.siblings.length-1]))) {
res.siblings.pop();
}
res.oldKey = resFind.notFoundKey;
@@ -253,12 +241,12 @@ class SMT {
if (typeof root === "undefined") root = this.root;
let res;
if (root.isZero()) {
if (F.isZero(root)) {
res = {
found: false,
siblings: [],
notFoundKey: key,
notFoundValue: bigInt.zero,
notFoundValue: F.zero,
isOld0: true
};
return res;
@@ -266,8 +254,8 @@ class SMT {
const record = await this.db.get(root);
if ((record.length==3)&&(record[0].equals(bigInt.one))) {
if (record[1].equals(key)) {
if ((record.length==3)&&(F.eq(record[0],F.one))) {
if (F.eq(record[1],key)) {
res = {
found: true,
siblings: [],
@@ -309,3 +297,5 @@ async function newMemEmptyTrie() {
module.exports.loadFromFile = loadFromFile;
module.exports.newMemEmptyTrie = newMemEmptyTrie;
module.exports.SMT = SMT;
module.exports.SMTMemDB = SMTMemDB;

View File

@@ -1,5 +1,5 @@
const mimc7 = require("./mimc7");
const bigInt = require("snarkjs").bigInt;
const bigInt = require("big-integer");
exports.hash0 = function (left, right) {
return mimc7.multiHash(left, right);
@@ -8,3 +8,5 @@ exports.hash0 = function (left, right) {
exports.hash1 = function(key, value) {
return mimc7.multiHash([key, value], bigInt.one);
};
exports.F = mimc7.F;

View File

@@ -1,12 +1,18 @@
const Poseidon = require("./poseidon");
const bigInt = require("snarkjs").bigInt;
const hash = Poseidon.createHash(6, 8, 57);
const ZqField = require("ffjavascript").ZqField;
const Scalar = require("ffjavascript").Scalar;
const poseidon = require("./poseidon");
const F = new ZqField(Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
exports.hash0 = function (left, right) {
return hash([left, right]);
return poseidon([left, right]);
};
exports.hash1 = function(key, value) {
return hash([key, value, bigInt.one]);
return poseidon([key, value, F.one]);
};
exports.F = F;

View File

@@ -1,9 +1,14 @@
const bigInt = require("snarkjs").bigInt;
const Scalar = require("ffjavascript").Scalar;
const ZqField = require("ffjavascript").ZqField;
// Prime 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
const F = new ZqField(Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
class SMTMemDb {
constructor() {
this.nodes = {};
this.root = bigInt(0);
this.root = F.zero;
}
async getRoot() {
@@ -12,13 +17,13 @@ class SMTMemDb {
_key2str(k) {
// const keyS = bigInt(key).leInt2Buff(32).toString("hex");
const keyS = bigInt(k).toString();
const keyS = k.toString();
return keyS;
}
_normalize(n) {
for (let i=0; i<n.length; i++) {
n[i] = bigInt(n[i]);
n[i] = F.e(n[i]);
}
}
@@ -27,6 +32,14 @@ class SMTMemDb {
return this.nodes[keyS];
}
async multiGet(keys) {
const promises = [];
for (let i=0; i<keys.length; i++) {
promises.push(this.get(keys[i]));
}
return await Promise.all(promises);
}
async setRoot(rt) {
this.root = rt;
}

View File

@@ -1,11 +1,15 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
const Scalar = require("ffjavascript").Scalar;
const F1Field = require("ffjavascript").F1Field;
const utils = require("ffjavascript").utils;
const q = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
const F = new F1Field(q);
const tester = require("circom").tester;
function print(circuit, w, s) {
console.log(s + ": " + w[circuit.getSignalIdx(s)]);
@@ -14,60 +18,59 @@ function print(circuit, w, s) {
function getBits(v, n) {
const res = [];
for (let i=0; i<n; i++) {
if (v.shr(i).isOdd()) {
res.push(bigInt.one);
if (Scalar.isOdd(Scalar.shr(v,i))) {
res.push(F.one);
} else {
res.push(bigInt.zero);
res.push(F.zero);
}
}
return res;
}
const q = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
describe("Aliascheck test", () => {
let circuit;
describe("Aliascheck test", function () {
this.timeout(100000);
let cir;
before( async() => {
const cirDef = await compiler(path.join(__dirname, "circuits", "aliascheck_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains: " + circuit.nConstraints);
cir = await tester(path.join(__dirname, "circuits", "aliascheck_test.circom"));
});
it("Satisfy the aliastest 0", async () => {
const inp = getBits(bigInt.zero, 254);
circuit.calculateWitness({in: inp});
const inp = getBits(0, 254);
await cir.calculateWitness({in: inp}, true);
});
it("Satisfy the aliastest 3", async () => {
const inp = getBits(bigInt(3), 254);
circuit.calculateWitness({in: inp});
const inp = getBits(3, 254);
await cir.calculateWitness({in: inp}, true);
});
it("Satisfy the aliastest q-1", async () => {
const inp = getBits(q.sub(bigInt.one), 254);
circuit.calculateWitness({in: inp});
const inp = getBits(F.minusone, 254);
// console.log(JSON.stringify(utils.stringifyBigInts(inp)));
await cir.calculateWitness({in: inp}, true);
});
it("Nhot not satisfy an input of q", async () => {
it("Should not satisfy an input of q", async () => {
const inp = getBits(q, 254);
try {
circuit.calculateWitness({in: inp});
await cir.calculateWitness({in: inp}, true);
assert(false);
} catch(err) {
assert.equal(err.message, "Constraint doesn't match: 1 != 0");
assert(/Constraint\sdoesn't\smatch(.*)1\s!=\s0/.test(err.message) );
}
});
it("Nhot not satisfy all ones", async () => {
it("Should not satisfy all ones", async () => {
const inp = getBits(bigInt(1).shl(254).sub(bigInt(1)), 254);
const inp = getBits(Scalar.sub(Scalar.shl(1, 254) , 1) , 254);
try {
circuit.calculateWitness({in: inp});
await cir.calculateWitness({in: inp}, true);
assert(false);
} catch(err) {
assert.equal(err.message, "Constraint doesn't match: 1 != 0");
assert(/Constraint\sdoesn't\smatch(.*)1\s!=\s0/.test(err.message) );
}
});

View File

@@ -1,106 +1,93 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const createBlakeHash = require("blake-hash");
const eddsa = require("../src/eddsa.js");
const F = require("../src/babyjub.js").F;
const assert = chai.assert;
const bigInt = require("snarkjs").bigInt;
const tester = require("circom").tester;
const utils = require("ffjavascript").utils;
const Scalar = require("ffjavascript").Scalar;
describe("Baby Jub test", function () {
let circuitAdd;
let circuitTest;
let circuitPbk;
this.timeout(100000);
before( async() => {
const cirDefAdd = await compiler(path.join(__dirname, "circuits", "babyadd_tester.circom"));
circuitAdd = new snarkjs.Circuit(cirDefAdd);
console.log("NConstrains BabyAdd: " + circuitAdd.nConstraints);
circuitAdd = await tester(path.join(__dirname, "circuits", "babyadd_tester.circom"));
const cirDefTest = await compiler(path.join(__dirname, "circuits", "babycheck_test.circom"));
circuitTest = new snarkjs.Circuit(cirDefTest);
console.log("NConstrains BabyTest: " + circuitTest.nConstraints);
const cirDefPbk = await compiler(path.join(__dirname, "circuits", "babypbk_test.circom"));
circuitPbk = new snarkjs.Circuit(cirDefPbk);
console.log("NConstrains BabyPbk: " + circuitPbk.nConstraints);
circuitTest = await tester(path.join(__dirname, "circuits", "babycheck_test.circom"));
circuitPbk = await tester(path.join(__dirname, "circuits", "babypbk_test.circom"));
});
it("Should add point (0,1) and (0,1)", async () => {
const input={
x1: snarkjs.bigInt(0),
y1: snarkjs.bigInt(1),
x2: snarkjs.bigInt(0),
y2: snarkjs.bigInt(1)
x1: F.e(0),
y1: F.e(1),
x2: F.e(0),
y2: F.e(1)
};
const w = circuitAdd.calculateWitness(input);
const w = await circuitAdd.calculateWitness(input, true);
const xout = w[circuitAdd.getSignalIdx("main.xout")];
const yout = w[circuitAdd.getSignalIdx("main.yout")];
assert(xout.equals(0));
assert(yout.equals(1));
await circuitAdd.assertOut(w, {xout: F.e(0), yout: F.e(1)});
});
it("Should add 2 same numbers", async () => {
const input={
x1: snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
y1: snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
x2: snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
y2: snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475")
x1: F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
y1: F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
x2: F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
y2: F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475")
};
const w = circuitAdd.calculateWitness(input);
const w = await circuitAdd.calculateWitness(input, true);
const xout = w[circuitAdd.getSignalIdx("main.xout")];
const yout = w[circuitAdd.getSignalIdx("main.yout")];
await circuitAdd.assertOut(w, {
xout: F.e("6890855772600357754907169075114257697580319025794532037257385534741338397365"),
yout: F.e("4338620300185947561074059802482547481416142213883829469920100239455078257889")
});
assert(xout.equals(snarkjs.bigInt("6890855772600357754907169075114257697580319025794532037257385534741338397365")));
assert(yout.equals(snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889")));
});
it("Should add 2 different numbers", async () => {
const input={
x1: snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
y1: snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
x2: snarkjs.bigInt("16540640123574156134436876038791482806971768689494387082833631921987005038935"),
y2: snarkjs.bigInt("20819045374670962167435360035096875258406992893633759881276124905556507972311")
x1: F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
y1: F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
x2: F.e("16540640123574156134436876038791482806971768689494387082833631921987005038935"),
y2: F.e("20819045374670962167435360035096875258406992893633759881276124905556507972311")
};
const w = circuitAdd.calculateWitness(input);
const w = await circuitAdd.calculateWitness(input, true);
const xout = w[circuitAdd.getSignalIdx("main.xout")];
const yout = w[circuitAdd.getSignalIdx("main.yout")];
/*
console.log(xout.toString());
console.log(yout.toString());
*/
assert(xout.equals(snarkjs.bigInt("7916061937171219682591368294088513039687205273691143098332585753343424131937")));
assert(yout.equals(snarkjs.bigInt("14035240266687799601661095864649209771790948434046947201833777492504781204499")));
await circuitAdd.assertOut(w, {
xout: F.e("7916061937171219682591368294088513039687205273691143098332585753343424131937"),
yout: F.e("14035240266687799601661095864649209771790948434046947201833777492504781204499")
});
it("Should check 0 is a valid poiny", async() => {
const w = circuitTest.calculateWitness({x: 0, y:1});
assert(circuitTest.checkWitness(w));
});
it("Should check 0 is an invalid poiny", async() => {
it("Should check (0,1) is a valid point", async() => {
const w = await circuitTest.calculateWitness({x: 0, y:1}, true);
await circuitTest.checkConstraints(w);
});
it("Should check (1,0) is an invalid point", async() => {
try {
circuitTest.calculateWitness({x: 1, y: 0});
await circuitTest.calculateWitness({x: 1, y: 0}, true);
assert(false, "Should be a valid point");
} catch(err) {
assert.equal(err.message, "Constraint doesn't match: 168700 != 1");
assert(/Constraint\sdoesn't\smatch(.*)168700\s!=\s1/.test(err.message) );
}
});
@@ -108,18 +95,19 @@ describe("Baby Jub test", function () {
const rawpvk = Buffer.from("0001020304050607080900010203040506070809000102030405060708090021", "hex");
const pvk = eddsa.pruneBuffer(createBlakeHash("blake512").update(rawpvk).digest().slice(0,32));
const S = bigInt.leBuff2int(pvk).shr(3);
const S = Scalar.shr(utils.leBuff2int(pvk), 3);
const A = eddsa.prv2pub(rawpvk);
const input = {
in : S,
Ax : A[0],
Ay : A[1]
}
in : S
};
const w = circuitPbk.calculateWitness(input);
assert(circuitPbk.checkWitness(w));
const w = await circuitPbk.calculateWitness(input, true);
await circuitPbk.assertOut(w, {Ax : A[0], Ay: A[1]});
await circuitPbk.checkConstraints(w);
});
});

View File

@@ -1,8 +1,6 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const babyjub = require("../src/babyjub.js");
const Scalar = require("ffjavascript").Scalar;
const assert = chai.assert;
@@ -16,16 +14,16 @@ describe("Baby Jub js test", function () {
it("Should add point (0,1) and (0,1)", () => {
const p1 = [
snarkjs.bigInt(0),
snarkjs.bigInt(1)];
babyjub.F.e(0),
babyjub.F.e(1)];
const p2 = [
snarkjs.bigInt(0),
snarkjs.bigInt(1)
babyjub.F.e(0),
babyjub.F.e(1)
];
const out = babyjub.addPoint(p1, p2)
assert(out[0].equals(0));
assert(out[1].equals(1));
const out = babyjub.addPoint(p1, p2);
assert(babyjub.F.eq(out[0], babyjub.F.zero));
assert(babyjub.F.eq(out[1], babyjub.F.one));
});
it("Should base be 8*generator", () => {
@@ -34,50 +32,50 @@ describe("Baby Jub js test", function () {
res = babyjub.addPoint(res, res);
res = babyjub.addPoint(res, res);
assert(res[0].equals(babyjub.Base8[0]));
assert(res[1].equals(babyjub.Base8[1]));
assert(babyjub.F.eq(res[0], babyjub.Base8[0]));
assert(babyjub.F.eq(res[1], babyjub.Base8[1]));
});
it("Should add 2 same numbers", () => {
const p1 = [
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
babyjub.F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
babyjub.F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
];
const p2 = [
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
babyjub.F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
babyjub.F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
];
const out = babyjub.addPoint(p1, p2)
assert(out[0].equals(snarkjs.bigInt("6890855772600357754907169075114257697580319025794532037257385534741338397365")));
assert(out[1].equals(snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889")));
const out = babyjub.addPoint(p1, p2);
assert(babyjub.F.eq(out[0], babyjub.F.e("6890855772600357754907169075114257697580319025794532037257385534741338397365")));
assert(babyjub.F.eq(out[1], babyjub.F.e("4338620300185947561074059802482547481416142213883829469920100239455078257889")));
});
it("Should add 2 different numbers", () => {
const p1 = [
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
babyjub.F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
babyjub.F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
];
const p2 = [
snarkjs.bigInt("16540640123574156134436876038791482806971768689494387082833631921987005038935"),
snarkjs.bigInt("20819045374670962167435360035096875258406992893633759881276124905556507972311"),
babyjub.F.e("16540640123574156134436876038791482806971768689494387082833631921987005038935"),
babyjub.F.e("20819045374670962167435360035096875258406992893633759881276124905556507972311"),
];
const out = babyjub.addPoint(p1, p2)
const out = babyjub.addPoint(p1, p2);
assert(babyjub.F.eq(out[0], babyjub.F.e("7916061937171219682591368294088513039687205273691143098332585753343424131937")));
assert(babyjub.F.eq(out[1], babyjub.F.e("14035240266687799601661095864649209771790948434046947201833777492504781204499")));
assert(out[0].equals(snarkjs.bigInt("7916061937171219682591368294088513039687205273691143098332585753343424131937")));
assert(out[1].equals(snarkjs.bigInt("14035240266687799601661095864649209771790948434046947201833777492504781204499")));
});
it("should mulPointEscalar 0", () => {
const p = [
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
babyjub.F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
babyjub.F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
];
const r = babyjub.mulPointEscalar(p, snarkjs.bigInt("3"));
const r = babyjub.mulPointEscalar(p, 3);
let r2 = babyjub.addPoint(p, p);
r2 = babyjub.addPoint(r2, p);
assert.equal(r2[0].toString(), r[0].toString());
@@ -88,65 +86,65 @@ describe("Baby Jub js test", function () {
it("should mulPointEscalar 1", () => {
const p = [
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
babyjub.F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
babyjub.F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
];
const r = babyjub.mulPointEscalar(p, snarkjs.bigInt("14035240266687799601661095864649209771790948434046947201833777492504781204499"));
const r = babyjub.mulPointEscalar(p, Scalar.fromString("14035240266687799601661095864649209771790948434046947201833777492504781204499"));
assert.equal(r[0].toString(), "17070357974431721403481313912716834497662307308519659060910483826664480189605");
assert.equal(r[1].toString(), "4014745322800118607127020275658861516666525056516280575712425373174125159339");
});
it("should mulPointEscalar 2", () => {
const p = [
snarkjs.bigInt("6890855772600357754907169075114257697580319025794532037257385534741338397365"),
snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889"),
babyjub.F.e("6890855772600357754907169075114257697580319025794532037257385534741338397365"),
babyjub.F.e("4338620300185947561074059802482547481416142213883829469920100239455078257889"),
];
const r = babyjub.mulPointEscalar(p, snarkjs.bigInt("20819045374670962167435360035096875258406992893633759881276124905556507972311"));
const r = babyjub.mulPointEscalar(p, Scalar.fromString("20819045374670962167435360035096875258406992893633759881276124905556507972311"));
assert.equal(r[0].toString(), "13563888653650925984868671744672725781658357821216877865297235725727006259983");
assert.equal(r[1].toString(), "8442587202676550862664528699803615547505326611544120184665036919364004251662");
});
it("should inCurve 1", () => {
const p = [
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
babyjub.F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
babyjub.F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
];
assert(babyjub.inCurve(p));
});
it("should inCurve 2", () => {
const p = [
snarkjs.bigInt("6890855772600357754907169075114257697580319025794532037257385534741338397365"),
snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889"),
babyjub.F.e("6890855772600357754907169075114257697580319025794532037257385534741338397365"),
babyjub.F.e("4338620300185947561074059802482547481416142213883829469920100239455078257889"),
];
assert(babyjub.inCurve(p));
});
it("should inSubgroup 1", () => {
const p = [
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
babyjub.F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
babyjub.F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
];
assert(babyjub.inSubgroup(p));
});
it("should inSubgroup 2", () => {
const p = [
snarkjs.bigInt("6890855772600357754907169075114257697580319025794532037257385534741338397365"),
snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889"),
babyjub.F.e("6890855772600357754907169075114257697580319025794532037257385534741338397365"),
babyjub.F.e("4338620300185947561074059802482547481416142213883829469920100239455078257889"),
];
assert(babyjub.inSubgroup(p));
});
it("should packPoint - unpackPoint 1", () => {
const p = [
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
babyjub.F.e("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
babyjub.F.e("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
];
const buf = babyjub.packPoint(p);
assert.equal(buf.toString('hex'), '53b81ed5bffe9545b54016234682e7b2f699bd42a5e9eae27ff4051bc698ce85');
assert.equal(buf.toString("hex"), "53b81ed5bffe9545b54016234682e7b2f699bd42a5e9eae27ff4051bc698ce85");
const p2 = babyjub.unpackPoint(buf);
assert.equal(p2[0].toString(), "17777552123799933955779906779655732241715742912184938656739573121738514868268");
assert.equal(p2[1].toString(), "2626589144620713026669568689430873010625803728049924121243784502389097019475");
@@ -154,11 +152,11 @@ describe("Baby Jub js test", function () {
it("should packPoint - unpackPoint 2", () => {
const p = [
snarkjs.bigInt("6890855772600357754907169075114257697580319025794532037257385534741338397365"),
snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889"),
babyjub.F.e("6890855772600357754907169075114257697580319025794532037257385534741338397365"),
babyjub.F.e("4338620300185947561074059802482547481416142213883829469920100239455078257889"),
];
const buf = babyjub.packPoint(p);
assert.equal(buf.toString('hex'), 'e114eb17eddf794f063a68fecac515e3620e131976108555735c8b0773929709');
assert.equal(buf.toString("hex"), "e114eb17eddf794f063a68fecac515e3620e131976108555735c8b0773929709");
const p2 = babyjub.unpackPoint(buf);
assert.equal(p2[0].toString(), "6890855772600357754907169075114257697580319025794532037257385534741338397365");
assert.equal(p2[1].toString(), "4338620300185947561074059802482547481416142213883829469920100239455078257889");

View File

@@ -1,55 +1,52 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
const Fr = require("ffjavascript").bn128.Fr;
const Scalar = require("ffjavascript").Scalar;
const tester = require("circom").tester;
function print(circuit, w, s) {
console.log(s + ": " + w[circuit.getSignalIdx(s)]);
}
function checkSub(_a,_b, circuit) {
let a=bigInt(_a);
let b=bigInt(_b);
if (a.lesser(bigInt.zero)) a = a.add(bigInt.one.shl(16));
if (b.lesser(bigInt.zero)) b = b.add(bigInt.one.shl(16));
const w = circuit.calculateWitness({a: a, b: b});
async function checkSub(_a,_b, circuit) {
let a=Scalar.e(_a);
let b=Scalar.e(_b);
if (Scalar.lt(a, 0)) a = Scalar.add(a, Scalar.shl(1, 16));
if (Scalar.lt(b, 0)) b = Scalar.add(b, Scalar.shl(1, 16));
const w = await circuit.calculateWitness({a: a, b: b}, true);
let res = a.sub(b);
if (res.lesser(bigInt.zero)) res = res.add(bigInt.one.shl(16));
assert( w[circuit.getSignalIdx("main.out")].equals(bigInt(res)) );
let res = Scalar.sub(a, b);
if (Scalar.lt(res, 0)) res = Scalar.add(res, Scalar.shl(1, 16));
await circuit.assertOut(w, {out: res});
}
describe("BinSub test", () => {
describe("BinSub test", function () {
this.timeout(100000);
let circuit;
before( async() => {
const cirDef = await compiler(path.join(__dirname, "circuits", "binsub_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains BinSub: " + circuit.nConstraints);
circuit = await tester(path.join(__dirname, "circuits", "binsub_test.circom"));
});
it("Should check variuos ege cases", async () => {
checkSub(0,0, circuit);
checkSub(1,0, circuit);
checkSub(-1,0, circuit);
checkSub(2,1, circuit);
checkSub(2,2, circuit);
checkSub(2,3, circuit);
checkSub(2,-1, circuit);
checkSub(2,-2, circuit);
checkSub(2,-3, circuit);
checkSub(-2,-3, circuit);
checkSub(-2,-2, circuit);
checkSub(-2,-1, circuit);
checkSub(-2,0, circuit);
checkSub(-2,1, circuit);
checkSub(-2,2, circuit);
checkSub(-2,3, circuit);
await checkSub(0,0, circuit);
await checkSub(1,0, circuit);
await checkSub(-1,0, circuit);
await checkSub(2,1, circuit);
await checkSub(2,2, circuit);
await checkSub(2,3, circuit);
await checkSub(2,-1, circuit);
await checkSub(2,-2, circuit);
await checkSub(2,-3, circuit);
await checkSub(-2,-3, circuit);
await checkSub(-2,-2, circuit);
await checkSub(-2,-1, circuit);
await checkSub(-2,0, circuit);
await checkSub(-2,1, circuit);
await checkSub(-2,2, circuit);
await checkSub(-2,3, circuit);
});

View File

@@ -1,35 +1,37 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const crypto = require("crypto");
const compiler = require("circom");
const tester = require("circom").tester;
const Fr = require("ffjavascript").bn128.Fr;
const assert = chai.assert;
describe("Sum test", () => {
describe("Binary sum test", function () {
this.timeout(100000000);
it("Should create a constant circuit", async () => {
const circuit = await tester(path.join(__dirname, "circuits", "constants_test.circom"));
await circuit.loadConstraints();
const cirDef = await compiler(path.join(__dirname, "circuits", "constants_test.circom"));
assert.equal(cirDef.nVars, 2);
assert.equal(circuit.nVars, 2);
assert.equal(circuit.constraints.length, 1);
const circuit = new snarkjs.Circuit(cirDef);
const witness = await circuit.calculateWitness({ "in": Fr.e("d807aa98", 16)}, true);
const witness = circuit.calculateWitness({ "in": "0xd807aa98" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt("0xd807aa98")));
assert(Fr.eq(witness[0],Fr.e(1)));
assert(Fr.eq(witness[1],Fr.e("d807aa98", 16)));
});
it("Should create a sum circuit", async () => {
const circuit = await tester(path.join(__dirname, "circuits", "sum_test.circom"));
await circuit.loadConstraints();
const cirDef = await compiler(path.join(__dirname, "circuits", "sum_test.circom"));
assert.equal(cirDef.nVars, 101);
assert.equal(circuit.constraints.length, 97); // 32 (in1) + 32(in2) + 32(out) + 1 (carry)
const circuit = new snarkjs.Circuit(cirDef);
const witness = await circuit.calculateWitness({ "a": "111", "b": "222" }, true);
const witness = circuit.calculateWitness({ "a": "111", "b": "222" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt("333")));
assert(Fr.eq(witness[0],Fr.e(1)));
assert(Fr.eq(witness[1],Fr.e("333")));
});
});

View File

@@ -6,6 +6,8 @@ template A() {
signal input b;
signal output out;
var i;
component n2ba = Num2Bits(16);
component n2bb = Num2Bits(16);
component sub = BinSub(16);
@@ -14,9 +16,12 @@ template A() {
n2ba.in <== a;
n2bb.in <== b;
for (var i=0; i<16; i++) {
for (i=0; i<16; i++) {
sub.in[0][i] <== n2ba.out[i];
sub.in[1][i] <== n2bb.out[i];
}
for (i=0; i<16; i++) {
b2n.in[i] <== sub.out[i];
}

View File

@@ -8,7 +8,7 @@ template Main() {
var i;
var base = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203]
16950150798460657717958625567821834550301663161624707787222815936182638968203];
component escalarMul = EscalarMul(256, base);

View File

@@ -6,8 +6,8 @@ template Main() {
signal input in;
signal output out[2];
var base = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203]
var base[2] = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203];
component n2b = Num2Bits(253);

View File

@@ -7,8 +7,8 @@ template Main() {
var i;
var base = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203]
var base[2] = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203];
component escalarMul = EscalarMul(256, base);

View File

@@ -6,7 +6,7 @@ template Main() {
signal input e;
signal output out[2];
var base = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
var base[2] = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203]

View File

@@ -1,6 +1,6 @@
include "../../circuits/escalarmulw4table.circom";
var base = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
var base[2] = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203]
component main = EscalarMulW4Table(base, 0);

View File

@@ -4,13 +4,13 @@ include "../../circuits/escalarmulw4table.circom";
template Main() {
signal input in;
signal output out[16][2];
var base = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
var base[2] = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203];
component escalarMul = EscalarMulW4Table(base, 0);
var escalarMul[16][2] = EscalarMulW4Table(base, 0);
for (var i=0; i<16; i++) {
out[i][0] <== escalarMul.out[i][0]*in;
out[i][1] <== escalarMul.out[i][1]*in;
out[i][0] <== escalarMul[i][0]*in;
out[i][1] <== escalarMul[i][1]*in;
}
}

View File

@@ -4,13 +4,13 @@ include "../../circuits/escalarmulw4table.circom";
template Main() {
signal input in;
signal output out[16][2];
var base = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
var base[2] = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203];
component escalarMul = EscalarMulW4Table(base, 3);
var escalarMul[16][2] = EscalarMulW4Table(base, 3);
for (var i=0; i<16; i++) {
out[i][0] <== escalarMul.out[i][0]*in;
out[i][1] <== escalarMul.out[i][1]*in;
out[i][0] <== escalarMul[i][0]*in;
out[i][1] <== escalarMul[i][1]*in;
}
}

View File

@@ -1,3 +1,3 @@
include "../../circuits/poseidon.circom"
component main = Poseidon(2, 6, 8, 57);
component main = Poseidon(2);

View File

@@ -0,0 +1,3 @@
include "../../circuits/poseidon.circom"
component main = Poseidon(5);

View File

@@ -6,6 +6,8 @@ template A() {
signal input b;
signal output out;
var i;
component n2ba = Num2Bits(32);
component n2bb = Num2Bits(32);
component sum = BinSum(32,2);
@@ -14,9 +16,12 @@ template A() {
n2ba.in <== a;
n2bb.in <== b;
for (var i=0; i<32; i++) {
for (i=0; i<32; i++) {
sum.in[0][i] <== n2ba.out[i];
sum.in[1][i] <== n2bb.out[i];
}
for (i=0; i<32; i++) {
b2n.in[i] <== sum.out[i];
}

View File

@@ -1,193 +1,185 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const crypto = require("crypto");
const compiler = require("circom");
const tester = require("circom").tester;
const Fr = require("ffjavascript").bn128.Fr;
const assert = chai.assert;
describe("Sum test", () => {
it("Should create a iszero circuit", async() => {
const cirDef = await compiler(path.join(__dirname, "circuits", "iszero.circom"));
describe("Comparators test", function () {
const circuit = new snarkjs.Circuit(cirDef);
this.timeout(100000);
it("Should create a iszero circuit", async() => {
const circuit = await tester(path.join(__dirname, "circuits", "iszero.circom"));
let witness;
witness = circuit.calculateWitness({ "in": 111});
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = await circuit.calculateWitness({ "in": 111}, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(0)));
witness = circuit.calculateWitness({ "in": 0 });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = await circuit.calculateWitness({ "in": 0 }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(1)));
});
it("Should create a isequal circuit", async() => {
const cirDef = await compiler(path.join(__dirname, "circuits", "isequal.circom"));
const circuit = new snarkjs.Circuit(cirDef);
const circuit = await tester(path.join(__dirname, "circuits", "isequal.circom"));
let witness;
witness = circuit.calculateWitness({ "in[0]": "111", "in[1]": "222" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = await circuit.calculateWitness({ "in": [111,222] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(0)));
witness = circuit.calculateWitness({ "in[0]": "444", "in[1]": "444" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = await circuit.calculateWitness({ "in": [444,444] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(1)));
});
it("Should create a comparison lessthan", async() => {
const cirDef = await compiler(path.join(__dirname, "circuits", "lessthan.circom"));
const circuit = new snarkjs.Circuit(cirDef);
const circuit = await tester(path.join(__dirname, "circuits", "lessthan.circom"));
let witness;
witness = circuit.calculateWitness({ "in[0]": "333", "in[1]": "444" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = await circuit.calculateWitness({ "in": [333,444] }), true;
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(1)));
witness = circuit.calculateWitness({ "in[0]": "1", "in[1]": "1" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = await circuit.calculateWitness({ "in":[1,1] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(0)));
witness = circuit.calculateWitness({ "in[0]": "661", "in[1]": "660" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = await circuit.calculateWitness({ "in": [661, 660] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(0)));
witness = circuit.calculateWitness({ "in[0]": "0", "in[1]": "1" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = await circuit.calculateWitness({ "in": [0, 1] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(1)));
witness = circuit.calculateWitness({ "in[0]": "0", "in[1]": "444" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = await circuit.calculateWitness({ "in": [0, 444] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(1)));
witness = circuit.calculateWitness({ "in[0]": "1", "in[1]": "0" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = await circuit.calculateWitness({ "in": [1, 0] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(0)));
witness = circuit.calculateWitness({ "in[0]": "555", "in[1]": "0" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = await circuit.calculateWitness({ "in": [555, 0] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(0)));
witness = circuit.calculateWitness({ "in[0]": "0", "in[1]": "0" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = await circuit.calculateWitness({ "in": [0, 0] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(0)));
});
it("Should create a comparison lesseqthan", async() => {
const cirDef = await compiler(path.join(__dirname, "circuits", "lesseqthan.circom"));
const circuit = new snarkjs.Circuit(cirDef);
const circuit = await tester(path.join(__dirname, "circuits", "lesseqthan.circom"));
let witness;
witness = circuit.calculateWitness({ "in[0]": "333", "in[1]": "444" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = await circuit.calculateWitness({ "in": [333,444] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(1)));
witness = circuit.calculateWitness({ "in[0]": "1", "in[1]": "1" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = await circuit.calculateWitness({ "in":[1,1] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(1)));
witness = circuit.calculateWitness({ "in[0]": "661", "in[1]": "660" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = await circuit.calculateWitness({ "in": [661, 660] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(0)));
witness = circuit.calculateWitness({ "in[0]": "0", "in[1]": "1" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = await circuit.calculateWitness({ "in": [0, 1] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(1)));
witness = circuit.calculateWitness({ "in[0]": "0", "in[1]": "444" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = await circuit.calculateWitness({ "in": [0, 444] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(1)));
witness = circuit.calculateWitness({ "in[0]": "1", "in[1]": "0" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = await circuit.calculateWitness({ "in": [1, 0] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(0)));
witness = circuit.calculateWitness({ "in[0]": "555", "in[1]": "0" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = await circuit.calculateWitness({ "in": [555, 0] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(0)));
witness = circuit.calculateWitness({ "in[0]": "0", "in[1]": "0" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = await circuit.calculateWitness({ "in": [0, 0] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(1)));
});
it("Should create a comparison greaterthan", async() => {
const cirDef = await compiler(path.join(__dirname, "circuits", "greaterthan.circom"));
const circuit = new snarkjs.Circuit(cirDef);
const circuit = await tester(path.join(__dirname, "circuits", "greaterthan.circom"));
let witness;
witness = circuit.calculateWitness({ "in[0]": "333", "in[1]": "444" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = await circuit.calculateWitness({ "in": [333,444] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(0)));
witness = circuit.calculateWitness({ "in[0]": "1", "in[1]": "1" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = await circuit.calculateWitness({ "in":[1,1] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(0)));
witness = circuit.calculateWitness({ "in[0]": "661", "in[1]": "660" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = await circuit.calculateWitness({ "in": [661, 660] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(1)));
witness = circuit.calculateWitness({ "in[0]": "0", "in[1]": "1" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = await circuit.calculateWitness({ "in": [0, 1] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(0)));
witness = circuit.calculateWitness({ "in[0]": "0", "in[1]": "444" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = await circuit.calculateWitness({ "in": [0, 444] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(0)));
witness = circuit.calculateWitness({ "in[0]": "1", "in[1]": "0" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = await circuit.calculateWitness({ "in": [1, 0] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(1)));
witness = circuit.calculateWitness({ "in[0]": "555", "in[1]": "0" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = await circuit.calculateWitness({ "in": [555, 0] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(1)));
witness = circuit.calculateWitness({ "in[0]": "0", "in[1]": "0" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = await circuit.calculateWitness({ "in": [0, 0] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(0)));
});
it("Should create a comparison greatereqthan", async() => {
const cirDef = await compiler(path.join(__dirname, "circuits", "greatereqthan.circom"));
const circuit = new snarkjs.Circuit(cirDef);
console.log("NConstraints BalancesUpdater: " + circuit.nConstraints);
const circuit = await tester(path.join(__dirname, "circuits", "greatereqthan.circom"));
let witness;
witness = circuit.calculateWitness({ "in[0]": "333", "in[1]": "444" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = await circuit.calculateWitness({ "in": [333,444] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(0)));
witness = circuit.calculateWitness({ "in[0]": "1", "in[1]": "1" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = await circuit.calculateWitness({ "in":[1,1] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(1)));
witness = circuit.calculateWitness({ "in[0]": "661", "in[1]": "660" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = await circuit.calculateWitness({ "in": [661, 660] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(1)));
witness = circuit.calculateWitness({ "in[0]": "0", "in[1]": "1" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = await circuit.calculateWitness({ "in": [0, 1] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(0)));
witness = circuit.calculateWitness({ "in[0]": "0", "in[1]": "444" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0)));
witness = await circuit.calculateWitness({ "in": [0, 444] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(0)));
witness = circuit.calculateWitness({ "in[0]": "1", "in[1]": "0" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = await circuit.calculateWitness({ "in": [1, 0] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(1)));
witness = circuit.calculateWitness({ "in[0]": "555", "in[1]": "0" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = await circuit.calculateWitness({ "in": [555, 0] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(1)));
witness = circuit.calculateWitness({ "in[0]": "0", "in[1]": "0" });
assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1)));
witness = await circuit.calculateWitness({ "in": [0, 0] }, true);
assert(Fr.eq(witness[0], Fr.e(1)));
assert(Fr.eq(witness[1], Fr.e(1)));
});
});

View File

@@ -1,16 +1,14 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
// const crypto = require("crypto");
const tester = require("circom").tester;
const Fr = require("ffjavascript").bn128.Fr;
const eddsa = require("../src/eddsa.js");
const babyJub = require("../src/babyjub.js");
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
function print(circuit, w, s) {
console.log(s + ": " + w[circuit.getSignalIdx(s)]);
}
@@ -20,9 +18,9 @@ function buffer2bits(buff) {
for (let i=0; i<buff.length; i++) {
for (let j=0; j<8; j++) {
if ((buff[i]>>j)&1) {
res.push(bigInt.one);
res.push(Fr.one);
} else {
res.push(bigInt.zero);
res.push(Fr.zero);
}
}
}
@@ -36,11 +34,7 @@ describe("EdDSA test", function () {
this.timeout(100000);
before( async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "eddsa_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains EdDSA: " + circuit.nConstraints);
circuit = await tester(path.join(__dirname, "circuits", "eddsa_test.circom"));
});
it("Sign a single 10 bytes from 0 to 9", async () => {
@@ -66,9 +60,8 @@ describe("EdDSA test", function () {
const sBits = buffer2bits(pSignature.slice(32, 64));
const aBits = buffer2bits(pPubKey);
const w = circuit.calculateWitness({A: aBits, R8: r8Bits, S: sBits, msg: msgBits});
assert(circuit.checkWitness(w));
const w = await circuit.calculateWitness({A: aBits, R8: r8Bits, S: sBits, msg: msgBits}, true);
await circuit.checkConstraints(w);
});
});

View File

@@ -1,12 +1,11 @@
const chai = require("chai");
const snarkjs = require("snarkjs");
const eddsa = require("../src/eddsa.js");
const babyJub = require("../src/babyjub.js");
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
const utils = require("ffjavascript").utils;
describe("EdDSA js test", function () {
@@ -14,7 +13,7 @@ describe("EdDSA js test", function () {
it("Sign (using Mimc7) a single 10 bytes from 0 to 9", () => {
const msgBuf = Buffer.from("00010203040506070809", "hex");
const msg = bigInt.leBuff2int(msgBuf);
const msg = utils.leBuff2int(msgBuf);
// const prvKey = crypto.randomBytes(32);
@@ -49,7 +48,7 @@ describe("EdDSA js test", function () {
it("Sign (using Poseidon) a single 10 bytes from 0 to 9", () => {
const msgBuf = Buffer.from("00010203040506070809", "hex");
const msg = bigInt.leBuff2int(msgBuf);
const msg = utils.leBuff2int(msgBuf);
const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex");
@@ -68,12 +67,12 @@ describe("EdDSA js test", function () {
assert.equal(signature.R8[1].toString(),
"15383486972088797283337779941324724402501462225528836549661220478783371668959");
assert.equal(signature.S.toString(),
"248298168863866362217836334079793350221620631973732197668910946177382043688");
"1398758333392199195742243841591064350253744445503462896781493968760929513778");
const pSignature = eddsa.packSignature(signature);
assert.equal(pSignature.toString("hex"), ""+
"dfedb4315d3f2eb4de2d3c510d7a987dcab67089c8ace06308827bf5bcbe02a2"+
"28506bce274aa1b3f7e7c2fd7e4fe09bff8f9aa37a42def7994e98f322888c00");
"32f16b0f2f4c4e1169aa59685637e1429b6581a9531d058d65f4ab224eab1703");
const uSignature = eddsa.unpackSignature(pSignature);
assert(eddsa.verifyPoseidon(msg, uSignature, pubKey));

View File

@@ -1,29 +1,25 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const tester = require("circom").tester;
const Fr = require("ffjavascript").bn128.Fr;
const eddsa = require("../src/eddsa.js");
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
describe("EdDSA MiMC test", function () {
let circuit;
this.timeout(100000);
before( async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "eddsamimc_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains EdDSA MiMC: " + circuit.nConstraints);
circuit = await tester(path.join(__dirname, "circuits", "eddsamimc_test.circom"));
});
it("Sign a single number", async () => {
const msg = bigInt(1234);
const msg = Fr.e(1234);
const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex");
@@ -33,20 +29,22 @@ describe("EdDSA MiMC test", function () {
assert(eddsa.verifyMiMC(msg, signature, pubKey));
const w = circuit.calculateWitness({
const w = await circuit.calculateWitness({
enabled: 1,
Ax: pubKey[0],
Ay: pubKey[1],
R8x: signature.R8[0],
R8y: signature.R8[1],
S: signature.S,
M: msg});
M: msg}, true);
await circuit.checkConstraints(w);
assert(circuit.checkWitness(w));
});
it("Detect Invalid signature", async () => {
const msg = bigInt(1234);
const msg = Fr.e(1234);
const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex");
@@ -57,23 +55,23 @@ describe("EdDSA MiMC test", function () {
assert(eddsa.verifyMiMC(msg, signature, pubKey));
try {
const w = circuit.calculateWitness({
const w = await circuit.calculateWitness({
enabled: 1,
Ax: pubKey[0],
Ay: pubKey[1],
R8x: signature.R8[0].add(bigInt(1)),
R8x: Fr.add(signature.R8[0], Fr.e(1)),
R8y: signature.R8[1],
S: signature.S,
M: msg});
M: msg}, true);
assert(false);
} catch(err) {
assert.equal(err.message, "Constraint doesn't match: 1 != 0");
assert(/Constraint\sdoesn't\smatch(.*)1\s!=\s0/.test(err.message) );
}
});
it("Test a dissabled circuit with a bad signature", async () => {
const msg = bigInt(1234);
const msg = Fr.e(1234);
const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex");
@@ -84,15 +82,16 @@ describe("EdDSA MiMC test", function () {
assert(eddsa.verifyMiMC(msg, signature, pubKey));
const w = circuit.calculateWitness({
const w = await circuit.calculateWitness({
enabled: 0,
Ax: pubKey[0],
Ay: pubKey[1],
R8x: signature.R8[0].add(bigInt(1)),
R8x: Fr.add(signature.R8[0], Fr.e(1)),
R8y: signature.R8[1],
S: signature.S,
M: msg});
M: msg}, true);
await circuit.checkConstraints(w);
assert(circuit.checkWitness(w));
});
});

View File

@@ -1,29 +1,25 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const tester = require("circom").tester;
const Fr = require("ffjavascript").bn128.Fr;
const eddsa = require("../src/eddsa.js");
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
describe("EdDSA Poseidon test", function () {
let circuit;
this.timeout(100000);
before( async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "eddsaposeidon_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
circuit = await tester(path.join(__dirname, "circuits", "eddsaposeidon_test.circom"));
console.log("NConstrains EdDSA Poseidon: " + circuit.nConstraints);
});
it("Sign a single number", async () => {
const msg = bigInt(1234);
const msg = Fr.e(1234);
const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex");
@@ -33,20 +29,25 @@ describe("EdDSA Poseidon test", function () {
assert(eddsa.verifyPoseidon(msg, signature, pubKey));
const w = circuit.calculateWitness({
const input = {
enabled: 1,
Ax: pubKey[0],
Ay: pubKey[1],
R8x: signature.R8[0],
R8y: signature.R8[1],
S: signature.S,
M: msg});
M: msg
};
assert(circuit.checkWitness(w));
// console.log(JSON.stringify(utils.stringifyBigInts(input)));
const w = await circuit.calculateWitness(input, true);
await circuit.checkConstraints(w);
});
it("Detect Invalid signature", async () => {
const msg = bigInt(1234);
const msg = Fr.e(1234);
const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex");
@@ -57,23 +58,23 @@ describe("EdDSA Poseidon test", function () {
assert(eddsa.verifyPoseidon(msg, signature, pubKey));
try {
circuit.calculateWitness({
await circuit.calculateWitness({
enabled: 1,
Ax: pubKey[0],
Ay: pubKey[1],
R8x: signature.R8[0].add(bigInt(1)),
R8x: Fr.add(signature.R8[0], Fr.e(1)),
R8y: signature.R8[1],
S: signature.S,
M: msg});
M: msg}, true);
assert(false);
} catch(err) {
assert.equal(err.message, "Constraint doesn't match: 1 != 0");
assert(/Constraint\sdoesn't\smatch(.*)1\s!=\s0/.test(err.message) );
}
});
it("Test a dissabled circuit with a bad signature", async () => {
const msg = bigInt(1234);
const msg = Fr.e(1234);
const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex");
@@ -84,15 +85,15 @@ describe("EdDSA Poseidon test", function () {
assert(eddsa.verifyPoseidon(msg, signature, pubKey));
const w = circuit.calculateWitness({
const w = await circuit.calculateWitness({
enabled: 0,
Ax: pubKey[0],
Ay: pubKey[1],
R8x: signature.R8[0].add(bigInt(1)),
R8x: Fr.add(signature.R8[0], Fr.e(1)),
R8y: signature.R8[1],
S: signature.S,
M: msg});
M: msg}, true);
assert(circuit.checkWitness(w));
await circuit.checkConstraints(w);
});
});

View File

@@ -1,168 +1,115 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const tester = require("circom").tester;
const babyJub = require("../src/babyjub.js");
const Fr = require("ffjavascript").bn128.Fr;
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
const q=bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
function addPoint(a,b) {
const cta = bigInt("168700");
const d = bigInt("168696");
const res = [];
res[0] = bigInt((a[0]*b[1] + b[0]*a[1]) * bigInt(bigInt.one + 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.one - d*a[0]*b[0]*a[1]*b[1]).inverse(q)).affine(q);
return res;
}
function print(circuit, w, s) {
console.log(s + ": " + w[circuit.getSignalIdx(s)]);
}
describe("Exponentioation test", () => {
describe("Exponentioation test", function () {
this.timeout(100000);
it("Should generate the Exponentiation table in k=0", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "escalarmulw4table_test.circom"));
const circuit = await tester(path.join(__dirname, "circuits", "escalarmulw4table_test.circom"));
// console.log(JSON.stringify(cirDef, null, 1));
const w = await circuit.calculateWitness({in: 1});
// assert.equal(cirDef.nVars, 2);
await circuit.checkConstraints(w);
const circuit = new snarkjs.Circuit(cirDef);
let g = [
Fr.e("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
Fr.e("16950150798460657717958625567821834550301663161624707787222815936182638968203")
];
console.log("NConstrains: " + circuit.nConstraints);
let dbl= [Fr.e("0"), Fr.e("1")];
const w = circuit.calculateWitness({in: 1});
let g = [bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")]
dbl= [bigInt("0"), snarkjs.bigInt("1")];
const expectedOut = [];
for (let i=0; i<16; i++) {
const xout1 = w[circuit.getSignalIdx(`main.out[${i}][0]`)];
const yout1 = w[circuit.getSignalIdx(`main.out[${i}][1]`)];
/*
console.log(xout1.toString());
console.log(yout1.toString());
console.log(dbl[0]);
console.log(dbl[1]);
*/
assert(xout1.equals(dbl[0]));
assert(yout1.equals(dbl[1]));
dbl = addPoint([xout1, yout1],g);
expectedOut.push(dbl);
dbl = babyJub.addPoint(dbl,g);
}
await circuit.assertOut(w, {out: expectedOut});
});
it("Should generate the Exponentiation table in k=3", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "escalarmulw4table_test3.circom"));
const circuit = await tester(path.join(__dirname, "circuits", "escalarmulw4table_test3.circom"));
// console.log(JSON.stringify(cirDef, null, 1));
const w = await circuit.calculateWitness({in: 1});
// assert.equal(cirDef.nVars, 2);
await circuit.checkConstraints(w);
const circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains: " + circuit.nConstraints);
const w = circuit.calculateWitness({in: 1});
let g = [snarkjs.bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
snarkjs.bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")]
let g = [
Fr.e("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
Fr.e("16950150798460657717958625567821834550301663161624707787222815936182638968203")
];
for (let i=0; i<12;i++) {
g = addPoint(g,g);
g = babyJub.addPoint(g,g);
}
dbl= [snarkjs.bigInt("0"), snarkjs.bigInt("1")];
let dbl= [Fr.e("0"), Fr.e("1")];
const expectedOut = [];
for (let i=0; i<16; i++) {
const xout1 = w[circuit.getSignalIdx(`main.out[${i}][0]`)];
const yout1 = w[circuit.getSignalIdx(`main.out[${i}][1]`)];
expectedOut.push(dbl);
/*
console.log(xout1.toString());
console.log(yout1.toString());
console.log(dbl[0]);
console.log(dbl[1]);
*/
assert(xout1.equals(dbl[0]));
assert(yout1.equals(dbl[1]));
dbl = addPoint([xout1, yout1],g);
dbl = babyJub.addPoint(dbl,g);
}
await circuit.assertOut(w, {out: expectedOut});
});
it("Should exponentiate g^31", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "escalarmul_test.circom"));
// console.log(JSON.stringify(cirDef, null, 1));
const circuit = await tester(path.join(__dirname, "circuits", "escalarmul_test.circom"));
// assert.equal(cirDef.nVars, 2);
const w = await circuit.calculateWitness({"in": 31});
const circuit = new snarkjs.Circuit(cirDef);
await circuit.checkConstraints(w);
console.log("NConstrains: " + circuit.nConstraints);
let g = [
Fr.e("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
Fr.e("16950150798460657717958625567821834550301663161624707787222815936182638968203")
];
const w = circuit.calculateWitness({"in": 31});
assert(circuit.checkWitness(w));
let g = [snarkjs.bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
snarkjs.bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")]
let c = [0n, 1n];
let c = [Fr.e(0), Fr.e(1)];
for (let i=0; i<31;i++) {
c = addPoint(c,g);
c = babyJub.addPoint(c,g);
}
const xout = w[circuit.getSignalIdx(`main.out[0]`)];
const yout = w[circuit.getSignalIdx(`main.out[1]`)];
await circuit.assertOut(w, {out: c});
/*
console.log(xout.toString());
console.log(yout.toString());
*/
assert(xout.equals(c[0]));
assert(yout.equals(c[1]));
console.log("-------")
const w2 = circuit.calculateWitness({"in": (1n<<252n)+1n});
const xout2 = w2[circuit.getSignalIdx(`main.out[0]`)];
const yout2 = w2[circuit.getSignalIdx(`main.out[1]`)];
const w2 = await circuit.calculateWitness({"in": Fr.add(Fr.shl(Fr.e(1), Fr.e(252)),Fr.one)});
c = [g[0], g[1]];
for (let i=0; i<252;i++) {
c = addPoint(c,c);
c = babyJub.addPoint(c,c);
}
c = addPoint(c,g);
/*
console.log(xout2.toString());
console.log(yout2.toString());
console.log(c[0].toString());
console.log(c[1].toString());
*/
assert(xout2.equals(c[0]));
assert(yout2.equals(c[1]));
c = babyJub.addPoint(c,g);
await circuit.assertOut(w2, {out: c});
}).timeout(10000000);
it("Number of constrains for 256 bits", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "escalarmul_test_min.circom"));
const circuit = new snarkjs.Circuit(cirDef);
const circuit = await tester(path.join(__dirname, "circuits", "escalarmul_test_min.circom"));
console.log("NConstrains: " + circuit.nConstraints);
}).timeout(10000000);
});

View File

@@ -1,11 +1,7 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
const tester = require("circom").tester;
const Fr = require("ffjavascript").bn128.Fr;
function print(circuit, w, s) {
@@ -18,41 +14,33 @@ describe("Escalarmul test", function () {
this.timeout(100000);
let g = [
snarkjs.bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
snarkjs.bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")
Fr.e("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
Fr.e("16950150798460657717958625567821834550301663161624707787222815936182638968203")
];
before( async() => {
const cirDefEMulAny = await compiler(path.join(__dirname, "circuits", "escalarmulany_test.circom"));
circuitEMulAny = new snarkjs.Circuit(cirDefEMulAny);
console.log("NConstrains Escalarmul any: " + circuitEMulAny.nConstraints);
circuitEMulAny = await tester(path.join(__dirname, "circuits", "escalarmulany_test.circom"));
});
it("Should generate Same escalar mul", async () => {
const w = circuitEMulAny.calculateWitness({"e": 1, "p": g});
const w = await circuitEMulAny.calculateWitness({"e": 1, "p": g});
assert(circuitEMulAny.checkWitness(w));
await circuitEMulAny.checkConstraints(w);
const xout = w[circuitEMulAny.getSignalIdx("main.out[0]")];
const yout = w[circuitEMulAny.getSignalIdx("main.out[1]")];
await circuitEMulAny.assertOut(w, {out: g}, true);
assert(xout.equals(g[0]));
assert(yout.equals(g[1]));
});
it("If multiply by order should return 0", async () => {
const r = bigInt("2736030358979909402780800718157159386076813972158567259200215660948447373041");
const w = circuitEMulAny.calculateWitness({"e": r, "p": g});
const r = Fr.e("2736030358979909402780800718157159386076813972158567259200215660948447373041");
const w = await circuitEMulAny.calculateWitness({"e": r, "p": g});
assert(circuitEMulAny.checkWitness(w));
await circuitEMulAny.checkConstraints(w);
const xout = w[circuitEMulAny.getSignalIdx("main.out[0]")];
const yout = w[circuitEMulAny.getSignalIdx("main.out[1]")];
await circuitEMulAny.assertOut(w, {out: [0,1]}, true);
assert(xout.equals(bigInt.zero));
assert(yout.equals(bigInt.one));
});
});

View File

@@ -1,14 +1,11 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const tester = require("circom").tester;
const babyjub = require("../src/babyjub");
const Fr = require("ffjavascript").bn128.Fr;
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
function print(circuit, w, s) {
console.log(s + ": " + w[circuit.getSignalIdx(s)]);
}
@@ -19,93 +16,74 @@ describe("Escalarmul test", function () {
this.timeout(100000);
before( async() => {
const cirDef = await compiler(path.join(__dirname, "circuits", "escalarmulfix_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains Escalarmul fix: " + circuit.nConstraints);
circuit = await tester(path.join(__dirname, "circuits", "escalarmulfix_test.circom"));
});
it("Should generate Same escalar mul", async () => {
const w = circuit.calculateWitness({"e": 0});
const w = await circuit.calculateWitness({"e": 0});
assert(circuit.checkWitness(w));
await circuit.checkConstraints(w);
const xout = w[circuit.getSignalIdx("main.out[0]")];
const yout = w[circuit.getSignalIdx("main.out[1]")];
await circuit.assertOut(w, {out: [0,1]}, true);
assert(xout.equals(0));
assert(yout.equals(1));
});
it("Should generate Same escalar mul", async () => {
const w = circuit.calculateWitness({"e": 1});
const w = await circuit.calculateWitness({"e": 1}, true);
assert(circuit.checkWitness(w));
await circuit.checkConstraints(w);
const xout = w[circuit.getSignalIdx("main.out[0]")];
const yout = w[circuit.getSignalIdx("main.out[1]")];
await circuit.assertOut(w, {out: babyjub.Base8});
assert(xout.equals(babyjub.Base8[0]));
assert(yout.equals(babyjub.Base8[1]));
});
it("Should generate scalar mul of a specific constant", async () => {
const s = bigInt("2351960337287830298912035165133676222414898052661454064215017316447594616519");
const s = Fr.e("2351960337287830298912035165133676222414898052661454064215017316447594616519");
const base8 = [
bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")
Fr.e("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
Fr.e("16950150798460657717958625567821834550301663161624707787222815936182638968203")
];
const w = circuit.calculateWitness({"e": s});
const w = await circuit.calculateWitness({"e": s}, true);
assert(circuit.checkWitness(w));
const xout = w[circuit.getSignalIdx("main.out[0]")];
const yout = w[circuit.getSignalIdx("main.out[1]")];
await circuit.checkConstraints(w);
const expectedRes = babyjub.mulPointEscalar(base8, s);
assert(xout.equals(expectedRes[0]));
assert(yout.equals(expectedRes[1]));
await circuit.assertOut(w, {out: expectedRes});
});
it("Should generate scalar mul of the firsts 50 elements", async () => {
const base8 = [
bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")
Fr.e("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
Fr.e("16950150798460657717958625567821834550301663161624707787222815936182638968203")
];
for (let i=0; i<50; i++) {
const s = bigInt(i);
const s = Fr.e(i);
const w = circuit.calculateWitness({"e": s});
const w = await circuit.calculateWitness({"e": s}, true);
assert(circuit.checkWitness(w));
const xout = w[circuit.getSignalIdx("main.out[0]")];
const yout = w[circuit.getSignalIdx("main.out[1]")];
await circuit.checkConstraints(w);
const expectedRes = babyjub.mulPointEscalar(base8, s);
assert(xout.equals(expectedRes[0]));
assert(yout.equals(expectedRes[1]));
await circuit.assertOut(w, {out: expectedRes});
}
});
it("If multiply by order should return 0", async () => {
const w = circuit.calculateWitness({"e": babyjub.subOrder });
const w = await circuit.calculateWitness({"e": babyjub.subOrder }, true);
assert(circuit.checkWitness(w));
await circuit.checkConstraints(w);
const xout = w[circuit.getSignalIdx("main.out[0]")];
const yout = w[circuit.getSignalIdx("main.out[1]")];
assert(xout.equals(bigInt.zero));
assert(yout.equals(bigInt.one));
await circuit.assertOut(w, {out: [0,1]});
});
});

View File

@@ -1,35 +1,25 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const tester = require("circom").tester;
const mimcjs = require("../src/mimc7.js");
const assert = chai.assert;
describe("MiMC Circuit test", function () {
let circuit;
this.timeout(100000);
before( async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "mimc_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("MiMC constraints: " + circuit.nConstraints);
circuit = await tester(path.join(__dirname, "circuits", "mimc_test.circom"));
});
it("Should check constrain", async () => {
const w = circuit.calculateWitness({x_in: 1, k: 2});
const res = w[circuit.getSignalIdx("main.out")];
const w = await circuit.calculateWitness({x_in: 1, k: 2}, true);
const res2 = mimcjs.hash(1,2,91);
assert.equal(res.toString(), res2.toString());
assert(circuit.checkWitness(w));
await circuit.assertOut(w, {out: res2});
await circuit.checkConstraints(w);
});
});

View File

@@ -1,11 +1,8 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const tester = require("circom").tester;
const mimcjs = require("../src/mimcsponge.js");
const assert = chai.assert;
describe("MiMC Sponge Circuit test", function () {
let circuit;
@@ -13,46 +10,28 @@ describe("MiMC Sponge Circuit test", function () {
this.timeout(100000);
it("Should check permutation", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "mimc_sponge_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
circuit = await tester(path.join(__dirname, "circuits", "mimc_sponge_test.circom"));
console.log("MiMC Feistel constraints: " + circuit.nConstraints);
const w = circuit.calculateWitness({xL_in: 1, xR_in: 2, k: 3});
const xLout = w[circuit.getSignalIdx("main.xL_out")];
const xRout = w[circuit.getSignalIdx("main.xR_out")];
const w = await circuit.calculateWitness({xL_in: 1, xR_in: 2, k: 3});
const out2 = mimcjs.hash(1,2,3);
assert.equal(xLout.toString(), out2.xL.toString());
assert.equal(xRout.toString(), out2.xR.toString());
await circuit.assertOut(w, {xL_out: out2.xL, xR_out: out2.xR});
assert(circuit.checkWitness(w));
await circuit.checkConstraints(w);
});
it("Should check hash", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "mimc_sponge_hash_test.circom"));
circuit = await tester(path.join(__dirname, "circuits", "mimc_sponge_hash_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("MiMC Sponge constraints: " + circuit.nConstraints);
const w = circuit.calculateWitness({ins: [1, 2], k: 0});
const o1 = w[circuit.getSignalIdx("main.outs[0]")];
const o2 = w[circuit.getSignalIdx("main.outs[1]")];
const o3 = w[circuit.getSignalIdx("main.outs[2]")];
const w = await circuit.calculateWitness({ins: [1, 2], k: 0});
const out2 = mimcjs.multiHash([1,2], 0, 3);
assert.equal(o1.toString(), out2[0].toString());
assert.equal(o2.toString(), out2[1].toString());
assert.equal(o3.toString(), out2[2].toString());
assert(circuit.checkWitness(w));
await circuit.assertOut(w, {outs: out2});
await circuit.checkConstraints(w);
});
});

View File

@@ -1,13 +1,11 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const tester = require("circom").tester;
const babyJub = require("../src/babyjub.js");
const Fr = require("ffjavascript").bn128.Fr;
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
describe("Montgomery test", function () {
let circuitE2M;
let circuitM2E;
@@ -15,85 +13,80 @@ describe("Montgomery test", function () {
let circuitMDouble;
let g = [
snarkjs.bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
snarkjs.bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")];
Fr.e("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
Fr.e("16950150798460657717958625567821834550301663161624707787222815936182638968203")
];
let mg, mg2, g2, g3, mg3;
this.timeout(100000);
before( async() => {
const cirDefE2M = await compiler(path.join(__dirname, "circuits", "edwards2montgomery.circom"));
circuitE2M = new snarkjs.Circuit(cirDefE2M);
console.log("NConstrains Edwards -> Montgomery: " + circuitE2M.nConstraints);
const cirDefM2E = await compiler(path.join(__dirname, "circuits", "montgomery2edwards.circom"));
circuitM2E = new snarkjs.Circuit(cirDefM2E);
console.log("NConstrains Montgomery -> Edwards: " + circuitM2E.nConstraints);
const cirDefMAdd = await compiler(path.join(__dirname, "circuits", "montgomeryadd.circom"));
circuitMAdd = new snarkjs.Circuit(cirDefMAdd);
console.log("NConstrains Montgomery Add: " + circuitMAdd.nConstraints);
const cirDefMDouble = await compiler(path.join(__dirname, "circuits", "montgomerydouble.circom"));
circuitMDouble = new snarkjs.Circuit(cirDefMDouble);
console.log("NConstrains Montgomery Double: " + circuitMDouble.nConstraints);
circuitE2M = await tester(path.join(__dirname, "circuits", "edwards2montgomery.circom"));
await circuitE2M.loadSymbols();
circuitM2E = await tester(path.join(__dirname, "circuits", "montgomery2edwards.circom"));
await circuitM2E.loadSymbols();
circuitMAdd = await tester(path.join(__dirname, "circuits", "montgomeryadd.circom"));
await circuitMAdd.loadSymbols();
circuitMDouble = await tester(path.join(__dirname, "circuits", "montgomerydouble.circom"));
await circuitMDouble.loadSymbols();
});
it("Convert Edwards to Montgomery and back again", async () => {
let w, xout, yout;
w = circuitE2M.calculateWitness({ in: g});
w = await circuitE2M.calculateWitness({ in: g}, true);
xout = w[circuitE2M.getSignalIdx("main.out[0]")];
yout = w[circuitE2M.getSignalIdx("main.out[1]")];
xout = w[circuitE2M.symbols["main.out[0]"].varIdx];
yout = w[circuitE2M.symbols["main.out[1]"].varIdx];
mg = [xout, yout];
w = circuitM2E.calculateWitness({ in: [xout, yout]});
w = await circuitM2E.calculateWitness({ in: [xout, yout]}, true);
xout = w[circuitM2E.getSignalIdx("main.out[0]")];
yout = w[circuitM2E.getSignalIdx("main.out[1]")];
xout = w[circuitM2E.symbols["main.out[0]"].varIdx];
yout = w[circuitM2E.symbols["main.out[1]"].varIdx];
assert(xout.equals(g[0]));
assert(yout.equals(g[1]));
assert(Fr.eq(xout, g[0]));
assert(Fr.eq(yout, g[1]));
});
it("Should double a point", async () => {
let w, xout, yout;
g2 = babyJub.addPoint(g,g);
w = circuitMDouble.calculateWitness({ in: mg});
w = await circuitMDouble.calculateWitness({ in: mg}, true);
xout = w[circuitE2M.getSignalIdx("main.out[0]")];
yout = w[circuitE2M.getSignalIdx("main.out[1]")];
xout = w[circuitE2M.symbols["main.out[0]"].varIdx];
yout = w[circuitE2M.symbols["main.out[1]"].varIdx];
mg2 = [xout, yout];
w = circuitM2E.calculateWitness({ in: mg2});
w = await circuitM2E.calculateWitness({ in: mg2}, true);
xout = w[circuitM2E.getSignalIdx("main.out[0]")];
yout = w[circuitM2E.getSignalIdx("main.out[1]")];
xout = w[circuitM2E.symbols["main.out[0]"].varIdx];
yout = w[circuitM2E.symbols["main.out[1]"].varIdx];
assert(xout.equals(g2[0]));
assert(yout.equals(g2[1]));
assert(Fr.eq(xout, g2[0]));
assert(Fr.eq(yout, g2[1]));
});
it("Should add a point", async () => {
let w, xout, yout;
g3 = babyJub.addPoint(g,g2);
w = circuitMAdd.calculateWitness({ in1: mg, in2: mg2});
w = await circuitMAdd.calculateWitness({ in1: mg, in2: mg2}, true);
xout = w[circuitMAdd.getSignalIdx("main.out[0]")];
yout = w[circuitMAdd.getSignalIdx("main.out[1]")];
xout = w[circuitMAdd.symbols["main.out[0]"].varIdx];
yout = w[circuitMAdd.symbols["main.out[1]"].varIdx];
mg3 = [xout, yout];
w = circuitM2E.calculateWitness({ in: mg3});
w = await circuitM2E.calculateWitness({ in: mg3}, true);
xout = w[circuitM2E.getSignalIdx("main.out[0]")];
yout = w[circuitM2E.getSignalIdx("main.out[1]")];
xout = w[circuitM2E.symbols["main.out[0]"].varIdx];
yout = w[circuitM2E.symbols["main.out[1]"].varIdx];
assert(xout.equals(g3[0]));
assert(yout.equals(g3[1]));
assert(Fr.eq(xout, g3[0]));
assert(Fr.eq(yout, g3[1]));
});
});

View File

@@ -1,127 +1,98 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const tester = require("circom").tester;
const Fr = require("ffjavascript").bn128.Fr;
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
describe("Mux4 test", () => {
describe("Mux4 test", function() {
this.timeout(100000);
it("Should create a constant multiplexer 4", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "mux4_1.circom"));
// console.log(JSON.stringify(cirDef, null, 1));
// assert.equal(cirDef.nVars, 2);
const circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains Mux4: " + circuit.nConstraints);
const circuit = await tester(path.join(__dirname, "circuits", "mux4_1.circom"));
const ct16 = [
bigInt("123"),
bigInt("456"),
bigInt("789"),
bigInt("012"),
bigInt("111"),
bigInt("222"),
bigInt("333"),
bigInt("4546"),
bigInt("134523"),
bigInt("44356"),
bigInt("15623"),
bigInt("4566"),
bigInt("1223"),
bigInt("4546"),
bigInt("4256"),
bigInt("4456")
Fr.e("123"),
Fr.e("456"),
Fr.e("789"),
Fr.e("012"),
Fr.e("111"),
Fr.e("222"),
Fr.e("333"),
Fr.e("4546"),
Fr.e("134523"),
Fr.e("44356"),
Fr.e("15623"),
Fr.e("4566"),
Fr.e("1223"),
Fr.e("4546"),
Fr.e("4256"),
Fr.e("4456")
];
for (let i=0; i<16; i++) {
const w = circuit.calculateWitness({ "selector": i });
const w = await circuit.calculateWitness({ "selector": i }, true);
assert(w[0].equals(bigInt(1)));
await circuit.checkConstraints(w);
// console.log(i + " -> " + w[circuit.getSignalIdx("main.out")].toString());
assert(w[circuit.getSignalIdx("main.out")].equals(ct16[i]));
await circuit.assertOut(w, {out: ct16[i]});
}
});
it("Should create a constant multiplexer 3", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "mux3_1.circom"));
const circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains Mux3: " + circuit.nConstraints);
const circuit = await tester(path.join(__dirname, "circuits", "mux3_1.circom"));
const ct8 = [
bigInt("37"),
bigInt("47"),
bigInt("53"),
bigInt("71"),
bigInt("89"),
bigInt("107"),
bigInt("163"),
bigInt("191")
Fr.e("37"),
Fr.e("47"),
Fr.e("53"),
Fr.e("71"),
Fr.e("89"),
Fr.e("107"),
Fr.e("163"),
Fr.e("191")
];
for (let i=0; i<8; i++) {
const w = circuit.calculateWitness({ "selector": i });
const w = await circuit.calculateWitness({ "selector": i }, true);
assert(w[0].equals(bigInt(1)));
await circuit.checkConstraints(w);
// console.log(i + " -> " + w[circuit.getSignalIdx("main.out")].toString());
assert(w[circuit.getSignalIdx("main.out")].equals(ct8[i]));
await circuit.assertOut(w, {out: ct8[i]});
}
});
it("Should create a constant multiplexer 2", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "mux2_1.circom"));
const circuit = await tester(path.join(__dirname, "circuits", "mux2_1.circom"));
const circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains Mux2: " + circuit.nConstraints);
const ct8 = [
bigInt("37"),
bigInt("47"),
bigInt("53"),
bigInt("71"),
const ct4 = [
Fr.e("37"),
Fr.e("47"),
Fr.e("53"),
Fr.e("71"),
];
for (let i=0; i<4; i++) {
const w = circuit.calculateWitness({ "selector": i });
const w = await circuit.calculateWitness({ "selector": i }, true);
assert(w[0].equals(bigInt(1)));
await circuit.checkConstraints(w);
// console.log(i + " -> " + w[circuit.getSignalIdx("main.out")].toString());
assert(w[circuit.getSignalIdx("main.out")].equals(ct8[i]));
await circuit.assertOut(w, {out: ct4[i]});
}
});
it("Should create a constant multiplexer 1", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "mux1_1.circom"));
const circuit = await tester(path.join(__dirname, "circuits", "mux1_1.circom"));
const circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains Mux1: " + circuit.nConstraints);
const ct8 = [
bigInt("37"),
bigInt("47"),
const ct2 = [
Fr.e("37"),
Fr.e("47"),
];
for (let i=0; i<2; i++) {
const w = circuit.calculateWitness({ "selector": i });
const w = await circuit.calculateWitness({ "selector": i }, true);
assert(w[0].equals(bigInt(1)));
await circuit.checkConstraints(w);
// console.log(i + " -> " + w[circuit.getSignalIdx("main.out")].toString());
assert(w[circuit.getSignalIdx("main.out")].equals(ct8[i]));
await circuit.assertOut(w, {out: ct2[i]});
}
});
});

View File

@@ -1,100 +1,77 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
const Fr = require("ffjavascript").bn128.Fr;
const tester = require("circom").tester;
const babyJub = require("../src/babyjub.js");
const PBASE =
[
[bigInt("10457101036533406547632367118273992217979173478358440826365724437999023779287"),bigInt("19824078218392094440610104313265183977899662750282163392862422243483260492317")],
[bigInt("2671756056509184035029146175565761955751135805354291559563293617232983272177"),bigInt("2663205510731142763556352975002641716101654201788071096152948830924149045094")],
[bigInt("5802099305472655231388284418920769829666717045250560929368476121199858275951"),bigInt("5980429700218124965372158798884772646841287887664001482443826541541529227896")],
[bigInt("7107336197374528537877327281242680114152313102022415488494307685842428166594"),bigInt("2857869773864086953506483169737724679646433914307247183624878062391496185654")],
[bigInt("20265828622013100949498132415626198973119240347465898028410217039057588424236"),bigInt("1160461593266035632937973507065134938065359936056410650153315956301179689506")]
[Fr.e("10457101036533406547632367118273992217979173478358440826365724437999023779287"),Fr.e("19824078218392094440610104313265183977899662750282163392862422243483260492317")],
[Fr.e("2671756056509184035029146175565761955751135805354291559563293617232983272177"),Fr.e("2663205510731142763556352975002641716101654201788071096152948830924149045094")],
[Fr.e("5802099305472655231388284418920769829666717045250560929368476121199858275951"),Fr.e("5980429700218124965372158798884772646841287887664001482443826541541529227896")],
[Fr.e("7107336197374528537877327281242680114152313102022415488494307685842428166594"),Fr.e("2857869773864086953506483169737724679646433914307247183624878062391496185654")],
[Fr.e("20265828622013100949498132415626198973119240347465898028410217039057588424236"),Fr.e("1160461593266035632937973507065134938065359936056410650153315956301179689506")]
];
describe("Double Pedersen test", function() {
let circuit;
this.timeout(100000);
before( async() => {
const cirDef = await compiler(path.join(__dirname, "circuits", "pedersen_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
circuit = await tester(path.join(__dirname, "circuits", "pedersen_test.circom"));
console.log("NConstrains: " + circuit.nConstraints);
});
it("Should pedersen at zero", async () => {
let w, xout, yout;
let w;
w = circuit.calculateWitness({ in: ["0", "0"]});
w = await circuit.calculateWitness({ in: ["0", "0"]}, true);
xout = w[circuit.getSignalIdx("main.out[0]")];
yout = w[circuit.getSignalIdx("main.out[1]")];
await circuit.assertOut(w, {out: [0,1]});
assert(xout.equals("0"));
assert(yout.equals("1"));
});
it("Should pedersen at one first generator", async () => {
let w, xout, yout;
let w;
w = circuit.calculateWitness({ in: ["1", "0"]});
w = await circuit.calculateWitness({ in: ["1", "0"]}, true);
xout = bigInt(w[circuit.getSignalIdx("main.out[0]")]);
yout = bigInt(w[circuit.getSignalIdx("main.out[1]")]);
await circuit.assertOut(w, {out: PBASE[0]});
assert(xout.equals(PBASE[0][0]));
assert(yout.equals(PBASE[0][1]));
});
it("Should pedersen at one second generator", async () => {
let w, xout, yout;
let w;
w = circuit.calculateWitness({ in: ["0", "1"]});
w = await circuit.calculateWitness({ in: ["0", "1"]}, true);
xout = w[circuit.getSignalIdx("main.out[0]")];
yout = w[circuit.getSignalIdx("main.out[1]")];
assert(xout.equals(PBASE[1][0]));
assert(yout.equals(PBASE[1][1]));
await circuit.assertOut(w, {out: PBASE[1]});
});
it("Should pedersen at mixed generators", async () => {
let w, xout, yout;
w = circuit.calculateWitness({ in: ["3", "7"]});
xout = w[circuit.getSignalIdx("main.out[0]")];
yout = w[circuit.getSignalIdx("main.out[1]")];
let w;
w = await circuit.calculateWitness({ in: ["3", "7"]}, true);
const r = babyJub.addPoint(
babyJub.mulPointEscalar(PBASE[0], 3),
babyJub.mulPointEscalar(PBASE[1], 7)
);
assert(xout.equals(r[0]));
assert(yout.equals(r[1]));
await circuit.assertOut(w, {out: r});
});
it("Should pedersen all ones", async () => {
let w, xout, yout;
let w;
const allOnes = bigInt("1").shl(250).sub(bigInt("1"));
w = circuit.calculateWitness({ in: [allOnes, allOnes]});
const allOnes = Fr.sub(Fr.shl(Fr.e("1"), Fr.e(250)), Fr.e("1"));
w = await circuit.calculateWitness({ in: [allOnes, allOnes]}, true);
xout = w[circuit.getSignalIdx("main.out[0]")];
yout = w[circuit.getSignalIdx("main.out[1]")];
const r2 = babyJub.addPoint(
babyJub.mulPointEscalar(PBASE[0], allOnes),
babyJub.mulPointEscalar(PBASE[1], allOnes)
);
assert(xout.equals(r2[0]));
assert(yout.equals(r2[1]));
await circuit.assertOut(w, {out: r2});
});
});

View File

@@ -1,11 +1,7 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
const Fr = require("ffjavascript").bn128.Fr;
const tester = require("circom").tester;
const babyJub = require("../src/babyjub.js");
const pedersen = require("../src/pedersenHash.js");
@@ -15,60 +11,39 @@ describe("Pedersen test", function() {
let circuit;
this.timeout(100000);
before( async() => {
const cirDef = await compiler(path.join(__dirname, "circuits", "pedersen2_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains Pedersen2: " + circuit.nConstraints);
circuit = await tester(path.join(__dirname, "circuits", "pedersen2_test.circom"));
});
it("Should pedersen at zero", async () => {
let w, xout, yout;
let w;
w = circuit.calculateWitness({ in: 0});
xout = w[circuit.getSignalIdx("main.out[0]")];
yout = w[circuit.getSignalIdx("main.out[1]")];
w = await circuit.calculateWitness({ in: 0}, true);
const b = Buffer.alloc(32);
const h = pedersen.hash(b);
const hP = babyJub.unpackPoint(h);
/*
console.log(`[${xout.toString()}, ${yout.toString()}]`);
console.log(`[${hP[0].toString()}, ${hP[1].toString()}]`);
*/
await circuit.assertOut(w, {out: hP});
assert(xout.equals(hP[0]));
assert(yout.equals(hP[1]));
});
it("Should pedersen with 253 ones", async () => {
let w, xout, yout;
let w;
const n = bigInt.one.shl(253).sub(bigInt.one);
console.log(n.toString(16));
const n = Fr.sub(Fr.shl(Fr.one, Fr.e(253)), Fr.one);
w = circuit.calculateWitness({ in: n});
xout = w[circuit.getSignalIdx("main.out[0]")];
yout = w[circuit.getSignalIdx("main.out[1]")];
w = await circuit.calculateWitness({ in: n}, true);
const b = Buffer.alloc(32);
for (let i=0; i<31; i++) b[i] = 0xFF;
b[31] = 0x1F;
const h = pedersen.hash(b);
const hP = babyJub.unpackPoint(h);
/*
console.log(`[${xout.toString()}, ${yout.toString()}]`);
console.log(`[${hP[0].toString()}, ${hP[1].toString()}]`);
*/
await circuit.assertOut(w, {out: hP});
assert(xout.equals(hP[0]));
assert(yout.equals(hP[1]));
});
});

View File

@@ -1,11 +1,5 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
const tester = require("circom").tester;
const babyJub = require("../src/babyjub.js");
@@ -14,20 +8,16 @@ describe("Point 2 bits test", function() {
let circuit;
this.timeout(100000);
before( async() => {
const cirDef = await compiler(path.join(__dirname, "circuits", "pointbits_loopback.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains Point2Bits loopback: " + circuit.nConstraints);
circuit = await tester(path.join(__dirname, "circuits", "pointbits_loopback.circom"));
});
it("Should do the both convertions for 8Base", async () => {
const w = circuit.calculateWitness({ in: babyJub.Base8});
const w = await circuit.calculateWitness({ in: babyJub.Base8}, true);
assert(circuit.checkWitness(w));
await circuit.checkConstraints(w);
});
it("Should do the both convertions for Zero point", async () => {
const w = circuit.calculateWitness({ in: [0, 1]});
const w = await circuit.calculateWitness({ in: [0, 1]}, true);
assert(circuit.checkWitness(w));
await circuit.checkConstraints(w);
});
});

View File

@@ -1,60 +1,57 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
var blake2b = require('blake2b');
const tester = require("circom").tester;
const poseidon = require("../src/poseidon.js");
const assert = chai.assert;
describe("Blake2b version test", function() {
it("Should give the expected output for blake2b version", async () => {
var output = new Uint8Array(32);
var input = Buffer.from('poseidon_constants');
h = blake2b(output.length).update(input).digest('hex')
assert.equal('e57ba154fb2c47811dc1a2369b27e25a44915b4e4ece4eb8ec74850cb78e01b1', h);
});
});
describe("Poseidon Circuit test", function () {
let circuit;
let circuit6;
let circuit3;
this.timeout(100000);
before( async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "poseidon_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("Poseidon constraints: " + circuit.nConstraints);
circuit6 = await tester(path.join(__dirname, "circuits", "poseidon6_test.circom"));
circuit3 = await tester(path.join(__dirname, "circuits", "poseidon3_test.circom"));
});
it("Should check constrain of hash([1, 2])", async () => {
const w = circuit.calculateWitness({inputs: [1, 2]});
it("Should check constrain of hash([1, 2]) t=6", async () => {
const w = await circuit6.calculateWitness({inputs: [1, 2, 0,0,0]}, true);
const res = w[circuit.getSignalIdx("main.out")];
const hash = poseidon.createHash(6, 8, 57);
const res2 = hash([1,2]);
assert.equal('12242166908188651009877250812424843524687801523336557272219921456462821518061', res2.toString());
assert.equal(res.toString(), res2.toString());
assert(circuit.checkWitness(w));
const res2 = poseidon([1,2,0,0,0]);
assert.equal("3975478831357328722254985704342968745327876719981393787143845259590563829094", res2.toString());
await circuit6.assertOut(w, {out : res2});
await circuit6.checkConstraints(w);
});
it("Should check constrain of hash([3, 4])", async () => {
const w = circuit.calculateWitness({inputs: [3, 4]});
it("Should check constrain of hash([3, 4]) t=6", async () => {
const w = await circuit6.calculateWitness({inputs: [3, 4,5,10,23]});
const res = w[circuit.getSignalIdx("main.out")];
const res2 = poseidon([3, 4,5,10,23]);
const hash = poseidon.createHash(6, 8, 57);
assert.equal("18540626624821144952552691894137986276337186174352554475896834101336254024067", res2.toString());
await circuit6.assertOut(w, {out : res2});
await circuit6.checkConstraints(w);
});
const res2 = hash([3, 4]);
assert.equal('17185195740979599334254027721507328033796809509313949281114643312710535000993', res2.toString());
assert.equal(res.toString(), res2.toString());
it("Should check constrain of hash([1, 2]) t=3", async () => {
const w = await circuit3.calculateWitness({inputs: [1, 2]});
assert(circuit.checkWitness(w));
const res2 = poseidon([1,2]);
assert.equal("17117985411748610629288516079940078114952304104811071254131751175361957805920", res2.toString());
await circuit3.assertOut(w, {out : res2});
await circuit3.checkConstraints(w);
});
it("Should check constrain of hash([3, 4]) t=3", async () => {
const w = await circuit3.calculateWitness({inputs: [3, 4]});
const res2 = poseidon([3, 4]);
assert.equal("21867347236198497199818917118739170715216974132230970409806500217655788551452", res2.toString());
await circuit3.assertOut(w, {out : res2});
await circuit3.checkConstraints(w);
});
});

View File

@@ -2,19 +2,18 @@ const ganache = require("ganache-cli");
const Web3 = require("web3");
const chai = require("chai");
const poseidonGenContract = require("../src/poseidon_gencontract.js");
const Poseidon = require("../src/poseidon.js");
const bigInt = require("snarkjs").bigInt;
const poseidon = require("../src/poseidon.js");
const assert = chai.assert;
const log = (msg) => { if (process.env.MOCHA_VERBOSE) console.log(msg); };
const SEED = "mimc";
describe("Poseidon Smart contract test", () => {
describe("Poseidon Smart contract test", function () {
let testrpc;
let web3;
let mimc;
let poseidon6;
let poseidon3;
let accounts;
this.timeout(100000);
before(async () => {
web3 = new Web3(ganache.provider(), null, { transactionConfirmationBlocks: 1 });
@@ -22,28 +21,45 @@ describe("Poseidon Smart contract test", () => {
});
it("Should deploy the contract", async () => {
const C = new web3.eth.Contract(poseidonGenContract.abi);
const C6 = new web3.eth.Contract(poseidonGenContract.generateABI(5));
const C3 = new web3.eth.Contract(poseidonGenContract.generateABI(2));
mimc = await C.deploy({
data: poseidonGenContract.createCode()
poseidon6 = await C6.deploy({
data: poseidonGenContract.createCode(5)
}).send({
gas: 2500000,
gas: 5000000,
from: accounts[0]
});
poseidon3 = await C3.deploy({
data: poseidonGenContract.createCode(2)
}).send({
gas: 5000000,
from: accounts[0]
});
});
it("Shold calculate the mimic correctly", async () => {
it("Should calculate the poseidon correctly t=6", async () => {
const res = await mimc.methods.poseidon([1,2]).call();
const res = await poseidon6.methods.poseidon([1,2, 0, 0, 0]).call();
// console.log("Cir: " + bigInt(res.toString(16)).toString(16));
const hash = Poseidon.createHash(6, 8, 57);
const res2 = hash([1,2]);
const res2 = poseidon([1,2, 0, 0, 0]);
// console.log("Ref: " + bigInt(res2).toString(16));
assert.equal(res.toString(), res2.toString());
});
it("Should calculate the poseidon correctly t=3", async () => {
const res = await poseidon3.methods.poseidon([1,2]).call();
// console.log("Cir: " + bigInt(res.toString(16)).toString(16));
const res2 = poseidon([1,2]);
// console.log("Ref: " + bigInt(res2).toString(16));
assert.equal(res.toString(), res2.toString());
});
});

View File

@@ -1,14 +1,14 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const crypto = require("crypto");
const compiler = require("circom");
const Fr = require("ffjavascript").bn128.Fr;
const assert = chai.assert;
const sha256 = require("./helpers/sha256");
const tester = require("circom").tester;
// const printSignal = require("./helpers/printsignal");
@@ -34,7 +34,8 @@ function bitArray2buffer(a) {
}
describe("SHA256 test", () => {
describe("SHA256 test", function () {
this.timeout(100000);
it("Should work bits to array and array to bits", async () => {
@@ -45,17 +46,13 @@ describe("SHA256 test", () => {
const a = buffer2bitArray(b);
const b2 = bitArray2buffer(a);
assert.equal(b.toString("hex"), b2.toString("hex"));
assert.equal(b.toString("hex"), b2.toString("hex"), true);
});
it("Should calculate a hash of 1 compressor", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "sha256_2_test.circom"));
const circuit = new snarkjs.Circuit(cirDef);
const cir = await tester(path.join(__dirname, "circuits", "sha256_2_test.circom"));
console.log("Vars: "+circuit.nVars);
console.log("Constraints: "+circuit.nConstraints);
const witness = circuit.calculateWitness({ "a": "1", "b": "2" });
const witness = await cir.calculateWitness({ "a": "1", "b": "2" }, true);
const b = new Buffer.alloc(54);
b[26] = 1;
@@ -70,21 +67,12 @@ describe("SHA256 test", () => {
assert.equal(hash, hash2);
assert(witness[1].equals(snarkjs.bigInt(r)));
assert(Fr.eq(witness[1], Fr.e(r)));
}).timeout(1000000);
it("Should calculate a hash of 2 compressor", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "sha256_test512.circom"), {reduceConstraints:false} );
const circuit = new snarkjs.Circuit(cirDef);
const cir = await tester(path.join(__dirname, "circuits", "sha256_test512.circom"));
console.log("Vars: "+circuit.nVars);
console.log("Constraints: "+circuit.nConstraints);
/*
const testStr = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
const b = Buffer.from(testStr, 'utf8');
*/
const b = new Buffer.alloc(64);
for (let i=0; i<64; i++) {
b[i] = i+1;
@@ -95,7 +83,7 @@ describe("SHA256 test", () => {
.digest("hex");
const arrIn = buffer2bitArray(b);
const witness = circuit.calculateWitness({ "in": arrIn } /*, {logOutput: true} */);
const witness = await cir.calculateWitness({ "in": arrIn }, true);
const arrOut = witness.slice(1, 257);
const hash2 = bitArray2buffer(arrOut).toString("hex");
@@ -103,34 +91,25 @@ describe("SHA256 test", () => {
assert.equal(hash, hash2);
}).timeout(1000000);
it ("Should calculate a hash of 2 compressor", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "sha256_test448.circom"), {reduceConstraints:false} );
const circuit = new snarkjs.Circuit(cirDef);
console.log("Vars: "+circuit.nVars);
console.log("Constraints: "+circuit.nConstraints);
const cir = await tester(path.join(__dirname, "circuits", "sha256_test448.circom"));
const testStr = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
const b = Buffer.from(testStr, 'utf8');
for (let i=0; i<64; i++) {
b[i] = i+1;
}
const b = Buffer.from(testStr, "utf8");
const hash = crypto.createHash("sha256")
.update(b)
.digest("hex");
const arrIn = buffer2bitArray(b);
const witness = circuit.calculateWitness({ "in": arrIn } /*, {logOutput: true} */);
const witness = await cir.calculateWitness({ "in": arrIn }, true);
const arrOut = witness.slice(1, 257);
const hash2 = bitArray2buffer(arrOut).toString("hex");
assert.equal(hash, hash2);
}).timeout(1000000);
});
});

View File

@@ -1,11 +1,7 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
const Fr = require("ffjavascript").bn128.Fr;
const Scalar = require("ffjavascript").Scalar;
const tester = require("circom").tester;
function print(circuit, w, s) {
console.log(s + ": " + w[circuit.getSignalIdx(s)]);
@@ -14,75 +10,71 @@ function print(circuit, w, s) {
function getBits(v, n) {
const res = [];
for (let i=0; i<n; i++) {
if (v.shr(i).isOdd()) {
res.push(bigInt.one);
if (Scalar.isOdd(Scalar.shr(v, i))) {
res.push(Fr.one);
} else {
res.push(bigInt.zero);
res.push(Fr.zero);
}
}
return res;
}
const q = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
const q = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
describe("Sign test", () => {
describe("Sign test", function() {
let circuit;
this.timeout(100000);
before( async() => {
const cirDef = await compiler(path.join(__dirname, "circuits", "sign_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains: " + circuit.nConstraints);
circuit = await tester(path.join(__dirname, "circuits", "sign_test.circom"));
});
it("Sign of 0", async () => {
const inp = getBits(bigInt.zero, 254);
const w = circuit.calculateWitness({in: inp});
const inp = getBits(Scalar.e(0), 254);
const w = await circuit.calculateWitness({in: inp}, true);
assert( w[circuit.getSignalIdx("main.sign")].equals(bigInt(0)) );
await circuit.assertOut(w, {sign: 0});
});
it("Sign of 3", async () => {
const inp = getBits(bigInt(3), 254);
const w = circuit.calculateWitness({in: inp});
const inp = getBits(Scalar.e(3), 254);
const w = await circuit.calculateWitness({in: inp}, true);
assert( w[circuit.getSignalIdx("main.sign")].equals(bigInt(0)) );
await circuit.assertOut(w, {sign: 0});
});
it("Sign of q/2", async () => {
const inp = getBits(q.shr(bigInt.one), 254);
const w = circuit.calculateWitness({in: inp});
const inp = getBits(Scalar.shr(q, 1), 254);
const w = await circuit.calculateWitness({in: inp}, true);
assert( w[circuit.getSignalIdx("main.sign")].equals(bigInt(0)) );
await circuit.assertOut(w, {sign: 0});
});
it("Sign of q/2+1", async () => {
const inp = getBits(q.shr(bigInt.one).add(bigInt.one), 254);
const w = circuit.calculateWitness({in: inp});
const inp = getBits(Scalar.add(Scalar.shr(q, 1), 1) , 254);
const w = await circuit.calculateWitness({in: inp}, true);
assert( w[circuit.getSignalIdx("main.sign")].equals(bigInt(1)) );
await circuit.assertOut(w, {sign: 1});
});
it("Sign of q-1", async () => {
const inp = getBits(q.sub(bigInt.one), 254);
const w = circuit.calculateWitness({in: inp});
const inp = getBits(Scalar.sub(q, 1), 254);
const w = await circuit.calculateWitness({in: inp}, true);
assert( w[circuit.getSignalIdx("main.sign")].equals(bigInt(1)) );
await circuit.assertOut(w, {sign: 1});
});
it("Sign of q", async () => {
const inp = getBits(q, 254);
const w = circuit.calculateWitness({in: inp});
const w = await circuit.calculateWitness({in: inp}, true);
assert( w[circuit.getSignalIdx("main.sign")].equals(bigInt(1)) );
await circuit.assertOut(w, {sign: 1});
});
it("Sign of all ones", async () => {
const inp = getBits(bigInt(1).shl(254).sub(bigInt(1)), 254);
const w = circuit.calculateWitness({in: inp});
const inp = getBits(Scalar.sub(Scalar.shl(1,254),1), 254);
const w = await circuit.calculateWitness({in: inp}, true);
assert( w[circuit.getSignalIdx("main.sign")].equals(bigInt(1)) );
await circuit.assertOut(w, {sign: 1});
});
});

View File

@@ -1,29 +1,11 @@
const chai = require("chai");
const snarkjs = require("snarkjs");
const Fr = require("ffjavascript").bn128.Fr;
const smt = require("../src/smt.js");
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
function stringifyBigInts(o) {
if ((typeof(o) == "bigint") || (o instanceof bigInt)) {
return o.toString(10);
} else if (Array.isArray(o)) {
return o.map(stringifyBigInts);
} else if (typeof o == "object") {
const res = {};
for (let k in o) {
res[k] = stringifyBigInts(o[k]);
}
return res;
} else {
return o;
}
}
describe("SMT Javascript test", function () {
this.timeout(100000);
before( async () => {
@@ -31,22 +13,22 @@ describe("SMT Javascript test", function () {
it("Should insert 2 elements and empty them", async () => {
const tree = await smt.newMemEmptyTrie();
const key1 = bigInt(111);
const value1 = bigInt(222);
const key2 = bigInt(333);
const value2 = bigInt(444);
const key1 = Fr.e(111);
const value1 = Fr.e(222);
const key2 = Fr.e(333);
const value2 = Fr.e(444);
await tree.insert(key1,value1);
await tree.insert(key2,value2);
await tree.delete(key2);
await tree.delete(key1);
assert(tree.root.isZero());
assert(Fr.isZero(tree.root));
});
it("Should insert 3 elements in dferent order and should be the same", async () => {
const keys = [bigInt(8), bigInt(9), bigInt(32)];
const values = [bigInt(88), bigInt(99), bigInt(3232)];
const keys = [Fr.e(8), Fr.e(9), Fr.e(32)];
const values = [Fr.e(88), Fr.e(99), Fr.e(3232)];
const tree1 = await smt.newMemEmptyTrie();
const tree2 = await smt.newMemEmptyTrie();
const tree3 = await smt.newMemEmptyTrie();
@@ -78,11 +60,11 @@ describe("SMT Javascript test", function () {
await tree6.insert(keys[1],values[1]);
await tree6.insert(keys[0],values[0]);
assert(tree1.root.equals(tree2.root));
assert(tree2.root.equals(tree3.root));
assert(tree3.root.equals(tree4.root));
assert(tree4.root.equals(tree5.root));
assert(tree5.root.equals(tree6.root));
assert(Fr.eq(tree1.root, tree2.root));
assert(Fr.eq(tree2.root, tree3.root));
assert(Fr.eq(tree3.root, tree4.root));
assert(Fr.eq(tree4.root, tree5.root));
assert(Fr.eq(tree5.root, tree6.root));
assert.equal(Object.keys(tree1.db.nodes).length, Object.keys(tree2.db.nodes).length);
assert.equal(Object.keys(tree2.db.nodes).length, Object.keys(tree3.db.nodes).length);
@@ -94,19 +76,19 @@ describe("SMT Javascript test", function () {
await tree1.delete(keys[1]);
await tree2.delete(keys[1]);
await tree2.delete(keys[0]);
assert(tree1.root.equals(tree2.root));
assert(Fr.eq(tree1.root, tree2.root));
await tree3.delete(keys[0]);
await tree3.delete(keys[2]);
await tree4.delete(keys[2]);
await tree4.delete(keys[0]);
assert(tree3.root.equals(tree4.root));
assert(Fr.eq(tree3.root, tree4.root));
await tree5.delete(keys[1]);
await tree5.delete(keys[2]);
await tree6.delete(keys[2]);
await tree6.delete(keys[1]);
assert(tree5.root.equals(tree6.root));
assert(Fr.eq(tree5.root, tree6.root));
await tree1.delete(keys[2]);
await tree2.delete(keys[2]);
@@ -115,12 +97,12 @@ describe("SMT Javascript test", function () {
await tree5.delete(keys[0]);
await tree6.delete(keys[0]);
assert(tree1.root.isZero());
assert(tree2.root.isZero());
assert(tree3.root.isZero());
assert(tree4.root.isZero());
assert(tree5.root.isZero());
assert(tree6.root.isZero());
assert(Fr.isZero(tree1.root));
assert(Fr.isZero(tree2.root));
assert(Fr.isZero(tree3.root));
assert(Fr.isZero(tree4.root));
assert(Fr.isZero(tree5.root));
assert(Fr.isZero(tree6.root));
assert.equal(Object.keys(tree1.db.nodes).length, 0);
assert.equal(Object.keys(tree2.db.nodes).length, 0);
@@ -145,7 +127,7 @@ describe("SMT Javascript test", function () {
const arr = [];
const N = 100;
for (let i=0; i<N; i++) {
arr.push(bigInt(i));
arr.push(Fr.e(i));
}
const insArr = perm(arr);
for (let i=0; i<N; i++) {
@@ -156,7 +138,7 @@ describe("SMT Javascript test", function () {
await tree.delete(delArr[i]);
}
assert(tree.root.isZero());
assert(Fr.isZero(tree.root));
assert.equal(Object.keys(tree.db.nodes).length, 0);
});
@@ -176,7 +158,16 @@ describe("SMT Javascript test", function () {
await tree1.update(9, 999);
await tree1.update(32, 323232);
assert(tree1.root.equals(tree2.root));
assert(Fr.eq(tree1.root, tree2.root));
});
it("Should test update with same key-value", async () => {
const tree1 = await smt.newMemEmptyTrie();
await tree1.insert(8,88);
await tree1.update(8,88);
const res = await tree1.db.get(tree1.root);
assert.notEqual(res, undefined);
});
});

View File

@@ -1,25 +1,23 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const tester = require("circom").tester;
const Fr = require("ffjavascript").bn128.Fr;
const smt = require("../src/smt.js");
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
function print(circuit, w, s) {
console.log(s + ": " + w[circuit.getSignalIdx(s)]);
}
async function testInsert(tree, key, value, circuit, log ) {
async function testInsert(tree, key, value, circuit ) {
const res = await tree.insert(key,value);
let siblings = res.siblings;
while (siblings.length<10) siblings.push(bigInt(0));
while (siblings.length<10) siblings.push(Fr.e(0));
const w = circuit.calculateWitness({
const w = await circuit.calculateWitness({
fnc: [1,0],
oldRoot: res.oldRoot,
siblings: siblings,
@@ -28,19 +26,20 @@ async function testInsert(tree, key, value, circuit, log ) {
isOld0: res.isOld0 ? 1 : 0,
newKey: key,
newValue: value
}, log);
}, true);
await circuit.checkConstraints(w);
await circuit.assertOut(w, {newRoot: res.newRoot});
const root1 = w[circuit.getSignalIdx("main.newRoot")];
assert(circuit.checkWitness(w));
assert(root1.equals(res.newRoot));
}
async function testDelete(tree, key, circuit) {
const res = await tree.delete(key);
let siblings = res.siblings;
while (siblings.length<10) siblings.push(bigInt(0));
while (siblings.length<10) siblings.push(Fr.e(0));
const w = circuit.calculateWitness({
const w = await circuit.calculateWitness({
fnc: [1,1],
oldRoot: res.oldRoot,
siblings: siblings,
@@ -49,20 +48,19 @@ async function testDelete(tree, key, circuit) {
isOld0: res.isOld0 ? 1 : 0,
newKey: res.delKey,
newValue: res.delValue
});
}, true);
const root1 = w[circuit.getSignalIdx("main.newRoot")];
await circuit.checkConstraints(w);
assert(circuit.checkWitness(w));
assert(root1.equals(res.newRoot));
await circuit.assertOut(w, {newRoot: res.newRoot});
}
async function testUpdate(tree, key, newValue, circuit) {
const res = await tree.update(key, newValue);
let siblings = res.siblings;
while (siblings.length<10) siblings.push(bigInt(0));
while (siblings.length<10) siblings.push(Fr.e(0));
const w = circuit.calculateWitness({
const w = await circuit.calculateWitness({
fnc: [0,1],
oldRoot: res.oldRoot,
siblings: siblings,
@@ -73,53 +71,47 @@ async function testUpdate(tree, key, newValue, circuit) {
newValue: res.newValue
});
const root1 = w[circuit.getSignalIdx("main.newRoot")];
await circuit.checkConstraints(w);
assert(circuit.checkWitness(w));
assert(root1.equals(res.newRoot));
await circuit.assertOut(w, {newRoot: res.newRoot});
}
describe("SMT test", function () {
describe("SMT Processor test", function () {
let circuit;
let tree;
this.timeout(10000000);
before( async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "smtprocessor10_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains SMTProcessor: " + circuit.nConstraints);
circuit = await tester(path.join(__dirname, "circuits", "smtprocessor10_test.circom"));
await circuit.loadSymbols();
tree = await smt.newMemEmptyTrie();
});
it("Should verify an insert to an empty tree", async () => {
const key = bigInt(111);
const value = bigInt(222);
const key = Fr.e(111);
const value = Fr.e(222);
await testInsert(tree, key, value, circuit);
});
it("It should add another element", async () => {
const key = bigInt(333);
const value = bigInt(444);
const key = Fr.e(333);
const value = Fr.e(444);
await testInsert(tree, key, value, circuit);
});
it("Should remove an element", async () => {
await testDelete(tree, 111, circuit);
await testDelete(tree, 333, circuit);
});
it("Should test convination of adding and removing 3 elements", async () => {
const keys = [bigInt(8), bigInt(9), bigInt(32)];
const values = [bigInt(88), bigInt(99), bigInt(3232)];
const keys = [Fr.e(8), Fr.e(9), Fr.e(32)];
const values = [Fr.e(88), Fr.e(99), Fr.e(3232)];
const tree1 = await smt.newMemEmptyTrie();
const tree2 = await smt.newMemEmptyTrie();
const tree3 = await smt.newMemEmptyTrie();
@@ -178,8 +170,8 @@ describe("SMT test", function () {
it("Should match a NOp with random vals", async () => {
let siblings = [];
while (siblings.length<10) siblings.push(bigInt(88));
const w = circuit.calculateWitness({
while (siblings.length<10) siblings.push(Fr.e(88));
const w = await circuit.calculateWitness({
fnc: [0,0],
oldRoot: 11,
siblings: siblings,
@@ -190,12 +182,12 @@ describe("SMT test", function () {
newValue: 77
});
const root1 = w[circuit.getSignalIdx("main.oldRoot")];
const root2 = w[circuit.getSignalIdx("main.newRoot")];
const root1 = w[circuit.symbols["main.oldRoot"].varIdx];
const root2 = w[circuit.symbols["main.newRoot"].varIdx];
assert(circuit.checkWitness(w));
assert(root1.equals(root2));
await circuit.checkConstraints(w);
assert(Fr.eq(root1, root2));
});
it("Should update an element", async () => {
const tree1 = await smt.newMemEmptyTrie();
@@ -213,5 +205,4 @@ describe("SMT test", function () {
await testUpdate(tree1, 9, 999, circuit);
await testUpdate(tree1, 32, 323232, circuit);
});
});

View File

@@ -1,14 +1,12 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("snarkjs");
const compiler = require("circom");
const Fr = require("ffjavascript").bn128.Fr;
const tester = require("circom").tester;
const smt = require("../src/smt.js");
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
function print(circuit, w, s) {
console.log(s + ": " + w[circuit.getSignalIdx(s)]);
}
@@ -19,9 +17,9 @@ async function testInclusion(tree, key, circuit) {
assert(res.found);
let siblings = res.siblings;
while (siblings.length<10) siblings.push(bigInt(0));
while (siblings.length<10) siblings.push(Fr.e(0));
const w = circuit.calculateWitness({
const w = await circuit.calculateWitness({
enabled: 1,
fnc: 0,
root: tree.root,
@@ -31,9 +29,10 @@ async function testInclusion(tree, key, circuit) {
isOld0: 0,
key: key,
value: res.foundValue
});
}, true);
await circuit.checkConstraints(w);
assert(circuit.checkWitness(w));
}
async function testExclusion(tree, key, circuit) {
@@ -41,9 +40,9 @@ async function testExclusion(tree, key, circuit) {
assert(!res.found);
let siblings = res.siblings;
while (siblings.length<10) siblings.push(bigInt(0));
while (siblings.length<10) siblings.push(Fr.e(0));
const w = circuit.calculateWitness({
const w = await circuit.calculateWitness({
enabled: 1,
fnc: 1,
root: tree.root,
@@ -55,21 +54,18 @@ async function testExclusion(tree, key, circuit) {
value: 0
});
assert(circuit.checkWitness(w));
await circuit.checkConstraints(w);
}
describe("SMT test", function () {
describe("SMT Verifier test", function () {
let circuit;
let tree;
this.timeout(100000);
before( async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "smtverifier10_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains SMTVerifier: " + circuit.nConstraints);
circuit = await tester(path.join(__dirname, "circuits", "smtverifier10_test.circom"));
tree = await smt.newMemEmptyTrie();
await tree.insert(7,77);
@@ -97,7 +93,7 @@ describe("SMT test", function () {
let siblings = [];
for (let i=0; i<10; i++) siblings.push(i);
const w = circuit.calculateWitness({
const w = await circuit.calculateWitness({
enabled: 0,
fnc: 0,
root: 1,
@@ -108,7 +104,32 @@ describe("SMT test", function () {
key: 44,
value: 0
});
assert(circuit.checkWitness(w));
await circuit.checkConstraints(w);
});
it("Check inclussion Adria case", async () => {
const e1_hi= Fr.e("17124152697573569611556136390143205198134245887034837071647643529178599000839");
const e1_hv= Fr.e("19650379996168153643111744440707177573540245771926102415571667548153444658179");
const e2ok_hi= Fr.e("16498254692537945203721083102154618658340563351558973077349594629411025251262");
const e2ok_hv= Fr.e("19650379996168153643111744440707177573540245771926102415571667548153444658179");
const e2fail_hi= Fr.e("17195092312975762537892237130737365903429674363577646686847513978084990105579");
const e2fail_hv= Fr.e("19650379996168153643111744440707177573540245771926102415571667548153444658179");
const tree1 = await smt.newMemEmptyTrie();
await tree1.insert(e1_hi,e1_hv);
await tree1.insert(e2ok_hi,e2ok_hv);
await testInclusion(tree1, e2ok_hi, circuit);
const tree2 = await smt.newMemEmptyTrie();
await tree2.insert(e1_hi,e1_hv);
await tree2.insert(e2fail_hi,e2fail_hv);
await testInclusion(tree2, e2fail_hi, circuit);
});