Compare commits

..

37 Commits

Author SHA1 Message Date
14314b6bbb Bump version & use snarkjs dependency from self-hosted tornado git registry 2023-09-12 01:22:49 -07:00
Alexey
3b492f9801 poseidon contract now accepts both selectors: for uint256[n] and bytes32[n] 2020-10-27 21:31:39 +03:00
poma
afb4eff954
use 35 rounds for poseidon hash, update poseidon constants from sage script for 35 rounds 2020-10-27 13:23:41 +03:00
Alexey Pertsev
47f33f2275
Merge pull request #2 from tornadocash/poseidon-fixed-array
pass fixes size array arg in solidity poseidon implementation
2020-10-26 16:32:04 +03:00
Alexey
118238ea62 pass fixes size array arg in solidity poseidon implementation 2020-10-26 16:30:10 +03:00
poma
c4496aecc8
fix poseidon contract bug 2020-10-26 16:08:57 +03:00
poma
5beb6aee94
fix dependency 2020-08-19 01:31:49 +03:00
poma
6282474dc0
fix tests 2020-08-10 13:42:52 +03:00
poma
436cf45a04
poseidon contract 2020-08-10 13:19:52 +03:00
poma
528b292da5
Update references to Poseidon hash in the project 2020-08-10 13:18:02 +03:00
poma
82c2f606cc
Rewrite Poseidon hash implementation to be compatible with reference implementation 2020-08-10 13:13:45 +03:00
poma
48efcf02ce
update web3 2020-07-31 23:24:02 +03:00
Alexey
c372f14d32 pin snarkjs version 2020-04-06 13:00:11 +03:00
Pertsev Alexey
ce5dbe8e1a
Merge pull request #1 from tornadocash/feat/audit_fixes
Feat/audit fixes
2020-04-06 12:55:59 +03:00
Kobi Gurkan
3478226049 Merge remote-tracking branch 'iden3/master' into feat/audit_fixes 2019-12-11 18:33:31 +02: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
Kobi Gurkan
eeecd07cae Merge remote-tracking branch 'iden3/master' into feat/audit_fixes 2019-12-03 20:26:43 +02:00
Jordi Baylina
d6e6a3b3f4
Fix assigning to signal 2019-12-03 19:16:19 +01:00
Kobi Gurkan
b928421c58 adds comment about baby pbk public key extraction 2019-12-01 15:38:38 +02:00
Kobi Gurkan
8445381431 escalarmulfix uses segments of 246 and adds comments on limits 2019-11-23 22:00:11 +02:00
Kobi Gurkan
42e96c2e1f makes S value in eddsa signatures be 251 bit, uses alias checks with enabled flag and adds eddsamimcsponge test 2019-11-23 21:36:06 +02:00
Kobi Gurkan
5ec0744303 adds alias check for babyjubjub 2019-11-23 21:19:47 +02:00
Kobi Gurkan
451fb51a0d adds comments to binsum 2019-11-23 19:24:02 +02:00
Kobi Gurkan
ba656fefbe mimcsponge: makes the contract hash-only 2019-11-14 17:31:00 +02:00
Kobi Gurkan
5d626852ae Merge remote-tracking branch 'iden3/master' into feat/mimc_constant 2019-11-14 16:25:12 +02:00
Kobi Gurkan
de9c7dda46 mimcsponge: makes rounds constant 2019-11-14 16:24:29 +02: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
Marta Belles
97b870b725 Updated README files 2019-09-06 17:14:45 +02:00
83 changed files with 5154 additions and 4896 deletions

1
.npmrc Normal file
View File

@ -0,0 +1 @@
@tornado:registry=https://git.tornado.ws/api/packages/tornado-packages/npm/

View File

@ -1,4 +1,17 @@
# 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).
## 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,5 +1,5 @@
const bn128 = require("snarkjs").bn128; const bn128 = require("@tornado/snarkjs").bn128;
const bigInt = require("snarkjs").bigInt; const bigInt = require("@tornado/snarkjs").bigInt;
const createBlakeHash = require("blake-hash"); const createBlakeHash = require("blake-hash");
const babyJub = require("../src/babyjub"); const babyJub = require("../src/babyjub");
@ -8,12 +8,12 @@ function getPoint(S) {
const h = createBlakeHash("blake256").update(S).digest(); const h = createBlakeHash("blake256").update(S).digest();
if (h.length != 32) { if (h.length != 32) {
throw new Error("Invalid length") throw new Error("Invalid length");
} }
let sign = false; let sign = false;
if (h[31] & 0x80) { if (h[31] & 0x80) {
h[31] = h[31] & 0x7F; h[31] = h[31] & 0x7f;
sign = true; sign = true;
} }
@ -28,9 +28,7 @@ function getPoint(S) {
const y2 = F.square(y); const y2 = F.square(y);
let x = F.sqrt(F.div( let x = F.sqrt(F.div(F.sub(F.one, y2), F.sub(a, F.mul(d, y2))));
F.sub(F.one, y2),
F.sub(a, F.mul(d, y2))));
if (x == null) return null; if (x == null) return null;
@ -43,7 +41,6 @@ function getPoint(S) {
return p8; return p8;
} }
function generatePoint(S) { function generatePoint(S) {
let p = null; let p = null;
let idx = 0; let idx = 0;
@ -59,13 +56,10 @@ function generatePoint(S) {
return p; return p;
} }
const g = [ const g = [
bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"), bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")]; bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203"),
];
// Sanity check // Sanity check
if (!babyJub.inCurve(g)) { if (!babyJub.inCurve(g)) {
@ -78,6 +72,3 @@ for (let i=0; i<25; i++) {
const P = generatePoint("Iden3_PedersenGenerator_" + S); const P = generatePoint("Iden3_PedersenGenerator_" + S);
console.log(`[${P[0].toString()}, ${P[1].toString()}]`); console.log(`[${P[0].toString()}, ${P[1].toString()}]`);
} }

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

@ -21,7 +21,6 @@ include "compconstant.circom";
template AliasCheck() { template AliasCheck() {
signal input in[254]; signal input in[254];
component compConstant = CompConstant(-1); component compConstant = CompConstant(-1);
@ -30,3 +29,15 @@ template AliasCheck() {
compConstant.out === 0; compConstant.out === 0;
} }
template AliasCheckBabyJub() {
signal input in[251];
signal input enabled;
component compConstant = CompConstant(2736030358979909402780800718157159386076813972158567259200215660948447373040);
for (var i=0; i<251; i++) in[i] ==> compConstant.in[i];
for (var i=0; i<3; i++) 0 ==> compConstant.in[251+i];
compConstant.out*enabled === 0;
}

View File

@ -81,7 +81,7 @@ template BabyCheck() {
a*x2 + y2 === 1 + d*x2*y2; a*x2 + y2 === 1 + d*x2*y2;
} }
// Extracts the public key from private key // Extracts the public key from private key, as mentioned in https://tools.ietf.org/html/rfc8032
template BabyPbk() { template BabyPbk() {
signal private input in; signal private input in;
signal output Ax; signal output Ax;

View File

@ -50,6 +50,7 @@ To waranty binary outputs:
This function calculates the number of extra bits in the output to do the full sum. This function calculates the number of extra bits in the output to do the full sum.
*/ */
/* a must be < Nq/2, where Nq is the number of elements in the scalar field */
function nbits(a) { function nbits(a) {
var n = 1; var n = 1;
var r = 0; var r = 0;
@ -61,6 +62,7 @@ function nbits(a) {
} }
/* n must be such that (2**(n+1) -2) < Nq/ops, where Nq is the number of bits in the scalar field */
template BinSum(n, ops) { template BinSum(n, ops) {
var nout = nbits((2**n -1)*ops); var nout = nbits((2**n -1)*ops);
signal input in[ops][n]; signal input in[ops][n];

View File

@ -21,6 +21,7 @@ include "comparators.circom";
include "aliascheck.circom"; include "aliascheck.circom";
/* This doesn't check aliasing, so for n > 253 there are multiple bit strings for each number */
template Num2Bits(n) { template Num2Bits(n) {
signal input in; signal input in;
signal output out[n]; signal output out[n];
@ -76,6 +77,7 @@ template Bits2Num_strict() {
b2n.out ==> out; b2n.out ==> out;
} }
/* n must not exceed 253 */
template Num2BitsNeg(n) { template Num2BitsNeg(n) {
signal input in; signal input in;
signal output out[n]; signal output out[n];

View File

@ -17,7 +17,7 @@
along with circom. If not, see <https://www.gnu.org/licenses/>. along with circom. If not, see <https://www.gnu.org/licenses/>.
*/ */
include "compconstant.circom"; include "aliascheck.circom";
include "pointbits.circom"; include "pointbits.circom";
include "pedersen.circom"; include "pedersen.circom";
include "escalarmulany.circom"; include "escalarmulany.circom";
@ -40,12 +40,15 @@ template EdDSAVerifier(n) {
// Ensure S<Subgroup Order // Ensure S<Subgroup Order
component compConstant = CompConstant(2736030358979909402780800718157159386076813972158567259200215660948447373040); component aliasCheck = AliasCheckBabyJub();
aliasCheck.enabled <== 1;
for (i=0; i<254; i++) { for (i=0; i<251; i++) {
S[i] ==> compConstant.in[i]; S[i] ==> aliasCheck.in[i];
} }
compConstant.out === 0; S[251] === 0;
S[252] === 0;
S[253] === 0;
S[254] === 0; S[254] === 0;
S[255] === 0; S[255] === 0;

View File

@ -17,7 +17,7 @@
along with circom. If not, see <https://www.gnu.org/licenses/>. along with circom. If not, see <https://www.gnu.org/licenses/>.
*/ */
include "compconstant.circom"; include "aliascheck.circom";
include "pointbits.circom"; include "pointbits.circom";
include "mimc.circom"; include "mimc.circom";
include "bitify.circom"; include "bitify.circom";
@ -39,16 +39,15 @@ template EdDSAMiMCVerifier() {
// Ensure S<Subgroup Order // Ensure S<Subgroup Order
component snum2bits = Num2Bits(253); component snum2bits = Num2Bits(251);
snum2bits.in <== S; snum2bits.in <== S;
component compConstant = CompConstant(2736030358979909402780800718157159386076813972158567259200215660948447373040); component aliasCheck = AliasCheckBabyJub();
aliasCheck.enabled <== 1;
for (i=0; i<253; i++) { for (i=0; i<251; i++) {
snum2bits.out[i] ==> compConstant.in[i]; snum2bits.out[i] ==> aliasCheck.in[i];
} }
compConstant.in[253] <== 0;
compConstant.out === 0;
// Calculate the h = H(R,A, msg) // Calculate the h = H(R,A, msg)
@ -104,8 +103,8 @@ template EdDSAMiMCVerifier() {
5299619240641551281634865583518297030282874472190772894086521144482721001553, 5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203 16950150798460657717958625567821834550301663161624707787222815936182638968203
]; ];
component mulFix = EscalarMulFix(253, BASE8); component mulFix = EscalarMulFix(251, BASE8);
for (i=0; i<253; i++) { for (i=0; i<251; i++) {
mulFix.e[i] <== snum2bits.out[i]; mulFix.e[i] <== snum2bits.out[i];
} }

View File

@ -17,7 +17,7 @@
along with circom. If not, see <https://www.gnu.org/licenses/>. along with circom. If not, see <https://www.gnu.org/licenses/>.
*/ */
include "compconstant.circom"; include "aliascheck.circom";
include "pointbits.circom"; include "pointbits.circom";
include "mimcsponge.circom"; include "mimcsponge.circom";
include "bitify.circom"; include "bitify.circom";
@ -39,20 +39,19 @@ template EdDSAMiMCSpongeVerifier() {
// Ensure S<Subgroup Order // Ensure S<Subgroup Order
component snum2bits = Num2Bits(253); component snum2bits = Num2Bits(251);
snum2bits.in <== S; snum2bits.in <== S;
component compConstant = CompConstant(2736030358979909402780800718157159386076813972158567259200215660948447373040); component aliasCheck = AliasCheckBabyJub();
aliasCheck.enabled <== 1;
for (i=0; i<253; i++) { for (i=0; i<251; i++) {
snum2bits.out[i] ==> compConstant.in[i]; snum2bits.out[i] ==> aliasCheck.in[i];
} }
compConstant.in[253] <== 0;
compConstant.out === 0;
// Calculate the h = H(R,A, msg) // Calculate the h = H(R,A, msg)
component hash = MiMCSponge(5, 220, 1); component hash = MiMCSponge(5, 1);
hash.ins[0] <== R8x; hash.ins[0] <== R8x;
hash.ins[1] <== R8y; hash.ins[1] <== R8y;
hash.ins[2] <== Ax; hash.ins[2] <== Ax;
@ -104,8 +103,8 @@ template EdDSAMiMCSpongeVerifier() {
5299619240641551281634865583518297030282874472190772894086521144482721001553, 5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203 16950150798460657717958625567821834550301663161624707787222815936182638968203
]; ];
component mulFix = EscalarMulFix(253, BASE8); component mulFix = EscalarMulFix(251, BASE8);
for (i=0; i<253; i++) { for (i=0; i<251; i++) {
mulFix.e[i] <== snum2bits.out[i]; mulFix.e[i] <== snum2bits.out[i];
} }

View File

@ -38,20 +38,19 @@ template EdDSAPoseidonVerifier() {
// Ensure S<Subgroup Order // Ensure S<Subgroup Order
component snum2bits = Num2Bits(253); component snum2bits = Num2Bits(251);
snum2bits.in <== S; snum2bits.in <== S;
component compConstant = CompConstant(2736030358979909402780800718157159386076813972158567259200215660948447373040); component aliasCheck = AliasCheckBabyJub();
aliasCheck.enabled <== enabled;
for (i=0; i<253; i++) { for (i=0; i<251; i++) {
snum2bits.out[i] ==> compConstant.in[i]; snum2bits.out[i] ==> aliasCheck.in[i];
} }
compConstant.in[253] <== 0;
compConstant.out*enabled === 0;
// Calculate the h = H(R,A, msg) // Calculate the h = H(R,A, msg)
component hash = Poseidon(5, 6, 8, 57); component hash = Poseidon(5);
hash.inputs[0] <== R8x; hash.inputs[0] <== R8x;
hash.inputs[1] <== R8y; hash.inputs[1] <== R8y;
@ -103,8 +102,8 @@ template EdDSAPoseidonVerifier() {
5299619240641551281634865583518297030282874472190772894086521144482721001553, 5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203 16950150798460657717958625567821834550301663161624707787222815936182638968203
]; ];
component mulFix = EscalarMulFix(253, BASE8); component mulFix = EscalarMulFix(251, BASE8);
for (i=0; i<253; i++) { for (i=0; i<251; i++) {
mulFix.e[i] <== snum2bits.out[i]; mulFix.e[i] <== snum2bits.out[i];
} }

View File

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

View File

@ -44,6 +44,7 @@ include "babyjub.circom";
A good way to see it is that the accumulator input of the adder >= 2^247*B and the other input A good way to see it is that the accumulator input of the adder >= 2^247*B and the other input
is the output of the windows that it's going to be <= 2^246*B is the output of the windows that it's going to be <= 2^246*B
*/ */
/* base must not be the neutral element nor points of small order */
template WindowMulFix() { template WindowMulFix() {
signal input in[3]; signal input in[3];
signal input base[2]; signal input base[2];
@ -133,11 +134,12 @@ template WindowMulFix() {
/* /*
This component does a multiplication of a escalar times a fix base This component does a multiplication of a escalar times a fix base
nWindows must not exceed 82
Signals: Signals:
e: The scalar in bits e: The scalar in bits
base: the base point in edwards format base: the base point in edwards format
out: The result out: The result
dbl: Point in Edwards to be linked to the next segment. dbl: Point in Montgomery to be linked to the next segment.
*/ */
template SegmentMulFix(nWindows) { template SegmentMulFix(nWindows) {
@ -236,7 +238,7 @@ template EscalarMulFix(n, BASE) {
signal output out[2]; // Point (Twisted format) signal output out[2]; // Point (Twisted format)
var nsegments = (n-1)\246 +1; // 249 probably would work. But I'm not sure and for security I keep 246 var nsegments = (n-1)\246 +1; // 249 probably would work. But I'm not sure and for security I keep 246
var nlastsegment = n - (nsegments-1)*249; var nlastsegment = n - (nsegments-1)*246;
component segments[nsegments]; component segments[nsegments];
@ -250,13 +252,13 @@ template EscalarMulFix(n, BASE) {
for (s=0; s<nsegments; s++) { for (s=0; s<nsegments; s++) {
nseg = (s < nsegments-1) ? 249 : nlastsegment; nseg = (s < nsegments-1) ? 246 : nlastsegment;
nWindows = ((nseg - 1)\3)+1; nWindows = ((nseg - 1)\3)+1;
segments[s] = SegmentMulFix(nWindows); segments[s] = SegmentMulFix(nWindows);
for (i=0; i<nseg; i++) { for (i=0; i<nseg; i++) {
segments[s].e[i] <== e[s*249+i]; segments[s].e[i] <== e[s*246+i];
} }
for (i = nseg; i<nWindows*3; i++) { for (i = nseg; i<nWindows*3; i++) {

View File

@ -27,8 +27,8 @@ function pointAdd(x1,y1,x2,y2) {
return res; return res;
} }
template EscalarMulW4Table(base, k) { function EscalarMulW4Table(base, k) {
signal output out[16][2]; var out[16][2];
var i; var i;
var p[2]; var p[2];
@ -39,11 +39,13 @@ template EscalarMulW4Table(base, k) {
dbl = pointAdd(dbl[0], dbl[1], dbl[0], dbl[1]); dbl = pointAdd(dbl[0], dbl[1], dbl[0], dbl[1]);
} }
out[0][0] <== 0; out[0][0] = 0;
out[0][1] <== 1; out[0][1] = 1;
for (i=1; i<16; i++) { for (i=1; i<16; i++) {
p = pointAdd(out[i-1][0], out[i-1][1], dbl[0], dbl[1]); p = pointAdd(out[i-1][0], out[i-1][1], dbl[0], dbl[1]);
out[i][0] <== p[0]; out[i][0] = p[0];
out[i][1] <== p[1]; out[i][1] = p[1];
} }
return out;
} }

View File

@ -1,11 +1,13 @@
// implements MiMC-2n/n as hash using a sponge construction. // implements MiMC-2n/n as hash using a sponge construction.
// log_5(21888242871839275222246405745257275088548364400416034343698204186575808495617) ~= 110 // log_5(21888242871839275222246405745257275088548364400416034343698204186575808495617) ~= 110
// => nRounds should be 220 // => nRounds should be 220
template MiMCSponge(nInputs, nRounds, nOutputs) { template MiMCSponge(nInputs, nOutputs) {
signal input ins[nInputs]; signal input ins[nInputs];
signal input k; signal input k;
signal output outs[nOutputs]; signal output outs[nOutputs];
var nRounds = 220;
// S = R||C // S = R||C
component S[nInputs + nOutputs - 1]; component S[nInputs + nOutputs - 1];
@ -21,7 +23,7 @@ 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 (var i = 0; i < nOutputs - 1; i++) {
S[nInputs + i] = MiMCFeistel(nRounds); S[nInputs + i] = MiMCFeistel(nRounds);
@ -39,8 +41,8 @@ template MiMCFeistel(nrounds) {
signal output xL_out; signal output xL_out;
signal output xR_out; signal output xR_out;
var c = [ // doesn't contain the first and last round constants, which are always zero
0, var c_partial = [
7120861356467848435263064379192047478074060781135320967663101236819528304084, 7120861356467848435263064379192047478074060781135320967663101236819528304084,
5024705281721889198577876690145313457398658950011302225525409148828000436681, 5024705281721889198577876690145313457398658950011302225525409148828000436681,
17980351014018068290387269214713820287804403312720763401943303895585469787384, 17980351014018068290387269214713820287804403312720763401943303895585469787384,
@ -258,8 +260,7 @@ template MiMCFeistel(nrounds) {
18224457394066545825553407391290108485121649197258948320896164404518684305122, 18224457394066545825553407391290108485121649197258948320896164404518684305122,
274945154732293792784580363548970818611304339008964723447672490026510689427, 274945154732293792784580363548970818611304339008964723447672490026510689427,
11050822248291117548220126630860474473945266276626263036056336623671308219529, 11050822248291117548220126630860474473945266276626263036056336623671308219529,
2119542016932434047340813757208803962484943912710204325088879681995922344971, 2119542016932434047340813757208803962484943912710204325088879681995922344971
0
]; ];
var t; var t;
@ -268,13 +269,19 @@ template MiMCFeistel(nrounds) {
signal xL[nrounds-1]; signal xL[nrounds-1];
signal xR[nrounds-1]; signal xR[nrounds-1];
var c;
for (var i=0; i<nrounds; i++) { 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; t2[i] <== t*t;
t4[i] <== t2[i]*t2[i]; t4[i] <== t2[i]*t2[i];
if (i<nrounds-1) { if (i<nrounds-1) {
xL[i] <== ((i==0) ? xR_in : xR[i-1]) + t4[i]*t; 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 { } else {
xR_out <== xR[i-1] + t4[i]*t; xR_out <== xR[i-1] + t4[i]*t;
xL_out <== xL[i-1]; xL_out <== xL[i-1];

View File

@ -85,6 +85,7 @@ template Montgomery2Edwards() {
*/ */
/* in1 must be != in2 */
template MontgomeryAdd() { template MontgomeryAdd() {
signal input in1[2]; signal input in1[2];
signal input in2[2]; signal input in2[2];

View File

@ -108,6 +108,7 @@ template Window4() {
} }
/* nWindows must not exceed 50 */
template Segment(nWindows) { template Segment(nWindows) {
signal input in[nWindows*4]; signal input in[nWindows*4];
signal input base[2]; signal input base[2];

View File

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

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

5064
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "circomlib", "name": "@tornado/circomlib",
"version": "0.0.17", "version": "0.0.21",
"description": "Basic circuits library for Circom", "description": "Basic circuits library for Circom",
"main": "index.js", "main": "index.js",
"directories": { "directories": {
@ -19,19 +19,19 @@
], ],
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/iden3/circomlib.git" "url": "https://git.tornado.ws/tornado-packages/circomlib.git"
}, },
"author": "0Kims", "author": "0Kims",
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"blake-hash": "^1.1.0", "blake-hash": "^1.1.0",
"blake2b": "^2.1.3", "blake2b": "^2.1.3",
"snarkjs": "^0.1.20", "@tornado/snarkjs": "0.1.20",
"typedarray-to-buffer": "^3.1.5", "typedarray-to-buffer": "^3.1.5",
"web3": "^1.0.0-beta.55" "web3": "^1.2.11"
}, },
"devDependencies": { "devDependencies": {
"circom": "0.0.32", "circom": "0.0.35",
"eslint-plugin-mocha": "^5.2.0", "eslint-plugin-mocha": "^5.2.0",
"ganache-cli": "^6.4.4", "ganache-cli": "^6.4.4",
"mocha": "^5.2.0" "mocha": "^5.2.0"

View File

@ -1,5 +1,5 @@
const bn128 = require("snarkjs").bn128; const bn128 = require("@tornado/snarkjs").bn128;
const bigInt = require("snarkjs").bigInt; const bigInt = require("@tornado/snarkjs").bigInt;
exports.addPoint = addPoint; exports.addPoint = addPoint;
exports.mulPointEscalar = mulPointEscalar; exports.mulPointEscalar = mulPointEscalar;
@ -9,11 +9,11 @@ exports.packPoint = packPoint;
exports.unpackPoint = unpackPoint; exports.unpackPoint = unpackPoint;
exports.Generator = [ exports.Generator = [
bigInt("995203441582195749578291179787384436505546430278305826713579947235728471134"), bigInt("995203441582195749578291179787384436505546430278305826713579947235728471134"),
bigInt("5472060717959818805561601436314318772137091100104008585924551046643952123905") bigInt("5472060717959818805561601436314318772137091100104008585924551046643952123905"),
]; ];
exports.Base8 = [ exports.Base8 = [
bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"), bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203") bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203"),
]; ];
exports.order = bigInt("21888242871839275222246405745257275088614511777268538073601725287587578984328"); exports.order = bigInt("21888242871839275222246405745257275088614511777268538073601725287587578984328");
exports.subOrder = exports.order.shr(3); exports.subOrder = exports.order.shr(3);
@ -21,7 +21,6 @@ exports.p = bn128.r;
exports.A = bigInt("168700"); exports.A = bigInt("168700");
exports.D = bigInt("168696"); exports.D = bigInt("168696");
function addPoint(a, b) { function addPoint(a, b) {
const q = bn128.r; const q = bn128.r;
@ -31,8 +30,18 @@ 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[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[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[0] = bigInt(
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); bigInt(a[0])
.mul(b[1])
.add(bigInt(b[0]).mul(a[1]))
.mul(bigInt(bigInt("1").add(exports.D.mul(a[0]).mul(b[0]).mul(a[1]).mul(b[1]))).inverse(q))
).affine(q);
res[1] = bigInt(
bigInt(a[1])
.mul(b[1])
.sub(exports.A.mul(a[0]).mul(b[0]))
.mul(bigInt(bigInt("1").sub(exports.D.mul(a[0]).mul(b[0]).mul(a[1]).mul(b[1]))).inverse(q))
).affine(q);
return res; return res;
} }
@ -56,7 +65,7 @@ function mulPointEscalar(base, e) {
function inSubgroup(P) { function inSubgroup(P) {
if (!inCurve(P)) return false; if (!inCurve(P)) return false;
const res = mulPointEscalar(P, exports.subOrder); const res = mulPointEscalar(P, exports.subOrder);
return (res[0].equals(bigInt(0))) && (res[1].equals(bigInt(1))); return res[0].equals(bigInt(0)) && res[1].equals(bigInt(1));
} }
function inCurve(P) { function inCurve(P) {
@ -65,9 +74,7 @@ function inCurve(P) {
const x2 = F.square(P[0]); const x2 = F.square(P[0]);
const y2 = F.square(P[1]); const y2 = F.square(P[1]);
if (!F.equals( if (!F.equals(F.add(F.mul(exports.A, x2), y2), F.add(F.one, F.mul(F.mul(x2, y2), exports.D)))) return false;
F.add(F.mul(exports.A, x2), y2),
F.add(F.one, F.mul(F.mul(x2, y2), exports.D)))) return false;
return true; return true;
} }
@ -88,16 +95,14 @@ function unpackPoint(_buff) {
const P = new Array(2); const P = new Array(2);
if (buff[31] & 0x80) { if (buff[31] & 0x80) {
sign = true; sign = true;
buff[31] = buff[31] & 0x7F; buff[31] = buff[31] & 0x7f;
} }
P[1] = bigInt.leBuff2int(buff); P[1] = bigInt.leBuff2int(buff);
if (P[1].greaterOrEquals(exports.p)) return null; if (P[1].greaterOrEquals(exports.p)) return null;
const y2 = F.square(P[1]); const y2 = F.square(P[1]);
let x = F.sqrt(F.div( let x = F.sqrt(F.div(F.sub(F.one, y2), F.sub(exports.A, F.mul(exports.D, y2))));
F.sub(F.one, y2),
F.sub(exports.A, F.mul(exports.D, y2))));
if (x == null) return null; if (x == null) return null;

View File

@ -1,5 +1,5 @@
const createBlakeHash = require("blake-hash"); const createBlakeHash = require("blake-hash");
const bigInt = require("snarkjs").bigInt; const bigInt = require("@tornado/snarkjs").bigInt;
const babyJub = require("./babyjub"); const babyJub = require("./babyjub");
const pedersenHash = require("./pedersenHash").hash; const pedersenHash = require("./pedersenHash").hash;
const mimc7 = require("./mimc7"); const mimc7 = require("./mimc7");
@ -19,11 +19,10 @@ exports.packSignature = packSignature;
exports.unpackSignature = unpackSignature; exports.unpackSignature = unpackSignature;
exports.pruneBuffer = pruneBuffer; exports.pruneBuffer = pruneBuffer;
function pruneBuffer(_buff) { function pruneBuffer(_buff) {
const buff = Buffer.from(_buff); const buff = Buffer.from(_buff);
buff[0] = buff[0] & 0xF8; buff[0] = buff[0] & 0xf8;
buff[31] = buff[31] & 0x7F; buff[31] = buff[31] & 0x7f;
buff[31] = buff[31] | 0x40; buff[31] = buff[31] | 0x40;
return buff; return buff;
} }
@ -41,7 +40,9 @@ function sign(prv, msg) {
const s = bigInt.leBuff2int(sBuff); const s = bigInt.leBuff2int(sBuff);
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3)); const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msg])).digest(); const rBuff = createBlakeHash("blake512")
.update(Buffer.concat([h1.slice(32, 64), msg]))
.digest();
let r = bigInt.leBuff2int(rBuff); let r = bigInt.leBuff2int(rBuff);
r = r.mod(babyJub.subOrder); r = r.mod(babyJub.subOrder);
const R8 = babyJub.mulPointEscalar(babyJub.Base8, r); const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
@ -52,7 +53,7 @@ function sign(prv, msg) {
const S = r.add(hm.mul(s)).mod(babyJub.subOrder); const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
return { return {
R8: R8, R8: R8,
S: S S: S,
}; };
} }
@ -63,7 +64,9 @@ function signMiMC(prv, msg) {
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3)); const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
const msgBuff = bigInt.leInt2Buff(msg, 32); const msgBuff = bigInt.leInt2Buff(msg, 32);
const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest(); const rBuff = createBlakeHash("blake512")
.update(Buffer.concat([h1.slice(32, 64), msgBuff]))
.digest();
let r = bigInt.leBuff2int(rBuff); let r = bigInt.leBuff2int(rBuff);
r = r.mod(babyJub.subOrder); r = r.mod(babyJub.subOrder);
const R8 = babyJub.mulPointEscalar(babyJub.Base8, r); const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
@ -71,7 +74,7 @@ function signMiMC(prv, msg) {
const S = r.add(hm.mul(s)).mod(babyJub.subOrder); const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
return { return {
R8: R8, R8: R8,
S: S S: S,
}; };
} }
@ -82,7 +85,9 @@ function signMiMCSponge(prv, msg) {
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3)); const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
const msgBuff = bigInt.leInt2Buff(msg, 32); const msgBuff = bigInt.leInt2Buff(msg, 32);
const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest(); const rBuff = createBlakeHash("blake512")
.update(Buffer.concat([h1.slice(32, 64), msgBuff]))
.digest();
let r = bigInt.leBuff2int(rBuff); let r = bigInt.leBuff2int(rBuff);
r = r.mod(babyJub.subOrder); r = r.mod(babyJub.subOrder);
const R8 = babyJub.mulPointEscalar(babyJub.Base8, r); const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
@ -90,7 +95,7 @@ function signMiMCSponge(prv, msg) {
const S = r.add(hm.mul(s)).mod(babyJub.subOrder); const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
return { return {
R8: R8, R8: R8,
S: S S: S,
}; };
} }
@ -101,16 +106,17 @@ function signPoseidon(prv, msg) {
const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3)); const A = babyJub.mulPointEscalar(babyJub.Base8, s.shr(3));
const msgBuff = bigInt.leInt2Buff(msg, 32); const msgBuff = bigInt.leInt2Buff(msg, 32);
const rBuff = createBlakeHash("blake512").update(Buffer.concat([h1.slice(32,64), msgBuff])).digest(); const rBuff = createBlakeHash("blake512")
.update(Buffer.concat([h1.slice(32, 64), msgBuff]))
.digest();
let r = bigInt.leBuff2int(rBuff); let r = bigInt.leBuff2int(rBuff);
r = r.mod(babyJub.subOrder); r = r.mod(babyJub.subOrder);
const R8 = babyJub.mulPointEscalar(babyJub.Base8, r); const R8 = babyJub.mulPointEscalar(babyJub.Base8, r);
const hash = poseidon.createHash(6, 8, 57); const hm = poseidon([R8[0], R8[1], A[0], A[1], msg]);
const hm = hash([R8[0], R8[1], A[0], A[1], msg]);
const S = r.add(hm.mul(s)).mod(babyJub.subOrder); const S = r.add(hm.mul(s)).mod(babyJub.subOrder);
return { return {
R8: R8, R8: R8,
S: S S: S,
}; };
} }
@ -161,7 +167,6 @@ function verifyMiMC(msg, sig, A) {
return true; return true;
} }
function verifyPoseidon(msg, sig, A) { function verifyPoseidon(msg, sig, A) {
// Check parameters // Check parameters
if (typeof sig != "object") return false; if (typeof sig != "object") return false;
@ -173,8 +178,7 @@ function verifyPoseidon(msg, sig, A) {
if (!babyJub.inCurve(A)) return false; if (!babyJub.inCurve(A)) return false;
if (sig.S >= babyJub.subOrder) return false; if (sig.S >= babyJub.subOrder) return false;
const hash = poseidon.createHash(6, 8, 57); const hm = poseidon([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
const hm = hash([sig.R8[0], sig.R8[1], A[0], A[1], msg]);
const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S); const Pleft = babyJub.mulPointEscalar(babyJub.Base8, sig.S);
let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8"))); let Pright = babyJub.mulPointEscalar(A, hm.mul(bigInt("8")));
@ -216,8 +220,6 @@ function packSignature(sig) {
function unpackSignature(sigBuff) { function unpackSignature(sigBuff) {
return { return {
R8: babyJub.unpackPoint(sigBuff.slice(0, 32)), R8: babyJub.unpackPoint(sigBuff.slice(0, 32)),
S: bigInt.leBuff2int(sigBuff.slice(32,64)) S: bigInt.leBuff2int(sigBuff.slice(32, 64)),
}; };
} }

View File

@ -154,6 +154,17 @@ class Contract {
} }
push(data) { 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)); const d = Web3Utils.hexToBytes(Web3Utils.toHex(data));
if (d.length == 0 || d.length > 32) { if (d.length == 0 || d.length > 32) {
throw new Error("Assertion failed"); throw new Error("Assertion failed");

View File

@ -3,9 +3,8 @@
// //
const Contract = require("./evmasm"); const Contract = require("./evmasm");
const G2 = require("snarkjs").bn128.G2; const G2 = require("@tornado/snarkjs").bn128.G2;
const bigInt = require("snarkjs").bigInt; const bigInt = require("@tornado/snarkjs").bigInt;
function toHex256(a) { function toHex256(a) {
let S = a.toString(16); let S = a.toString(16);
@ -14,13 +13,12 @@ function toHex256(a) {
} }
function createCode(P, w) { function createCode(P, w) {
const C = new Contract(); const C = new Contract();
const NPOINTS = 1 << (w - 1); const NPOINTS = 1 << (w - 1);
const VAR_POS = C.allocMem(32); const VAR_POS = C.allocMem(32);
const VAR_POINTS = C.allocMem( (NPOINTS)*4*32); const VAR_POINTS = C.allocMem(NPOINTS * 4 * 32);
const savedP = C.allocMem(32); const savedP = C.allocMem(32);
const savedZ3 = C.allocMem(32); const savedZ3 = C.allocMem(32);
@ -96,7 +94,6 @@ function createCode(P, w) {
C.push("0x00"); C.push("0x00");
C.return(); C.return();
double(); double();
addPoint(); addPoint();
affine(); affine();
@ -210,7 +207,6 @@ function createCode(P, w) {
C.and(); C.and();
C.jumpi("enddouble"); // X Y Z q C.jumpi("enddouble"); // X Y Z q
// Z3 = 2*Y*Z // Remove Z // Z3 = 2*Y*Z // Remove Z
mul(2, 4, 6); // yz X Y Z q mul(2, 4, 6); // yz X Y Z q
rm(6); // X Y yz q rm(6); // X Y yz q
@ -279,8 +275,8 @@ function createCode(P, w) {
C.returnCall(); C.returnCall();
} }
function addPoint() { // p, xR, xI, yR, yI, zR zI, q function addPoint() {
// p, xR, xI, yR, yI, zR zI, q
C.dup(0); // p p X2 Y2 Z2 q C.dup(0); // p p X2 Y2 Z2 q
@ -290,7 +286,6 @@ function createCode(P, w) {
C.iszero(); // X2 Y2 Z2 q C.iszero(); // X2 Y2 Z2 q
C.jumpi("endpadd"); C.jumpi("endpadd");
C.dup(4); C.dup(4);
C.iszero(); C.iszero();
C.dup(6); C.dup(6);
@ -298,15 +293,12 @@ function createCode(P, w) {
C.and(); C.and();
C.jumpi("returnP"); // X2 Y2 Z2 q C.jumpi("returnP"); // X2 Y2 Z2 q
// lastZ3 = (Z2+1)^2 - Z2^2 // lastZ3 = (Z2+1)^2 - Z2^2
add1(4, 6); // Z2+1 X2 Y2 Z2 q add1(4, 6); // Z2+1 X2 Y2 Z2 q
square(0, 8); // (Z2+1)^2 Z2+1 X2 Y2 Z2 q square(0, 8); // (Z2+1)^2 Z2+1 X2 Y2 Z2 q
rm(2); // (Z2+1)^2 X2 Y2 Z2 q rm(2); // (Z2+1)^2 X2 Y2 Z2 q
square(6, 8); // Z2^2 (Z2+1)^2 X2 Y2 Z2 q square(6, 8); // Z2^2 (Z2+1)^2 X2 Y2 Z2 q
sub(2, 0, 10); // (Z2+1)^2-Z2^2 Z2^2 (Z2+1)^2 X2 Y2 Z2 q sub(2, 0, 10); // (Z2+1)^2-Z2^2 Z2^2 (Z2+1)^2 X2 Y2 Z2 q
saveZ3(); // Z2^2 (Z2+1)^2 X2 Y2 Z2 q saveZ3(); // Z2^2 (Z2+1)^2 X2 Y2 Z2 q
@ -315,13 +307,11 @@ function createCode(P, w) {
// U2 = X2 // U2 = X2
// S2 = Y2 // Z2^2 U2 S2 Z2 q // S2 = Y2 // Z2^2 U2 S2 Z2 q
// U1 = X1 * Z2^2 // U1 = X1 * Z2^2
loadX(); // X1 Z2^2 U2 S2 Z2 q loadX(); // X1 Z2^2 U2 S2 Z2 q
mul(0, 2, 10); // X1*Z2^2 X1 Z2^2 U2 S2 Z2 q mul(0, 2, 10); // X1*Z2^2 X1 Z2^2 U2 S2 Z2 q
rm(2); // X1*Z2^2 Z2^2 U2 S2 Z2 q rm(2); // X1*Z2^2 Z2^2 U2 S2 Z2 q
mul(2, 8, 10); // Z2^3 U1 Z2^2 U2 S2 Z2 q mul(2, 8, 10); // Z2^3 U1 Z2^2 U2 S2 Z2 q
rm(4); // U1 Z2^3 U2 S2 Z2 q rm(4); // U1 Z2^3 U2 S2 Z2 q
rm(8); // Z2^3 U2 S2 U1 q rm(8); // Z2^3 U2 S2 U1 q
@ -337,7 +327,6 @@ function createCode(P, w) {
C.and(); // c2&c1 S1 U2 S2 U1 q C.and(); // c2&c1 S1 U2 S2 U1 q
C.jumpi("double1"); // S1 U2 S2 U1 q C.jumpi("double1"); // S1 U2 S2 U1 q
// Returns the double // Returns the double
// H = U2-U1 // Remove U2 // H = U2-U1 // Remove U2
@ -473,7 +462,8 @@ function createCode(P, w) {
} }
} }
function affine() { // X Y Z q function affine() {
// X Y Z q
// If Z2=0 return 0 // If Z2=0 return 0
C.label("affine"); C.label("affine");
C.dup(4); C.dup(4);
@ -551,33 +541,32 @@ function createCode(P, w) {
} }
} }
} }
} }
module.exports.abi = [ module.exports.abi = [
{ {
"constant": true, constant: true,
"inputs": [ inputs: [
{ {
"name": "escalar", name: "escalar",
"type": "uint256" type: "uint256",
} },
], ],
"name": "mulexp", name: "mulexp",
"outputs": [ outputs: [
{ {
"name": "", name: "",
"type": "uint256" type: "uint256",
}, },
{ {
"name": "", name: "",
"type": "uint256" type: "uint256",
} },
], ],
"payable": false, payable: false,
"stateMutability": "pure", stateMutability: "pure",
"type": "function" type: "function",
} },
]; ];
module.exports.createCode = createCode; module.exports.createCode = createCode;

View File

@ -1,5 +1,5 @@
const bn128 = require("snarkjs").bn128; const bn128 = require("@tornado/snarkjs").bn128;
const bigInt = require("snarkjs").bigInt; const bigInt = require("@tornado/snarkjs").bigInt;
const Web3Utils = require("web3-utils"); const Web3Utils = require("web3-utils");
const F = bn128.Fr; const F = bn128.Fr;
@ -38,7 +38,7 @@ exports.hash = (_x_in, _k) =>{
let r; let r;
for (let i = 0; i < NROUNDS; i++) { for (let i = 0; i < NROUNDS; i++) {
const c = cts[i]; const c = cts[i];
const t = (i==0) ? F.add(x_in, k) : F.add(F.add(r, k), c); const t = i == 0 ? F.add(x_in, k) : F.add(F.add(r, k), c);
r = F.exp(t, 7); r = F.exp(t, 7);
} }
return F.affine(F.add(r, k)); return F.affine(F.add(r, k));
@ -46,19 +46,13 @@ exports.hash = (_x_in, _k) =>{
exports.multiHash = (arr, key) => { exports.multiHash = (arr, key) => {
let r; let r;
if (typeof(key) === "undefined") { if (typeof key === "undefined") {
r = F.zero; r = F.zero;
} else { } else {
r = key; r = key;
} }
for (let i = 0; i < arr.length; i++) { for (let i = 0; i < arr.length; i++) {
r = F.add( r = F.add(F.add(r, arr[i]), exports.hash(bigInt(arr[i]), r));
F.add(
r,
arr[i]
),
exports.hash(bigInt(arr[i]), r)
);
} }
return F.affine(r); return F.affine(r);
}; };

View File

@ -1,5 +1,5 @@
const bn128 = require("snarkjs").bn128; const bn128 = require("@tornado/snarkjs").bn128;
const bigInt = require("snarkjs").bigInt; const bigInt = require("@tornado/snarkjs").bigInt;
const Web3Utils = require("web3-utils"); const Web3Utils = require("web3-utils");
const F = bn128.Fr; const F = bn128.Fr;
@ -39,9 +39,9 @@ exports.hash = (_xL_in, _xR_in, _k) =>{
const k = bigInt(_k); const k = bigInt(_k);
for (let i = 0; i < NROUNDS; i++) { for (let i = 0; i < NROUNDS; i++) {
const c = cts[i]; const c = cts[i];
const t = (i==0) ? F.add(xL, k) : F.add(F.add(xL, k), c); const t = i == 0 ? F.add(xL, k) : F.add(F.add(xL, k), c);
const xR_tmp = bigInt(xR); const xR_tmp = bigInt(xR);
if (i < (NROUNDS - 1)) { if (i < NROUNDS - 1) {
xR = xL; xR = xL;
xL = F.add(xR_tmp, F.exp(t, 5)); xL = F.add(xR_tmp, F.exp(t, 5));
} else { } else {
@ -55,10 +55,10 @@ exports.hash = (_xL_in, _xR_in, _k) =>{
}; };
exports.multiHash = (arr, key, numOutputs) => { exports.multiHash = (arr, key, numOutputs) => {
if (typeof(numOutputs) === "undefined") { if (typeof numOutputs === "undefined") {
numOutputs = 1; numOutputs = 1;
} }
if (typeof(key) === "undefined") { if (typeof key === "undefined") {
key = F.zero; key = F.zero;
} }
@ -81,6 +81,6 @@ exports.multiHash = (arr, key, numOutputs) => {
if (numOutputs == 1) { if (numOutputs == 1) {
return F.affine(outputs[0]); return F.affine(outputs[0]);
} else { } else {
return outputs.map(x => F.affine(x)); return outputs.map((x) => F.affine(x));
} }
}; };

View File

@ -20,34 +20,29 @@ function createCode(seed, n) {
C.push("0x00"); C.push("0x00");
C.mload(); C.mload();
C.div(); C.div();
C.push("0x3f1a1187"); // MiMCSponge(uint256,uint256,uint256) C.push("0xf47d33b5"); // MiMCSponge(uint256,uint256)
C.eq(); C.eq();
C.jmpi("start"); C.jmpi("start");
C.invalid(); C.invalid();
C.label("start"); C.label("start");
C.push("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"); // q C.push("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"); // q
C.push("0x44");
C.mload(); // k q
C.push("0x04"); C.push("0x04");
C.mload(); // xL k q C.mload(); // xL q
C.dup(2); // q xL k q C.dup(1); // q xL q
C.push("0x24"); C.push("0x24");
C.mload(); // xR q xL k q C.mload(); // xR q xL q
C.dup(1); // q xR q xL k q C.dup(1); // q xR q xL q
C.dup(0); // q q xR q xL k q C.dup(3); // xL q xR q xL q
C.dup(4); // xL q q xR q xL k q C.dup(1); // q xL q xR q xL q
C.dup(6); // k xL q q xR q xL k q C.dup(0); // q q xL q xR q xL q
C.addmod(); // t=k+xL q xR q xL k q C.dup(2); // xL q q xL q xR q xL q
C.dup(1); // q t q xR q xL k q C.dup(0); // xL xL q q xL q xR q xL q
C.dup(0); // q q t q xR q xL k q C.mulmod(); // b=xL^2 q xL q xR q xL q
C.dup(2); // t q q t q xR q xL k q C.dup(0); // b b q xL q xR q xL q
C.dup(0); // t t q q t q xR q xL k q C.mulmod(); // c=xL^4 xL q xR q xL q
C.mulmod(); // b=t^2 q t q xR q xL k q C.mulmod(); // d=xL^5 xR q xL q
C.dup(0); // b b q t q xR q xL k q C.addmod(); // e=xL^5+xR xL q (for next round: xL xR q)
C.mulmod(); // c=t^4 t q xR q xL k q
C.mulmod(); // d=t^5 xR q xL k q
C.addmod(); // e=t^5+xR xL k q (for next round: xL xR k q)
for (let i=0; i<n-1; i++) { for (let i=0; i<n-1; i++) {
if (i < n-2) { if (i < n-2) {
@ -55,27 +50,24 @@ function createCode(seed, n) {
} else { } else {
ci = "0x00"; ci = "0x00";
} }
C.swap(1); // xR xL k q C.swap(1); // xR xL q
C.dup(3); // q xR xL k q C.dup(2); // q xR xL q
C.dup(3); // k q xR xL k q C.dup(2); // xL q xR xL q
C.dup(1); // q k q xR xL k q C.push(ci); // ci xL q xR xL q
C.dup(4); // xL q k q xR xL k q C.addmod(); // a=ci+xL xR xL q
C.push(ci); // ci xL q k q xR xL k q C.dup(3); // q a xR xL q
C.addmod(); // a=ci+xL k q xR xL k q C.swap(1); // a q xR xL q
C.addmod(); // t=a+k xR xL k q C.dup(1); // q a q xR xL q
C.dup(4); // q t xR xL k q C.dup(0); // q q a q xR xL q
C.swap(1); // t q xR xL k q C.dup(2); // a q q a q xR xL q
C.dup(1); // q t q xR xL k q C.dup(0); // a a q q a q xR xL q
C.dup(0); // q q t q xR xL k q C.mulmod(); // b=a^2 q a q xR xL q
C.dup(2); // t q q t q xR xL k q C.dup(0); // b b q a q xR xL q
C.dup(0); // t t q q t q xR xL k q C.mulmod(); // c=a^4 a q xR xL q
C.mulmod(); // b=t^2 q t q xR xL k q C.mulmod(); // d=a^5 xR xL q
C.dup(0); // b b q t q xR xL k q C.dup(3); // q d xR xL q
C.mulmod(); // c=t^4 t q xR xL k q C.swap(2); // xR d q xL q
C.mulmod(); // d=t^5 xR xL k q C.addmod(); // e=a^5+xR xL q (for next round: xL xR q)
C.dup(4); // q d xR xL k q
C.swap(2); // xR d q xL k q
C.addmod(); // e=t^5+xR xL k q (for next round: xL xR k q)
} }
C.push("0x20"); C.push("0x20");
@ -100,10 +92,6 @@ module.exports.abi = [
{ {
"name": "xR_in", "name": "xR_in",
"type": "uint256" "type": "uint256"
},
{
"name": "k",
"type": "uint256"
} }
], ],
"name": "MiMCSponge", "name": "MiMCSponge",

View File

@ -1,5 +1,5 @@
const bn128 = require("snarkjs").bn128; const bn128 = require("@tornado/snarkjs").bn128;
const bigInt = require("snarkjs").bigInt; const bigInt = require("@tornado/snarkjs").bigInt;
const babyJub = require("./babyjub"); const babyJub = require("./babyjub");
const createBlakeHash = require("blake-hash"); const createBlakeHash = require("blake-hash");
@ -21,7 +21,7 @@ function pedersenHash(msg) {
for (let s = 0; s < nSegments; s++) { for (let s = 0; s < nSegments; s++) {
let nWindows; let nWindows;
if (s == nSegments - 1) { if (s == nSegments - 1) {
nWindows = Math.floor(((bits.length - (nSegments - 1)*bitsPerSegment) - 1) / windowSize) +1; nWindows = Math.floor((bits.length - (nSegments - 1) * bitsPerSegment - 1) / windowSize) + 1;
} else { } else {
nWindows = nWindowsPerSegment; nWindows = nWindowsPerSegment;
} }
@ -30,7 +30,7 @@ function pedersenHash(msg) {
for (let w = 0; w < nWindows; w++) { for (let w = 0; w < nWindows; w++) {
let o = s * bitsPerSegment + w * windowSize; let o = s * bitsPerSegment + w * windowSize;
let acc = bigInt.one; let acc = bigInt.one;
for (let b=0; ((b<windowSize-1)&&(o<bits.length)) ; b++) { for (let b = 0; b < windowSize - 1 && o < bits.length; b++) {
if (bits[o]) { if (bits[o]) {
acc = acc.add(bigInt.one.shl(b)); acc = acc.add(bigInt.one.shl(b));
} }
@ -65,7 +65,7 @@ function getBasePoint(pointIdx) {
while (p == null) { while (p == null) {
const S = GENPOINT_PREFIX + "_" + padLeftZeros(pointIdx, 32) + "_" + padLeftZeros(tryIdx, 32); const S = GENPOINT_PREFIX + "_" + padLeftZeros(pointIdx, 32) + "_" + padLeftZeros(tryIdx, 32);
const h = createBlakeHash("blake256").update(S).digest(); const h = createBlakeHash("blake256").update(S).digest();
h[31] = h[31] & 0xBF; // Set 255th bit to 0 (256th is the signal and 254th is the last possible bit to 1) 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); p = babyJub.unpackPoint(h);
tryIdx++; tryIdx++;
} }
@ -105,7 +105,3 @@ function buffer2bits(buff) {
} }
return res; return res;
} }

View File

@ -1,116 +1,48 @@
const bn128 = require("snarkjs").bn128;
const bigInt = require("snarkjs").bigInt;
const blake2b = require('blake2b');
const assert = require("assert"); const assert = require("assert");
const bn128 = require("@tornado/snarkjs").bn128;
const bigInt = require("@tornado/snarkjs").bigInt;
const F = bn128.Fr; const F = bn128.Fr;
const { unstringifyBigInts } = require("@tornado/snarkjs");
const SEED = "poseidon"; // Prime 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
const NROUNDSF = 8; // const F = new ZqField(Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"));
const NROUNDSP = 57;
const T = 6;
function getPseudoRandom(seed, n) { // Parameters are generated by a reference script https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/generate_parameters_grain.sage
const res = []; // Used like so: sage generate_parameters_grain.sage 1 0 254 2 8 56 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
let input = Buffer.from(seed); const { C, M } = unstringifyBigInts(require("./poseidon_constants.json"));
let h = blake2b(32).update(input).digest()
while (res.length<n) {
const n = F.affine(bigInt.leBuff2int(h));
res.push(n);
h = blake2b(32).update(h).digest()
}
return res; // 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 = 35;
function allDifferent(v) { const pow5 = (a) => F.mul(a, F.square(F.square(a, a)));
for (let i=0; i<v.length; i++) {
if (v[i].isZero()) return false;
for (let j=i+1; j<v.length; j++) {
if (v[i].equals(v[j])) return false;
}
}
return true;
}
exports.getMatrix = (t, seed, nRounds) => { function poseidon(inputs) {
if (typeof seed === "undefined") seed = SEED;
if (typeof nRounds === "undefined") nRounds = NROUNDSF + NROUNDSP;
if (typeof t === "undefined") t = T;
let nonce = "0000";
let cmatrix = getPseudoRandom(seed+"_matrix_"+nonce, t*2);
while (!allDifferent(cmatrix)) {
nonce = (Number(nonce)+1)+"";
while(nonce.length<4) nonce = "0"+nonce;
cmatrix = getPseudoRandom(seed+"_matrix_"+nonce, t*2);
}
const M = new Array(t);
for (let i=0; i<t; i++) {
M[i] = new Array(t);
for (let j=0; j<t; j++) {
M[i][j] = F.affine(F.inverse(F.sub(cmatrix[i], cmatrix[t+j])));
}
}
return M;
};
exports.getConstants = (t, seed, nRounds) => {
if (typeof seed === "undefined") seed = SEED;
if (typeof nRounds === "undefined") nRounds = NROUNDSF + NROUNDSP;
if (typeof t === "undefined") t = T;
const cts = getPseudoRandom(seed+"_constants", nRounds);
return cts;
};
function ark(state, c) {
for (let j=0; j<state.length; j++ ) {
state[j] = F.add(state[j], c);
}
}
function sigma(a) {
return F.mul(a, F.square(F.square(a,a)));
}
function mix(state, M) {
const newState = new Array(state.length);
for (let i=0; i<state.length; i++) {
newState[i] = F.zero;
for (let j=0; j<state.length; j++) {
newState[i] = F.add(newState[i], F.mul(M[i][j], state[j]) );
}
}
for (let i=0; i<state.length; i++) state[i] = newState[i];
}
exports.createHash = (t, nRoundsF, nRoundsP, seed) => {
if (typeof seed === "undefined") seed = SEED;
if (typeof nRoundsF === "undefined") nRoundsF = NROUNDSF;
if (typeof nRoundsP === "undefined") nRoundsP = NROUNDSP;
if (typeof t === "undefined") t = T;
assert(nRoundsF % 2 == 0);
const C = exports.getConstants(t, seed, nRoundsF + nRoundsP);
const M = exports.getMatrix(t, seed, nRoundsF + nRoundsP);
return function(inputs) {
let state = [];
assert(inputs.length <= t);
assert(inputs.length > 0); assert(inputs.length > 0);
for (let i=0; i<inputs.length; i++) state[i] = bigInt(inputs[i]); assert(inputs.length < 5);
for (let i=inputs.length; i<t; i++) state[i] = F.zero;
for (let i=0; i< nRoundsF + nRoundsP; i++) { const t = inputs.length + 1;
ark(state, C[i]); const nRoundsF = N_ROUNDS_F;
if ((i<nRoundsF/2) || (i >= nRoundsF/2 + nRoundsP)) { const nRoundsP = N_ROUNDS_P;
for (let j=0; j<t; j++) state[j] = sigma(state[j]);
let state = [...inputs.map((a) => bigInt(a)), F.zero];
for (let r = 0; r < nRoundsF + nRoundsP; r++) {
state = state.map((a, i) => F.add(a, bigInt(C[t - 2][r * t + i])));
if (r < nRoundsF / 2 || r >= nRoundsF / 2 + nRoundsP) {
state = state.map((a) => pow5(a));
} else { } else {
state[0] = sigma(state[0]); state[0] = pow5(state[0]);
}
// 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(bigInt(M[t - 2][j][i]), a)), F.zero));
} }
mix(state, M);
} }
return F.affine(state[0]); return F.affine(state[0]);
}; }
};
module.exports = poseidon;

706
src/poseidon_constants.json Normal file
View File

@ -0,0 +1,706 @@
{
"C": [
[
"0x1083c3a16f6c55c7956a5ce08fb39df23957cc6381c217985d9ba0ae29771100",
"0x1dd8990173e411a3a4dff6710e8c3df9ef8e07216efd610a63b3ce10ab57b8ae",
"0x1f3ff523faa41dab28fd27c47286a6b93fe44a9e993ea1ab3723d17aba78b3de",
"0x2662d2995574e11e58f4ce13e282b6b57c2d7df1681bfef79a0261dc300573fc",
"0x20b3c06fa2b82434f725af0c37efb847324312d182d127fdb2054cfa0da9a8be",
"0x18ff92e6daa7639fc832d97928e4098d84efa47d7ef5c1929e54232960ae32b1",
"0x2c175450b8686e4958e698cf1af0b54e0e912ea93f35be8e8e1c3daebbc034be",
"0x00596181885c32674b20103a1a153744c302cf1fa86ee39e14e2ff9a5f9efcba",
"0x0e21b4330dd8a9563e60ef4ffdbb26b85ae766e867633e58c20932365d273a53",
"0x16eb0a124adc927e3fdae149e1aef43d5ee08693f7dac9aa20b46bb31ae12d1f",
"0x0ba1d75274999eb448de5751b5bd165582205d564c636e8340d2a3fe09e4e01c",
"0x04d615bf7a10c566ae2b198a40bef494bc43e7bbd40baa908bf2ce989d39cb16",
"0x10f7d989ce23d2ec2dc7cb425b603ef0fb09efb7f620a25b4e0187fafaeb364e",
"0x091562ecab7c0dffec5f874d385c6a7f06e10c0ba2d43a6e4958a47b9d369438",
"0x214c48e2dd8005914ef1c20e4e2e73933abc7dde8bf2f87ffee4bacb52110931",
"0x29418d43249c5f094ff06f9bc1b80e21dffbaac1874539e42b40f8dc49facb42",
"0x017c1908a9f8359c1280d6ac4edfdcec6ae060d0d520bf64b183191397999203",
"0x1a01b85c3b8e81a862a90fd72d5989f75683d9573d4865d79228eb8c5a105e93",
"0x261b40b148e35d05c9a231b70f46bd67e973c7e3cb33648e1904cc257d52a4d5",
"0x036eb758e5135f0137fc7ef59c37454e2b86f0fd90932f0e382ae7c97e3b2e35",
"0x2de1f93fc74bfa9f08fae8bb730f8d266d3726892b97db237f703ed3a8817ac2",
"0x2be0f288c7cb40cf6b063559e689775aa6e0837ff4a3a5d3d62f9f14d688c925",
"0x202410f3233bc5ccf8621873ab2827da7a365ffbd5c55d62bed934a2bf441256",
"0x2f4aa966c6aaa0f96b1a2d8c7c6090ac81a390252e2c2eca95b2d9d4f6f60118",
"0x1c8b2beb3bbc01ec6a6f31261215c3d3aa4193322317b2a8f0816369fbd8db0d",
"0x09166d1877b85ed30781d55bd800917958abc8eb14be7acdf7c74dca69b9f293",
"0x054974baac27bad68c2928ad06d711cb424e77509102145b9e5a1b911dc2342c",
"0x08759d0b984c16c5ba432900cf2bd92c4919cdd7e99a10c29cd343f69b460f74",
"0x2a65153ca0dbc6487497126a6ec8a8d014bcb3d1818914865a504404a4ad03a0",
"0x2b1c5d81263028bcf7996584eede3c315789d1f3e205919585145e023cefd30e",
"0x1927d650073030417589aa9047f9b62ee876cca63cde015e24d0bf4894b2978f",
"0x2d76a732e12f3deafda7b22085efef22772cd3de8f7e001bc99088cb81c9b734",
"0x04063f088d29d7e91e72cdbc50afe1835c4b11ed14f769522c86760cbf526d50",
"0x03e3a3a1c937f3c05882148070e9dac6b5915751fbca27c212bf7582441819eb",
"0x0d416931f39d66d2c94f070c54cae280da1c12605fd2256a129696e98f11ccf6",
"0x2bc7ec8d56eaf3c8e0d7695f84cbf898f0155c3ebaf24583af09b0e7154bec1a",
"0x0367eff17e1bddbee7eed78ec874a9a01e6a9a38406108f487662dc60614010b",
"0x08dd17e110dc0768f10866e8ccf53efb5290468cd8afd07430def10ec9a586fd",
"0x218efb40100662ed34129a8246a90398a806f52f5f76e104299092860a7a8888",
"0x1ac99c81cc6f26be5143ea1daccd4eacaa31e3b223f0a6c4dec96633410f197d",
"0x12cd3c8d2ac7f084684109522fb7be0b7531e2acf8d9e7b686e177ea7a0f05d6",
"0x17e4773a46b9bb17843f36f6db850bace2c86aa3376abf06614f62bded94a7b1",
"0x29d767ca1255c6c1b1bce1d68ecfbd596aa77657dfbe4a604235e60449a9ff14",
"0x242b7392dec412813184d8dca1a25147c092f3d7dfd3c0c58174eb4268452cb8",
"0x0ea9a0a62f1db4cf40e5e2db0286e48312eee96e72305cf4f98c5f7d6c2df9e5",
"0x13b3fe8f9d94f4d1bcbbaa26018c2c54fcaf122015c5cb9bfbe7a6694ca718bc",
"0x2208e0ced2039b4140bd1fdc4cdff8568f92ea662ab6588a16c42fd95adc8f39",
"0x1e8616716cf3255c36bdb7b62fe0f9b41c3877aa2df998ab54e8974e017a3537",
"0x038c19e5b3c8c3a6e812190a39e6313b181dc71e065ada3b823547451b8288eb",
"0x2518ab4d82a14c358e67509c46fd78ef736049c9498592e9390fce0e8b42a314",
"0x2c2b623bc30fbc269b3ef27e6a7fd25c2968a321382218ab2548e18ff6ea4b3c",
"0x25fa075323cdc87b1db37b7d42fccf1fd9a7ad6a598085e68e57dd145032c15c",
"0x2f5f009c35bb13a3027067b3bf5881d8c533b67fcb390d162fc406c989575905",
"0x0b8e0cd5cab0e99ca405d6bd1597a9dee6cd3c0dd4e0f6929a1d4d88b42605a3",
"0x104069c2b60c8e4b01890e6992cc841e269636e3c5ab6905a8f4045711c19665",
"0x25d04aa8cab6c80cce8005e027f4bc3b82e91fe2f1ca6e2b652defed5b0af05c",
"0x2cc7d8d1f3deb41e50665cb11ad9e821464a382dd17d2e71fe9d1c52c167427d",
"0x1b176ebf76e8d0d4dd54afe65596621b9af71273e5006cc60cad9819e2a0b87c",
"0x128db0ff4dade1354d6ad7567e59b4aee9341ecf906f2988aaa53f6eff912aa1",
"0x19b85e448cd2bd1cd640922cc2c7ba93441f0bafdb8a38818a5d5a666c0eb921",
"0x0498634a814e0850c5063b301461fff914fb9debe1aa76673bc0dd089e8898a9",
"0x1e0081d167ae36dc04c5359042be8c26af96b4ecd92c398d36a12aa863f23bcc",
"0x26f2231aee75807dbbd2a46279b38e94514b1945517909b93e482feceaab0ac7",
"0x2b81566447dccb12959315088de6e42cabf4a0798110a8c2339e0c6fa35952f7",
"0x106920fdae1cfe63ce0199599d45c4343ae36a016cab57dee1a1bda89788a1d5",
"0x2d1b3979803f4f5ad56b9cfcb41d62c4a30b5f01251dbc845fc0004ffdf9aaee",
"0x0492886098bc8d5601930dd4bc7fabaded741f1acb5e6dceb523a7dfa70958eb",
"0x1b2f4d14a2c0d5908c6176e46d241af50de7927f0bc02d12ca61f4590c040823",
"0x1e792cdeb85952cdeddfc38534e2321f4a566798aa7b7caa7c655404f4aeec44",
"0x29d050fabbb2ec05984df81ed8be2838f94b6cf3819a68a42ffbb66dd4c90641",
"0x222805d8ae12b43cbe30e5be4dba67ff2353b06f4bde6af8a3e7f8860016a047",
"0x20eb248ee0196d8b59886a343afd2fa88960f208ebec71901da094128cbc4725",
"0x22058b95c5f9776d8d3dd8d0c7a922602606ac72d7ac0c3ce353ee0c798c54a1",
"0x22afd288266fa099adeaf954fe2a94b0c05445272ac8b50655677be97b130bee",
"0x25c343fe28997a29309a518d42c63b72c281bc44fcd4bc76d2cb1ad34a3fb59f",
"0x26c9e1c8f49e22d6ac88c7a362513a449e682ab324b5e792eced3c0cf5a41f4a",
"0x2b666c9f3ed397d5bb857215fce16a5de70d844ec6ad0b8e53a70287ee939668",
"0x0193818f6648e494b44941453f1163478525f5cbec6b7fbf7fbcd2f5f370052f",
"0x287663a600dd765c1439d38bb92544aeddcd9959c96868df261f70021f4643e1",
"0x044046628ffff9fb29c8c7d497ea02f9941fb149960b5f2ea48c800bcce85ac3",
"0x26677946fb04e67bf0603bccf418736f976fe326f2351e351a623a49f015950c",
"0x2a79f2df436cc4bf39b2ab08d989ea590d2d1fb85caac9bd8a526dd965b0ab6d",
"0x2177c32e659c0d78c6766c5633e9716e6a3e09b0f16e139985044f6d2d231bfd",
"0x2181f1fbf114eb1033d4727aa2b879e28d034d8197e460798b2d8be106695c25",
"0x1582e0e3ea89e6c7912c2b2ffd9b6de7f960a6a7ee9c27d2ec9d53aaed390656",
"0x2899f6acd826f205c140ac2599496b3a3448dd62e25b076be959cc24b12aa69a"
],
[
"0x211fa1419f2b7b630c9d42ac4dfff1d8201547e24651d10dd4b4988ac06216f6",
"0x18ac51e16e5865ee074806af313b040924f20a76c2a45a76b90aeb07ac438e03",
"0x2906c33d1c67bd9a2ba6ab37ef7aecf377eb3f324ce68be741441faa846133b6",
"0x0d6fdc1a5ff92bedc6919093d495de525266075a273eadea7287b1b4941cf427",
"0x2552b734c5a95e374c8286a1cf7c05975265132ec03487470a513366fb38c5fd",
"0x1a8e88f6d94394599224dba0906142559b388ba2cc168fe97b6af4a85aec2680",
"0x2573ce0ce1273b649d31dd96f1f03f2ec83cf4920b72db75e428707dc1e26db3",
"0x0ce0750d2b6bf2a1251c0c6b496f01f7217a58c4ae1e5bf17a1f884f9c430642",
"0x154735e5f8c0640c2c722fb3dac05c4d603c3e150dd2cd09475d5770159fdeef",
"0x1671d015b9090cd861a5a5ccbba2cbd7a51bf07febdefabeff7b69f4b219ff3f",
"0x2d2fbd76fcfbc5943b16d77456d974a7741165a49187f28efb5d64a7634a4260",
"0x040a119f75e867208bddfaeb55741ebf53a30c7a1affcb8b6cd267c66c054755",
"0x11a3eb9fe3312950bf5cafea6c2b97818825db4389b8ae9408f9c7cb4882665a",
"0x12c9a214894557df9260fee1fd68af4fe37e63234f4b1950fb6302ef5c7602e2",
"0x19fc5d4620dbaeaf5448897edf3bcbfeb3853a9126c7b3c3d5b77ebf5b7fbf21",
"0x257c925a34966aae22eb261d58f97b43f255ae75fd0864fc48e492de7e55becc",
"0x18115b83ed73527d8c1823f98ae53c499a375f99a82064b270a54d35ea9f0ba6",
"0x1002ae120de1a1f4ba32b976d7dd4f4579381ca75f00248c5afbdfd80fe521a3",
"0x24230056009f5af1b7f585fe11ab1af1f4e0529381455573c76094e9828c7cc1",
"0x2fefc9ed5c4feb1474dcdd8b11184afdfb5c4663cf077c81c8c2f118f101c583",
"0x121991b5b076111411145f18534359541107182407d3981d463a10a6c04f5f04",
"0x161a5dc3f5e215684236c228529d96b6cae2af12fce8c281ae7c5ae13251cf0d",
"0x1b7cde8e1bf7f5df08a8fc322f21af95a44f9d782a5d74de4b12b3cac52d3d18",
"0x1efcd1c5767a2ce97fa08064888beb441feb80d799f939d284790268313e0cb8",
"0x1516c91480500fb959576c060a50df5e5c13b86e39089be8fad5a3017c19fef1",
"0x1a5acefb238a038e8567c0f8a98840870c17b9e2841f6de8a75b4ec765fdc74e",
"0x26f743f547ba08bb0a3800e83d37a508063c10ab415fd1c6b71fc3e642e27804",
"0x0439c5460f9710db5ef74e5e4ecfbbab6c92d81e1bef048af2ba990af6a96412",
"0x0b1cdb26cef7f77835ba81f23832acbe2cc8ad11311982f0b39d89eaa4ff3d88",
"0x1a4cbeea3894f5692512f2e13ce9034239ef5c203682750d0ed7263c3dc4a05d",
"0x1be2d5efb6c55e9b31ade0b3ca179410702f09ab5c176fd719adb145642dd2fc",
"0x1771f3273703d9c276b6be221b24044ad33a4f04cfc871010b8d1d7b461a5034",
"0x21042bc294c0c181f4c512a6a7d94f3c2782bc28a774ce517efb5c567daa30ed",
"0x0d3ea1bd94a88d6d2a0aaece2f577ee98168284e59138411c47702aa6e9a9df7",
"0x1b2ec4de5e50bbf2c918dce28e1291e7620f28b0cdffec6db9a3afb857d48bec",
"0x052fe3c5b2091f4d9cd772fb788288430ab43c404a9f1afd28f9e8a9e2b539ba",
"0x1ad58f9fd03d9d21c74c08dce54dabdd724b25ce408fe990253740a1dac49186",
"0x11c044f3e07c21ff4a93fd1056d54567510c622ae24cc7c454af294b4d5a7371",
"0x14dc6b7bab9b24d83ab458d326ccb312335c3526cc9dee1802ccb7eb0cb8ee6b",
"0x137cf4c2a4afcc4bcb58a8eda56f5223750a12b2d4e41a66727d797138fbde86",
"0x07d9bc2c364231525ac35618fae08284af5127124da38777326b4ced6e87a0b8",
"0x0f7ead7cfeb697ad5d119032f9e8580cf8dc44c8268402d866ee3ec4f66e723b",
"0x0bb18ee7793d2bd5a3b32a6daf6bce111c1ba770a03c8cb19214cd9315e6b381",
"0x234650e3ac2fb30e34af2d36dc407c891d2093232f6e9d1a5c212bc998560d45",
"0x2eb1745785eb34354cbc25e4d7d20866e97bf688aba5aab3462aa9d53c753308",
"0x1695af57d2faab4077ac86998fa44f39c1b3a9a6e8e3da91293f254ce12fea86",
"0x1b9c5539bab55de67a1feff373539bf20d74b975f0271a77fa67c923529dafc7",
"0x1901b13ce9cbfd15e91fafb059ced8b7936dca44e3fb3a59b9858f80f7e79bb5",
"0x302d415567eda49ff0c3dc812dd4f2f90addb3161b7fc6f604b739a8988e9264",
"0x1ee445f02ed077fce7dcaae404c42c72ce5c73bb60c59ed03192398330f27e40",
"0x14577b4a2afc653d9193cf40100e439ed67b26be2a9c1dcc4c53f29fcce478ef",
"0x0f70ff1275eec4602dcbdd315329e51316e39bcf6ce618b8cf49b9d0b9cfaef8",
"0x2e26e4b699b1fabd0b7bb94ae902ce38f8e4be6b723b02918b59288fe36c6153",
"0x0596a8f8be07116754d6b2664f7759ca2a81dcc3f05f89977e04b0fa3e424aa1",
"0x050b34c574517ab6ac58b491774c7fa2572951c4c0c0cfdbd1ca46242da8b48d",
"0x17a32f1c2ed7875f416eb3c3bc5296085c0f95cf8fc91429a81010beff1aeda3",
"0x08c7b7dd56ffae4496dad107e585670dff7919514bf2dfa8572df8d019938cdc",
"0x1041cb8c6d4155e3f11ea4f4dcaac28874b20400d511c166108580f5b4e1ea5d",
"0x1b19cb3e41e9c29970a4123c4d0c834f19216a277a03caceb457463bf353ca1a",
"0x2e4680a4ac50cfc484bf0bc75f064e0cce85e5bf037908a1f4e54a66f1ae9a0c",
"0x114fc9070b4811217501ab969073e570d01ebf4b10b3ce9fa09007aed14d7b3b",
"0x12a97a6552f3cb4aed117f029d2fb8a26cc6142887d84579404893055fce6be0",
"0x1dda8d69266fd4f1ce596778727e55262f555f158ba453321bdb34e18d835dad",
"0x1aeeba0b8ee533f104ef753a049e0495ab8d2832d271580be677568dd54dbc8b",
"0x087d80c02cb866a6e48757dd0715ae16de850983a156e249e898c0a099feb2c2",
"0x210cd88db2e56f4197fd2e78fce4a33f955fadfb9db3f3442b864016e5ff30d6",
"0x132b7ca535bcb9e3c5b2c218a2a6ddf99900436d2d68bc7c5a155715db5bfc03",
"0x2c101ab309253551ba608b65def31b407a7d13b157818c1f1edfa96a8b3075bc",
"0x25a13366ee7d2cef6fc1365c349f2eab64dbb154f492885d950ab1494868125e",
"0x2f1a3b3695d525788fddb27219d3092eb8afbbec37d5e097bdfb1bcb1aa9bdf1",
"0x12eb5e560c681856fb6af9f6ea072fd7eb82aad57e88af7bfc7f0b075741efcd",
"0x11581e2e8eed45d13baa42e711b93639d3ae5247c69914272cc2ff6058d3acf3",
"0x0c0c34dae8f3bf7007564fabedd283cb025d64f4e8f88a47b4e37bd89b5c6fd1",
"0x05b47ec45a81568e0730df30770377053d5465341d3309a87fca8604fd1c35e4",
"0x09755b27f172ae86cffad94e78fab9d8b740d6891efe2cba55366e61c0c98206",
"0x0600a9f4ff5c9d8bccd4952029aae6f6e2004d7baaabd9040e3b4216e2cc4041",
"0x2864302ac98fdbe4a29cc57c83ee1b60e0a7ef59519bf20a556d7b77a0bdbf38",
"0x14a0943541647294c4d0442506d1896c909ac78166985ffc45a933b4c5a47f39",
"0x14f026e852ce5c5fd9a55741e4e33d0a6d8d45ea190894530871cf9803101b20",
"0x0b7ffc49fc5601a646564e4327ecf8061ff6f4982d5d6dd85699e6a589f59861",
"0x11ecc2afb666b89fa519954da8f1e775a16657786839dd15ce4e18b6114a17af",
"0x0266048d728717bb6736cec6bb53a48d53c34866376fdeb1368616540dd57b38",
"0x05d0653ece676b876c63c85abc06d14e4b4fd5bb959f24ff226aac3ef33c0604",
"0x04888bfa7c5cd40a493a9089b36341207c2302edfd283e723633e335ed4839d3",
"0x0c5df4b6cf3b9215e3d6342ffa2df33ede670db50dc2477a03d6d3063e64fdd1",
"0x2cdb43576702ed93262567dc50237ce620a628d4c3e4eba9eb863485db2a9a4f",
"0x1da473b175874ba5f44bb5ef6136b6a4e817140aa5d5fb30d7a7e4f05af44e5d",
"0x17c4bddb0c8bf05980c312557057790f8e9aa1345d0b2b24f652a72785199f16",
"0x156ff7be6a05828d933945b04155dd3cd1070d810843b334083850a8de293d73",
"0x0d37d0e3108d1f3f1b1677dd4174acc0afc962f54215fee14e32bceb8337aa2e",
"0x11ddb1a440a4d076942d52f68bf0ef70800aec60ef150216d242abdfa84b5c97",
"0x163bea67b48bc43fd3d96705cbef764c4db1b61041f02510abb546cb6dc4806a",
"0x22aa414c469933375bf3b583210ec1742b997ca4f121f62df210056624ecf304",
"0x2d7f90267ae5b326c3d007fac1f761190f1a2d2213c8a1915057705b888b3b42",
"0x103fba0819fa863fe82f18070149ed5b059825ca663e57ffc8e025f5f954ba9b",
"0x043ff968ce318a4219dc8b1b3e9b1d0b5770696dde2e8b6e4f5ede0cc630a4f9",
"0x0b3ac488943b0685151bda44aa6adb5b645fdf95d63c25bfa118729900b69551",
"0x1151bf21881610c2a1fccc5f25a8d24aadd5bab7620a456f542d2a27fb9d8333",
"0x0bfd02387911be559bbddb6072937662c15b2a5e2c190a5364f26ccf51d04def",
"0x1e23be22f022d1cd8a90938d552875a52efdccb8d51bfcd9993bae65f19f437a",
"0x2d64657d2392bab3d55a6f03f876da7325eaa8b26d4627623ee323280150d5c4",
"0x28398c2867f3e75c79a3d183ebc74757b0dbd5976375d5de3c4643d4696f9bba",
"0x2fe98cb56d56da5166550e3d62da69427818797fd678eb85548b3955bd9a8dde",
"0x15f2acb43b89e025ad031c3331b0cfe815ecdd34ce38c164d4ec65c1097fc152",
"0x1dc5214afb325fc97ec49b140c7362e48f916b5fefff40d1d4357a6e8a64afb1",
"0x0bf98e88782e75a8ce25deb8208bebd3dcde4a4d8c0d7c95b320f98ae37bde87",
"0x1c8e78dbdc499fe504d6637fb592695048f80d471e413f50cd13beb6008a8391",
"0x23445d2bc07a0705a84ad107f5ffef149f3deb0dc8993dff9ac7cb5d307cd0e0",
"0x165455fb86eb06686440c8c2289c446541e676341d95bf85105d08e994a2c9d0",
"0x177bd958941329e30138b30781b1686c1531212a075f0166494b226bd667fdda",
"0x1d9cac387b77178d0118f881ac7ca94f79cb8052a59235a42cf869b9290da2f8",
"0x294c0bc45d475a1175b9d7977763d26b155f39c6043ea67c7c528bd0ed4e7bb5",
"0x2338a930f2cae293c3dbd1386d74b5b7d88b8ad739bd54ae5d720fb697e0b5e5",
"0x1fb1f893d955103c39e9f5cba64bc7ff4a078f73f386d9c070179cc279881f51",
"0x04e7ce1c09295df1f4c16216867451d9424f33ade5e0274bda0cb417a729a7f6",
"0x12f5ceb80784cbc5631e1ca115f5b55dba3c4315cfbc4f3488eebc776194a3dc",
"0x0f6f9f33c1f40f141caea00e1b2acf51f41fe58ae14aa03ccd7d926bbe02148f",
"0x1be83122d94ce0deed510a78f30acd81764a4ea1b13acb7ad4ea3d481d4df954",
"0x0d80a6a155fb12ca328331a46dc758011bab2e4007a5e9a79b5d615131d3444a",
"0x194acfa387c01b063aa4a33551ed7cb9a5a217d4ffd0ed1639140db2b742470e",
"0x0b33f09047bc972a94494173ac41f3d7df5aa1fdd42d7217474d531e8ef6af68",
"0x0df147663bc28d9b200afd361dc6189a18b74ff6e4ec99c31d7f47db967a41e9",
"0x2a4338b94beca683c00f47c48bcafcbfe66babdaa51b27ffb32d17378aa78597",
"0x03afe0efd0394501f0fc763b3f1019182e62c0255e34d82a76719a5c6dcfcd06",
"0x1e1d4dcf35b59905dc2275f3a37f84b6dae9650988eea92180aee8f45fefba5b",
"0x2a4ae8053cb5aa44efa7af3f76957e572de37def354c04ae6eb0e17dc9f38012",
"0x26b6da57dd2d67f63611cf269d31b28080a92b00567894e3d56b6df783e02ec0",
"0x1d0b3ca820d67c20f0a83efd9a9c50a5ef2183813dc4d658329fe39435ce5710",
"0x1505b4c73b4b6b7d0d0e84d1cef6b86bc62c0d6eb3c745570ab1beb0669de635"
],
[
"0x0769209ddbe93ac17371b60ada48a8b0baf8c2df826d0c60791701122abb3647",
"0x08ef53e225e568f8c2957adf5e2418106f57809c8370793fb3ccac0eb9c4ef12",
"0x0f67730966f094a9ae0ece540cf1ed527cc31c5f161107ce2146ff11f6b6dcdf",
"0x2a2c892eca22e361229c79ac5dc2d9aab2ae508ed5f70b9832f0557ec40aabc3",
"0x039c7ef7c29f809073e30f2591c4ff9858f8d498e233f3883dacd7d6e7570be6",
"0x26ad7dce66a9a95a2b92d1633da3f33587a46117f4c26bc642c808b86b925a50",
"0x294402ea191b6b02d558c2f860e6e11898efc5cac4214d6eaf78bf046b424da7",
"0x200cc1d8d4d6f4a22934248446129b2082ebcac73dc9477599f5efcd8f092b7f",
"0x031b696ba36be3334afaa13168f5a212cb222a5a43dceb67ef2f90def1f2a3ac",
"0x22405ea030cbd6aea6efbc202372454f3cb7315bb24ec7d273569499cf602072",
"0x0e892bb94be4ddb0e13900727efbe6545a7cdaf7837d2e8aa91c085416f4a08b",
"0x2884ab441638fd7622aedc70b5a338450962e57e801975a887c28608a3f6f3d8",
"0x2ea66506abc2e2a5536857d8a372510a5dfd44005813a53d13a83eb3e30caff5",
"0x0fe3e93c274dfb0164a3479d77be40f51fbd808a27068da1e6d633566f5ad4b4",
"0x1b64728c657615de184eabf173ebd624e2eeba23e04c4a818be2e7ceef50d2b2",
"0x2c5d33d430dfddb329dab768eacff9d0be4dc9d638d171a835b72f2630fc07a3",
"0x00775ecd42283f8a4782a1a8e101c59df926ecaf123c83a569872cc8c1e3e955",
"0x2dd915162db8286e7863f207e5116c30539aa05753fa157dd2f3b07b6dfe11d0",
"0x1452f77a0c98817d3834aa29d6dceb1fd078b8873a02b33e650d3d9a463f4d7d",
"0x2bc056180a81b77fcbbf620aa8453ca644931dd432030390162525a596bc380b",
"0x0b3c1e2cb0607e12103406681be5635236551aa286f2261ec88f27a7ff16a7a9",
"0x1e7032ee33c3d1fa6d8d24f1307f53cb33461822f2717913ca654c0e3a13ab04",
"0x0bd2dd98fc4a8af526799f197c315857d71b0740f9a5274c4e3c4e269af0718c",
"0x142e9259f139ab5b18345dba3b11d4ea7ba6483cf28163b603674527073cdc2f",
"0x28bc36ae9e257061fcab76ad2114d96f29bdc78dc36bc65bc94328213e5ec615",
"0x274dedce47e3d3ad192b0d48e25c1e83c68d78318d2538d787b3a79b143cfaa5",
"0x172ee8a327ff74dd9910f098513499eace293d9276dd4ad9b01bed9a5fdd499b",
"0x27e7c5263cf192368bac114666c8adb002a01def45fbf084e3fb1781d37fa17a",
"0x2bda40b3cb61f7868ea66a588423000121bd08ac139e5bb92717fd427e15bbc6",
"0x26fac827cf9e87cd9f46a055ca32db3055c68f8e7097f1907b27e78197f6c4dd",
"0x271e74c38c0bc0b5f904e1459fafe0032ae2b3a27679fb8bdf8fcfd9294ff1f5",
"0x25da79c356d14b424f40e8052b8168c7dc4d938d181c2caaca27619f12d210ee",
"0x1e699abd2c6508eae9bd6a9a282e5513c003dd642dd262d2e17f79f09bdf6bd9",
"0x1ee81815c3be0406b2a9cff25d6f668d9ff89d3f795ca260c7187547cf09e79e",
"0x21c26c8c318b88a969c93cd35c7d227fcf0d69867238695726f90dffcf938279",
"0x14013837d5e3e65ea5155e016e3bddcd575fd584e4e61bbbf295f88fafd8fafa",
"0x154198f9c749177ed41262a5906028d7fe7ac4c6c808865a85816ef44824de23",
"0x1e59f9ee9c83ee78c55c6bec8201f28966beb0c5c11b54ffa01c6451f7a57210",
"0x2558c2e976422214f0dc5a2d2ff180de2628f1a18645da52f02b5e6f846f9504",
"0x0043de4604c7bd1ced85922717d06992924c23f4149f844be9bf6dd9c60f3388",
"0x282947ab201839e628460e16d3d31fad868bec724f263969b3d0c69e9e8bada6",
"0x0a1ada5b5b5018481015fbe3c43c38b44c7b67804f50bbe4952812372603c935",
"0x12d7c76e2833a9f8f57a17e7118ff6666581503026cc1c7a7655ccbb514e516e",
"0x24576880cf40f29a0fc19df8ed0239cfcc150e11b800aa880f6289bebd89a013",
"0x1c7590758c8996f2119af7cef10df7c1cf9d8c1dc388975e830b50680b09d7c4",
"0x2c9096f0f659ee66751cf179cdfe5af5470c6845335de41a3ade2111d9330152",
"0x0ce33a79644c079faa54139a5074943790985a7c6936aa2d3ea97fcadb8d64eb",
"0x0ffba00c11bbb7e6070153b817c9ab5acaeef3306cb05bb8feb5d54fe89ff8be",
"0x15a15cc692ed7bf420df399c9d14e5ff9758a6c7db3c5c097063217b4c6c4f1f",
"0x2214373b87f53cb1d4e91aa21d2e607e83c7ba2a61de8d32c54db7050e9fc17a",
"0x1f0ba195d267de887b51cbdc77e6c77a5c055a625e76c5a22ccbb8cc9bb15539",
"0x2f3b29c072d8cd7c1a673c6759fd58e34dbc2075dae7fd5ebde784113d61755a",
"0x23df997a7ef29ad9a5fc7cc21937c9977a73247434821ff60b31ef0170ed17a4",
"0x1928275de0e4fb64134721b14ab3d99f94b1c268368c1167b2b39ab30e308972",
"0x2bdfec339abdfc11fd5a9f48dceef79a463be5074df37bf00893c83f4b20cc0b",
"0x266134d4d26103883f7f429ed07fbed19bb0e17904cf03eda9da117f8c0f4e1a",
"0x0471a32e2cb225ba86c91cb136309cb462d49c9045a4d4d61e00de27e6ae3ea4",
"0x2c56d2388857121e91cea207347f0e5449b8f7d4bfcdd0c8d71872a5b223ba58",
"0x2acc967f4e0cda77f4f3578b2e463848895b31e7607dbe33e8a1f92a17ff1f2e",
"0x1a891c55471f9da7f6d6125219a3b47eef6560c0fd64dca3177e1efc9b681267",
"0x01f6674fb43a263d7e6bc9b5c02264b61fe779d65e28b68c2b4db7cb39cc94df",
"0x07bd8e87fd3c9d91bc1341cf7edde51781bc51834aa0e3b6a57a830a7e93b83b",
"0x17d9fa87ca04d5451aede41b787ed0313aeb5f1a5f4effb914820aeacf0af8cc",
"0x0793d4a71e22db2909586a0caeb15bb2edfa0eb1237ae62fa90033d45c9921b6",
"0x2e36dff4ef06152e28de7355e3c5e25f10c0da1dd9c639c7aea03e6d8c2e27a9",
"0x11ac31fa48899db062624788cfda7840b346854f90dd5a45be2496bf304e6131",
"0x2655ee18d2a0ff7ea24b51fc3d465eed4b5b579f0d7c8c1ee1c0e385f53ccfa8",
"0x01dfa376e1f3fa01a5efb6d4c79ec70fbc7a07a7ee7458f879da75e64d75ee5b",
"0x274eed37c69fb44ab5c9da14719d85bdde627967d14d460c7d44f7f32000d1e4",
"0x04fae3f7994206170e657f4064b91fd43f7f0a5542e333dbabaa60e2470fbc60",
"0x3045e0d8b192fd61f35a9b5369bbff3ae2cd4708ffe02e8f919230e428c5761a",
"0x14c7c2e746ce0b0f805ac85a3ac01207c9930368f4e8729c4248b433e845c794",
"0x095e5bc71d416d2301417d3693ed6cd5685af11569e2883f80756e683ca609fd",
"0x29c47dd05c547c0f3c194d5bb37ad7e1ba31a6ca4949da0224bc516986b61c78",
"0x221da684f92fd8f01d335437a5d5594849cdb4c0d3e350b2ab9a29e6e6ef93a4",
"0x20ec5172b4edcddeeb1a493cbe2e5561762f2c1d4b41b438bf04bfdfc0402f69",
"0x1b9bcb2aefaebc677c70fd0a4f38c87dc9a739d39bfef6b23b855b1a2e9724cd",
"0x098af3612282c3b93c2c3d782d4731b5cb5241cde22dc665230afd82ff5aa72b",
"0x056bf5e4248f55f2e4c5a800dc1086d82ca98cfd2c4be973e7d4685f612050e9",
"0x2eca3301b4fef07d2e51ae33d6e98033141a34ea1f9821529e73de6a8d67560e",
"0x0ee44ca475a08ce1d7579734cc1ac2ccab00dc92828df9a0a16b17bf0d040f40",
"0x061f484c4e6fbf65812ba4a08dd042b7be0148a35b79c0baab82dbd129e349f2",
"0x270a8d9040ee78734474a3f1c03258cdde4eb2774909520ac95056c48b471d86",
"0x24e8ea7fb0806e1f548e34b85f61fc93f6a33106e1c2837f26900261defeff5a",
"0x17e6f76d7f71216caa967230ba0d20b91991131c31fc03a77a0e4346fac0cc47",
"0x218e63ae07ab39824838ad7423b262f9231446669bd64596a21692938f5fdbd1",
"0x04cec38dafd7be3a0aad26b24b100e25977ad1d6ad471922e39211e54b5b9d78",
"0x14496b72f8518bbf22ae5764f4197df7eb2d4cce04eb2caedf606f1ea4183ab9",
"0x0b15601fc061a468459830764b59a565feeffd1bf6a536f420a7a3e0b7d6ef86",
"0x01955c37d5e6e42ab82c2a57ba398d10f90446acf0d1a98910db6fc7d56524dd",
"0x1bd6de8dc821a746020210e1e5f3dd6dbb41ceddbd73f7d73410181a8cc74d09",
"0x05280c6d461eb9d7967ac91f4af334607802b8db12e141b33a0e30217b693c44",
"0x159b199ca401c0c9b8248631bf39d7d35083b5c2bbbd0d871d3d0d4f3cecc368",
"0x248e2210ed2a826c83fbd6c235dcbbb3d24a7badce71702fcaf08f66b785777b",
"0x0c43b7f0265074447850c22cd3a81726f053f490b261dddc1712ca38a3ebd1b6",
"0x1ae8d611514f4d9e3750f4e66e8c2566e4842b6505e19c45f3eb051a7b6d8bb3",
"0x18eaf3e459dc8ba7d98d3cb2c274f8e902594d4bafebc0757dce1eed8332e8d8",
"0x0c7f13454b2f73791edea658be8d87c6dd72c3c7d26d91182d9c8cc87182edfa",
"0x16e398c145af7ac01167cf56440dc93eaa837cff3cc468de6029f5613270f964",
"0x0a7736c58b3771a259cc813f727d9c7fff087354542175eebf7d44e127c30aad",
"0x13684f6a837c01e824cbd026b6d8c4e61b98df6aeb62d1142df389894788b5ee",
"0x0c4b1c8e9801649077a17bb8eb2d995b3989780c3af7f651004fa2d3f1b8865f",
"0x173602d42c0a38489130960549542bef693e5681947c48657dfceb41b0a6606d",
"0x2389dddac6b2890c7e30504b0fc875ebf8629325206958b69c55c9cb6303edb4",
"0x06c9ca19714c42cc7189005cdb51ef7b2f07484cbe0c151d48c46d47b77a93f2",
"0x167b108ec7a36c0e1bcf9c69e8ecc5a189528813f1737e80209ac99c462159a1",
"0x1871a5f48a8e6bcf2319360dc7885cb1aabc505a3b53a44494e2fc400a62d370",
"0x2e59f862747c1ff8fb961836ce770a2aca5f3b4e0e83e338cd599f9c4e35c1c8",
"0x198c87cac3cc736412bf0d8d2f3a4672e3ecf503b4d7d2e40258e8e64e3eb72e",
"0x2b36f6f2c7130341b2c699532d06d98da2be8ad3b8556dc1bf35375f2dc2cc01",
"0x05ad47418ed404da00ae2493c6c532f783dfd5adc7c4a0f2fa1d60c0e7f4b82f",
"0x2c07656ed2a56f41ae7d387cc0213f440e102742360c44679a6aad8c8263315c",
"0x28fc3ed801e80b8f745f860d2f57447700d4470e31c1ecf0b1f19240085d3218",
"0x2315de5587a5ab1b774763401f71ac6e796055ad5633300abd2e63446bb87563",
"0x2f1f3fdf187e2a6e34a48ec9dc8838b188053dad8e6008c01f627388c8ebfd96",
"0x0c72edc09bff0911637af2314b12f04aa1ab2a8936a0d0932f129bf1e666e1fb",
"0x2061a56cde9b94de146617e1c2d7550a8f1272154eea488149faabcc614ecfb6",
"0x24efce7c9f9dc595ee0286527b581cdf659e5721bd7707e06580f5cf8b0cc513",
"0x2fbb45e2d316c9e9b974c081fda1418bf8de14ccae39daa6532e5e2473ad9b95",
"0x0db1fe4767ca51a7f940cc68ddd576211627ae28319f868ac47cf81163856da5",
"0x07d7947f75ca7eadc86debc9d876cb2421307bbb5518bf82c0e27b2206afdd83",
"0x301687b7aad786b2c3721f665fdf74b8170ab8650d287f842500224e93146169",
"0x0231c466db088e9f696b9aa566fdac7207155e19d5fdbed6524f2c1aec5020c7",
"0x29c11de1b503f5da4bd8b3c3db5fe7d37b3877ca51ad0dcad95152ba819fbfae",
"0x0101217cfe53dc6325a81eb7e920b198a1560cb9c7e5976443860a143f8445e2",
"0x29972ac040a02f55d8d0fd383d0ba147375dd71132b1a91f197292bbe424a41d",
"0x1a7bd39d6d6bec6cf5ddaeebd174bc8eb5b98d0cd36ecdd28e1319e745ba18c4",
"0x0c59b48dfe53bd9fea14943ccc317baab6476d230d29b69f1f6fdc8a7a4e0b80",
"0x16310faca95189f36bcf9855861205fe1af9940667db087684c76da61c759a11",
"0x2a3ca21c40d5bd4edacd339e5ac480354abfa781e43ab96e04c36fbfc9b96991",
"0x03856e1b9ea7eed963383320a289f8e4434ad11184075ec48441b07a6a996cf2",
"0x14bb06da170069f2075e2e98779980f8c25c9afa09b6d9200473b0b4be1dfd0e",
"0x021f6235693e64c3e04019d980f130a8e9e0463a06f20f7b48d70d4e2767df40",
"0x248a11d422e2ba3824f403b12bf91f7c3e1f4cd7df0c8d926f4db7ca088e88c4",
"0x27c83f0074d7f09f5c653402f14e6c237ffe6dc88517708d1a6f22f8fcc5eaa4",
"0x29d69c60e82302690ee548e134e3472c4fdfc0de1980b05a3b16f4bf90b75df3",
"0x16263dd56b3a5d8e1adf78537a59edebe9279a666be8376c0f857dbdf619b3b0",
"0x2faf509e27d009d539ded46f4205be2a4d07990c6c3adaec2774d29f211c333c",
"0x00636fcd12c4cea57010606a3032ec57759c1ef7857908bae6f478f2ce6b1116",
"0x1ae54440ec1448a756b6d17eca423496fc01981d625130f0a34b16406169c628",
"0x087f48ba394023dc06e837328fe9c5c360e8051f7331008f55e6efe703a6e670",
"0x259f66390c6850db70bd9baa0a9af2544f5038fef029dca5859c498359efcdde",
"0x1a320b174924a92e7e1799f926b1a4a8613469713df982d4feb17c469c6b3132",
"0x2cda975460540e7dab62116c6681d9687de10a80135949380a986da2d3b6a93b",
"0x2904eabcec7a95c537f59bf4ec25cb5f61050bc4b385af6a7ed8dc787844e00b",
"0x27ea9cb045a66580707da6934884df14aacf6f77e4196f940e022d3c02962f4b",
"0x2afd7329aa726b450e0687fa7661fcbccd1b4d00f5c63ff56cf71f6e0782b351",
"0x1f70cb2a4b5c22e7597556b55dc9ab3c289b63abb49109e64b3731c4cc899d02",
"0x09d2c500e798e9bd5c97a43a905fd18880ec3ab776c34ae975cd5820b5be6a71",
"0x187868870b76c4af4533bcfef9cfd3a26e89326389e87f79b23f986ef6546b36",
"0x20cf61235eb8a2faf09f62dee581d48e756b7f6f6b0e108abec7d1cb4c340523",
"0x06431aee16b0fbb9a402325fe3e1c78d03b49cf7211b78e122607f24906f74e1",
"0x0ea64a8557885b201149fed02d32539d2270ab155012f543419d66e584f70980",
"0x2f989e96ac7353934bd8333aaffd25900f6d4b78ed5b50d832e35915f20e3c9c",
"0x1f2357fea7a406b651ea80a7ae83f97248b2713a15b689d6b694f4a04464ac3e",
"0x091eadfd9e583cbf346d83b894982a75f827c89bbbfd6473dba601cedbb13dd5",
"0x0c14fd42428144b7b77b93340103fe047998e9c50993da3ddbe328b8bd804f9e",
"0x252da7206be17596eb2ef5bfa94f142b39eb9fdc7f7dc3bda16825e7ccfdd8c1",
"0x2ace67f28e90ecf05b00aca160ad0e5444d3397ef40640081864803a63747e1c",
"0x207aef533b735e20998f6b54574293f8b0e5479e32eff2dc6ea3fd10414db107",
"0x09b3080dbe8fa12b8eec5edc0d55d87fa3425ed591daaf8396f70421b1a0c35a",
"0x1003dc28c13b5737df9ce84ad23480f3393de6024b095ba842d9c8c3d7168a8e",
"0x23618fdc2960f9fa296e65a926573ae39e2c442f819c2ccd2387c1493a1ee57e",
"0x1b12fa3a918da62249968385c65552489c76f8a808f5b28e5a3b1a76a25a8ee6",
"0x087a632fe1f540ecf61722f036f3f6863ae9e5a093da6d4f57156e2e8c6f5f9d",
"0x2b460380d8151ee73eb997fcb89f9b0d63a210ea8cb9f23ae4e0c75346d89a0d",
"0x302e06a0b308b3004b980eece40bc80cdbfd863a284e643ccdb22c359af19241",
"0x13dc02643f54245a7ec529481d59e849f7e82e4328a4f1b0d916308aec44f20e",
"0x01f9ea46bd55b9f52acec310f44a71a389a5ecb20933baddbe29699a70adb6ba",
"0x15c2f7ff0464ec096a3c89e8a6563afc7d290bd50620c57fe0c3f8e2667ce224",
"0x2bb074ae7bd782f9a3aad78192c58d12535da87bb865936065a1c2d8bec0cb03",
"0x1afb2feafdd6b4b18bf120c1bd40a0661d675cb6cdea4ffb935550db66613f66"
],
[
"0x2f519d236ff3908aeed8bc12b6e3204820c18780cda2aa9bf32a675722a943e7",
"0x0d463eca09295bbf17ecbd6c0f1a2ae22e9e971abf332b50f6dc652948130ac9",
"0x04f7b92e174673f12ad94305e211dbc74505cea331c8270bbc0436cfd3f9203d",
"0x0b9ce1d7a1d5702d9cce533fed0eb4efa2d3d5adeb056a0bcfaa8df560e39d65",
"0x05fd9a940ebf8c4f6365146a71cc4d60792afcfe5edfb289ef3a5e0ee7171df5",
"0x0b5644601dcb7f359904a3be22a6726d88c91c83462e2a96eefcb2e0d3aac3b2",
"0x05270c934663d155aa71e7bb2c9bcc6d8dc181ae02c779a1bde958eda5b61398",
"0x1ca3acc7430ca47799891a4c459af74a965256eba9d6940381c1d0bf0a9739a5",
"0x03db72aade768b78c7a6a9ecda0f0f2c6733a0651cf2212e174ea97c01a59c70",
"0x1ad0aa205be150c5621b3fea98b78db2e4b20fecf80034c52e9ae558950dc780",
"0x041dddc69336c714ee7cb998b68d94c5232d4e8d1deeca05ce83b0ed0834cd3f",
"0x2b3e015174c3a6939f08df076b3ba73bbd4f2452100c1821492321175d162b1f",
"0x238e6389e5fb2584c06ed2f534d4d9e2d5d62bb99dfe8add413d809fbdc754d3",
"0x15f4f175fe2ef1101a4f0a34fb73acf4397c3379b1c2924dd94b1dd4d2c6b27a",
"0x04fa37d0ac02626ecd1f192e28acc2ad80f3de4354aa8ebe87471757dbabc9e7",
"0x24deab96a4e96719adf665e11c38a3334d9b47643171a7d814b9dc6fe7382d02",
"0x0a2c7eb8738a61719ce05c72547cfdce9f6ac8770cd64e6556a06c7ae86610c0",
"0x199482b63e5fdf185628c3046f0bf2f7be5d0f256ecd035bc212fc01eea8ffa6",
"0x296cfc7f739a3cf4e9b75994056e2568c6aa52b8333520627bd6b28cf484de9d",
"0x06fdb5a0e6f4e2c7e546bad6b1669db01d9d4e3bff4ee772507563da1ed92dca",
"0x1216f1b2f749f561078eeaf1fc60590a71e33157d0227ac8e796a4042e945ba8",
"0x193fa4aa12acc79be80e6a2424afeb3f4d249566e8a0908c908761758437929e",
"0x12ad33b11810144865ae5391c8f266adc3fa0adb622b90c2ada406253e09eb2b",
"0x1a90d5e1c0578c066529c54f8f37e23109de9159e298cb6c9102c6ccf581a07d",
"0x15af9b019146d04fd7db3dcc25ce29d163fb604f5ce11b8fd507089a8660095b",
"0x124aa9d20b2a15ec73fc6b6eb84b544edc13e9a72309ab080e362563881eb8ff",
"0x183cf3432c6354e3bef6170a32fd653b560748e59b65052512125db3b542ca7a",
"0x263159492b9a836f8d477e6ccf6f2dad9d4bc43eea7241f224314cd356fb07eb",
"0x2ef6717639f7e6a2a0c60da01ce73721b83f6f9fca63ad632a27c5e0d561dc26",
"0x1b85e4a891411168c803d411048f946a167f45edd0b98aea0e96fcf9796a5415",
"0x1712b6d3ab45b45a1a43bbb23ac830235f8fa4c6c057be35b84e77ef366fd89b",
"0x2e97c862eb257de5ef4f71b56bab12b449b3186cb3f4c44ff32c931bd9c3108a",
"0x0500ca19f7690358b983978382d969729008b41a902b03c8254e8a4b863ebe2d",
"0x25ecf7468c3d34ab9aced95fd7f966c7e7fe7ed74ac02c2f33cbf59d182c169a",
"0x061493f05adc4813cb62ea6269e2672c241b4ce0e3658542e4bedc660cb832c8",
"0x077d4ee2b3292e73eb891b51f63b0fc897ddf1095208c65a291f470391eccc8a",
"0x2a1ddaac93b561971f9174611a06273671f80dcf4eb355636577a623f2267239",
"0x28c9d37bc63119f5b846f969452d93c78743ed7c769590d1e2eaff2f7d51b636",
"0x1c12d6672a7c9c525e1ad06e91be238291b6a452298c3f0907b3bbeeee33a75b",
"0x295813176a99d708f66de0dd6a79790c1049113c1a9589f58e29aef2431dc3d0",
"0x11cf1b0b429cdde5235a2fa4044a75fa29d464d422bcec4cd5a77b2a70996952",
"0x26cd23abd3084eb97652a0bdfa0675107c27d021a797ffd85c3935035e82c708",
"0x0c98e951acef5ecdf322fd11adf84e1237fd7a2856f5d611185677e064e59a7c",
"0x0f65e0d787c7a80daffa6fcec8e4333baf1b7e536dc26da1617bf8d33fd571ea",
"0x0a6af46169c405b7aefa2369aea2437e83a5f936e21b2c5bdd40c4c229691035",
"0x2c5d17722f1e857bc53fb954a1c617be89f79f666e7d42e5cd289bd1f6c2c253",
"0x05ed375b0a7340fdd67b5a6e02e9d7f8cee95207cc1f021a98c9f026b6b8263a",
"0x05c43b6a0449ae8aba7f7ef495f81f9b1172e2e33d6b45641c85ac438f867072",
"0x0632e9aaccb645ff09e9a71c0bdc98bb8525d16dc0808089288084dc6a37239d",
"0x020115cdd5958aee185af3281eb02700cb22c680fea57e0e24ddcfea04e4ce44",
"0x130ed2b41ae4fa1bcb39907d9213b816fb5be6f78c8b33f81037c6c82351ad6e",
"0x198b2b80ff15fe2af3c414b89c4fab453017cadce1b42986a9064069b91e9d1a",
"0x26a02e2e22afd030083fac312c3ea5ef2b8261a789a3cdb14e0f59344710c7d6",
"0x1e972689e841a22940b918fb25a4fd47bc016bb627359e0f8efb982516900250",
"0x1719a91dcbaa2591741e3c6e8c813071dbb249caed013b1a49a09c6337588388",
"0x07ae0bd9a15c6093e83d203cee422cabaac2b1480b199a5a01f3b6bae8943c22",
"0x0335138c841a80c3374731753ec839f6240bd2a965d10971c20a5573c6700a61",
"0x0bccc625cafac996fc66d3d723e2efcbc7291c5c2ee94ec4308719f0f682bae9",
"0x1aca016e7c2b5f0fa4a3c8466822be48e461a2f96daa05a7e6bd65447ceedc20",
"0x228ca2efdfb5fc0371bef36dae53fb3e6743f7f5ac32773eb9daa1fff9ad5280",
"0x0abd2713ba22c5a0284319c09fdb52831253c15a3dd8bec25ef562dfd902ffb3",
"0x0c20a2af2b35bffc6c6b267df78c0ea1e9382f9508fa665f8fdc0836a4d5da0a",
"0x0da1ed20c40a98057ee6df9f8e55d6e0936ec8b1ded7ae68ee97c9329310c346",
"0x2b662b17eae86aef2137d9f669f08960d262f221708c49fe793884326c92aae8",
"0x00892d01420c44d4b5266e98d3963b613ee8b005a2b1c9cd20082a3d49f595ff",
"0x1e7068ac5f13d9a2e8b46d99b5d5f35f2d3de6de8bd81c8e78668ef467f05160",
"0x04c946cb36ed8b5935362ac33029dedd33cd3d62f638eb74f1834b1fb83060a2",
"0x0bfaea8cdbcbab42a9e8bf92141c329651a604055f555663fe983c1b0646d051",
"0x0ed5e5e518343fbbc0fb70386a6df1945679b165d1a65afc6c825315775694fb",
"0x266d7fa0ddc680255cb75a0cbaf4d586f8edee107e2d3d5ad5ce90b142b9812d",
"0x038632d442ca8a88fb33a37ffde668cc8c499b6eadc40af5b3f237f2ab62da06",
"0x18e36f3104718c8e25493c8d0410aec2779af54c23014de0feb6f96f34ee52bc",
"0x231745182598bb764367a8490e1d61c3d3db1699a7a54212144ffafddd37712e",
"0x298d6012d765ff5ca0e313106417ffe9a7f08185d7623b37abacf91ab0aebfb9",
"0x19f2674561197e8fe58d8547d3926ba2702999f9f5147fe77445ad75c336d683",
"0x2b15c22e56345b557175c1eca4279b909af4e965d941cc1b5352fe2d3229ab0a",
"0x289ad5b36e4dd22b2c92a95b1e3ef574601e8117ffd22ac0a0389b478f80572f",
"0x214626bdeae25c53e26eb6f7f65fa6bb4c83469735f03166061c245d00ca86d5",
"0x24f3525dabc6b7f53d021138eb9dc49133d046b851d4781ebbc94b05dec248d7",
"0x2791a40b5946f478a90d4e5efb36d8bba14f53e401f87056af2d55a6b7df5cf8",
"0x09318d2f819b522b0a847e5038118e65718f361f8947580cfa8b8b361ce5e8ee",
"0x219d8daacb4cef1375b06392f9220f1d204f0e88499c108c961de46fdb5d8fe5",
"0x268a3e49958e2d7a588b7276b41a2c7f18989d599e80dc85e39c7308d5e92f69",
"0x10d8226869f3e198f804bc9d51901e5bd24d824e03458fc549a6a16e5c62125d",
"0x0660a3ff70a9db2da72081518d7a9b473b054a2508b047a5c363f97931dfea83",
"0x031271a704e1a00bc2b860da159913bcaad3c8acf27c1fa3b28ce2c33841ffab",
"0x07eddfe02b81044a908a5f7d73f6f461aad59a29f1b55b41a2dfadb7968b4a07",
"0x1f93630d8bedc406368b348a7006ec4806b4dbadef3e7a022ac8e51f779f2828",
"0x085a2c147a95c4414b1b67df4fd75753f44d02cc54148ddbd6d771d3084f4cd9",
"0x02b256807b01a9aa040f02c771397590bad8d20df2520d6ff24401663a3d5f8d",
"0x1dc83ce1042b12070a2998b52f2d88a4fc2a7d324d6d00664a3bd617bbb4ae85",
"0x18233d96215c73f726760194809c1a4dd405a32ebe67620ae85f2f2b96862eaa",
"0x0c7add4ec9ce9e2fea0dbba3833f9e1260249cc855df6a2a1557740b9c477cd9",
"0x0eb7a2b2438ca0b3459f24bf4bfa719f08272a6f27c747cc151a482ad8fb3be0",
"0x0167e7ef87785ac6c577e395e475209462b7cfa832cebf6c2add446ecec58878",
"0x1e52ca68bd85803046e5036b236a6886aaf8fdfeb2bf41ab82c1e0eedf045a81",
"0x0875d6ad908a0e1b77b24422a99aba983c8eaee3a2ed63fe5d476d58890bf06b",
"0x1bd4fdd412c233e4ad6558382c336ce03b154baf81846aeb4977c1213c8d5618",
"0x13ad247e3e1eefb651b3ec25c7dc4aa9df5448c73adb7b683d96a6d66bfa3aa6",
"0x02bdda4b91162dfd2c210bae56f9252170f555fe3bb6b21a177cfd04eb660803",
"0x00e8b60d2341985c55753fb8e4ccbfa8b99692463b4e0a11a1b475b688480c4f",
"0x19cf84ff8a5184368bb6a6f20b3fe1380600b45758ad3cf7b88bfdee2ec61b49",
"0x25abb85753668de0457dfe38099de2bd1c47978b344ca58f7c2c0c02201997e5",
"0x24710d523c762410a2d4924464743478feb594b14f12851a541cd3d3ba75b247",
"0x29ffbe3a4a3087d01b5acb88009abde722a89296b420c9f52449128bc9fdc34c",
"0x0ec3577cf043961d009493d183d50720d25e49fbc8f9adf62ba72aecd781dc1a",
"0x26c113117e795ef7b8d7773f81912c80aabc19116464aa8fb12241ceb5dcc2ee",
"0x07d5f46533b2a2e88682c6fda0bc7cf8a0c70b160a83a967618c65b59c9001a1",
"0x23d54f9c4c3e67d924d26da36276acbfe02cb4f9ced76f4fe12e0a73ba803343",
"0x10cd6323749cc45b68d78b9d749dc4a3faf38bc329b4b29e4f80eb3dfe3e039f",
"0x29f2a6f05e471ef11fc76dfaf7732a9b03a69ebe58720dc54d95e8d66aac9601",
"0x188cf3ecdef093b77624ab20d47ae582fd0d9dae59987f7fd4c173900d50196e",
"0x27a03aefe417b4f88a4a811b2ef281b1b8eddd2ac9ea62560a86af54eb5f5f31",
"0x0990e3d736045f5fc126258b0bae3710d70a9a7fdd4a03834d6ba3e1c41645e1",
"0x01d0c03377b6c3e03a1cadb8f00aa6b3e856a5b12e9ffacd829a2e17eb1e57ff",
"0x0b3551f6faa579f6fec4b813a862f196a14f15357371499f98eeb9cfd9970acb",
"0x0f9444b6c7eafdb309da46679dcbab14a65268c58757e5ca9f76143205985949",
"0x14db8cfa9979850abc02c0b49b33e22dc4ba8d4557c37a4bbce9a2645a553934",
"0x08d995c609e1701dbc84e53f3bf3889beca275d0bf20de975ab7bd11f29168c1",
"0x22ee92f4ec09f2174537985f561d785c4942a28cefe4b1a6f2d736579b4306d5",
"0x0deac3e417c3e702add7e11e9a9076d2b12d6cd4c432b7bf199c492feaac78cf",
"0x215d0c99a7fb3227054ecbb04b39dd2e85a33be4b2a78455322b9a8209a7839a",
"0x144dfd27491018d95745bfa263ab11b6f6865c050700c8bc38ef6196973d4e82",
"0x2e4c9e84e7b07e659bfc709a3de211b454d028e4a74120b07f130f461210548b",
"0x260666b80f1d865b7ad6d98dca26cf2c1a5bcbd87d9d9d19673ca4db486652a3",
"0x21c2ef3ae808bc3b0c1ba5eb6fc594b6e383c1bcb05006b64fad6c3483aaa96f",
"0x1ea451ecce4adee6b1682153f4038d177e50944ae9cb55b4e0535c24f6911b55",
"0x0f8df7e95aeaaf0fd8f61c50a0b282c6df25fc884d707ab96936be3d87f75de2",
"0x2d9abc0ebc4284989c7cc7f6dac8b356c0ed4e6839d8a43d5783dd8dfb57acfb",
"0x1e851335f8cfaa72342db1d1cd9575d2190c671423fd5cde851051c0dd5746f7",
"0x189dd6ddeb39ca53540ecd57bfbdebc075f7abf25b1ce4f9ede0f093bee3e6cb",
"0x1e8e34d095df1eb92444afc3f89b848905b8c2ac63d3805af088e67ff695d5c8",
"0x187eb13c7f95499b8ebaa0c5100fbacb1184a61e62ca9be6601c3af34c0d0804",
"0x269000bab546cb9f4e54adc5adb3b08f6f45bb19114977cced6e5035b605e4cc",
"0x1a4273c2ff4b80a91443e25d1f0ad568ba4586cdb8bd9e412be1fa40ef2f10a2",
"0x0b2c26399060c182a27682869690bd61c9395795349b873b16ceceed98ccdb0f",
"0x187370c642e5fd783fba4b7cc7bf03341f6b8efd23fe8c82cf7b627f91bedeb2",
"0x1162e4855ebcea47475ef6016b2129f42c06dd2262eee9f43e5bdb024cb3e3ab",
"0x1cb4e22d4b8bfd114320b70e2edc8ec4d077820dc7caaaf3983e0791f77c5afd",
"0x0b9246a297596e5b285d111c1da4dec37a96a56fe1f3532d45b51cd06da11582",
"0x06b14752752ad07b43a8daa7963c3c0d9a522671c61f49e7aaa77373839a3ca3",
"0x21fb7f7798350e11d807e4bac95162f8cbba7f5528f030f22682de559952b444",
"0x26eaf07e3bb2ad298141174e39808d12d3e8359624d57dcd4bd40d517c889f41",
"0x1bc988e5a7e158d7367f959b6d877986fb0696e1e9c1f1a59462086d1b4a4a9d",
"0x1665b29cab9b55ffc5bf2376609265ed9a8f6b8b607636df26ce4f2bc3a6ae56",
"0x27b2623f1a2a2d769759232e2cff279d0916efd69efb8c8392a402192e4469a5",
"0x0b11a77df9412a21a871a117cb027da0f8af823131f60add22ed9c4a2928f332",
"0x1ce9f86e393b0e2d0ddf1270803c496284ded0b35f69972031a5ceaa360c5af4",
"0x2c97533771428606f2bb3d8cc740ee47c66018fe54fecc8b567483befaa3d898",
"0x1a257215c9ffb1465ec62562d98025bf33a23fcbb683f89d53a118d060c11cf8",
"0x25fd8cfe274fe98e6e3ae98aaaab03ade4d1c56cef810df237e42d324184d86d",
"0x286cea2aeabf040c9bf2160ce8ca90ac489f0098982d790fb42ab33345cfcfe7",
"0x124c35aa339e0ee2c2046b2f5f0367ce4eedfeb8e3c6c94b7f6460dee9e51099",
"0x1665dee3f142dbe8f44d85e4d93b39fbf1c86e7a797a8d55932d81a3efa516a4",
"0x12cc10508db3a8b2f2c53afe91252ddf4bbcf5e4e2738fa8e699edb9fa3df62c",
"0x1ef850e8b97b2c0560843986acfff158d75aa9210acc6420e9650b56dd9b3c4b",
"0x2afe8e7f5b4525a1c015f8ace5dd35e62cf89e2232b90eb3eb011d082a114a37",
"0x2e9c398649994f32c3cd610bc6546bc05aab563fbba41d3124e255ff45e1c940",
"0x03b21b85b77588506db2fc108bd0cf2c03f6c0653020f46d939d8194ea1e716b",
"0x2e43508dd63e40681c9122d482d7900ebad01b9392e6c1611019e43cbc5455b8",
"0x113febd0e87001dda480a8c347f8a368c00740a25ee2d8d36c0608500bec6f2f",
"0x23cfec0d834aadca55bfe515af80e59183c1b24ea600cf7cde863df02fc859fc",
"0x1cbb1f36a1e7bc45c29ed8922599374d57010887420c91ecfa8727ad51df9b21",
"0x1c2a24adf0e0c5254eb4c834e252a04758e84181cfd1a163dc7089337c4eba52",
"0x2b7a7d74ea33c98f3b45bae98a2498ad5d316a43cfd40e8be9e1c5fd901f5bd8",
"0x1edb94d38964f284b41136812bd52c7679b1e1a3ce3b3a1354b1417b9012ec4b",
"0x2c2bad47394f3068c8b996c4859a22dd65460292fef9c250a5a9da8e0628d534",
"0x0b140b193aab84f6235a88b862ce4275746d5cac940fc494aef23d2279e8a353",
"0x15673d3dd92656dd60513676f7814459619a09681ee4ab63dd8ff3407a547846",
"0x2180ff0b613f8cce937068fa4a77a0f97865c4aed76483cb1fe09227517ba888",
"0x1048b70290f52d668ee6b98950b3e904fee8c844428919300a8945c0fe3e7280",
"0x0326df120ad22e946c41f475b7702dae0dd42a4387a8702c8e954aca640b2c79",
"0x2fc77a73fdbaaa22e2fc521f72f9ce5cef4857f58001409898d52c5e5b1723db",
"0x14938b2b6259f02791cccd157d789c2de68cdad27dc55aa08b9b90ec13dbfd79",
"0x0493187bf26d38b13ca04c712b42778f8618e6f7d9f9dd52bd4da96e085c7a78",
"0x1d40769876c58db37289e371fef2ffa559c95630dee045cde6e18370d2ceb561",
"0x03e7e9b8084366995f7a2f5732349b1139726536b378d78772eabb302705d204",
"0x06147e6e152d7d58f4cf01e05ae0f024607b8b7c3770bd5b7f3a54e048c30a17",
"0x2e49300214c5a0a7a6ebbbc8c48cc323be26d42e98e5bbbb0e2a10ecf4fe40fe",
"0x051c8240e8907e776279e7c66cdbdf39c9516f39ae61883185fac1ef5c64bbba",
"0x2c737904e8f8e845bf132de2b3be5d638993a9987d0e8003022f08bf6633a5bd",
"0x07825bfc67f5658bb5a3b1a26c8ad00f657b54a4a1a679ee37df11bed2ba219d",
"0x1c0e4d8b013541963f8e04667f13e6a60fafebb9bceca823d4054a7a63f8b569",
"0x1083d7cd5a11e3d3dba85745de17ea4abec8a2790003f39f1b1262521380d4b6",
"0x0e14bed1525102ddc1d3c17478ab0c2d4cdbfa67f5ef1a568642984665b4dad2",
"0x1d0c3a89fcc0171b7977f8f20bad9cfae37507a2038d3165d764632461745760",
"0x03162758d9df43281331905c161ed977e240f4a0c9cdd3f3f18a3b0592c3e67e",
"0x0fe5ec0343e9832d8a4c7c1bee1d73decc0661a27c527bec309561fda95a529a",
"0x0ddd28a35af3aced48f61c6558c5c4a72690975c2fc948feec51e1a53a6be5e7",
"0x2318c886ea334e72e9833e3b0bc9868e51843b8b63e0fa3d814540ad7f5d0359",
"0x0d5786dec1685237e3d171eb298a36a475c83c0651a450227d261d78260bab70",
"0x152282540da509e8ab8abcf010d3bd8f29d1c2c60454ffda67ca732db024f3ec",
"0x1b7f4ec7b4c7a593efd5f53ef204e642bb16fb9298a6ffbd1767183170822ad2",
"0x19e02df6f343636868908d644e9a2f767bb9fa9c13756669cb1d805898d949c0",
"0x115d3fa50f1ea1f76b4641586e954be25d7428ad21f5fea76b5889a3f4923ab6",
"0x059db78b0146183e8e6e0829bad801fcb4a0c4e6a8872cb3a5a497118dd29f2c",
"0x0e6441f0174ebe123449b9072472442e03c2f72a29c474d514e4dbb72c23bce1",
"0x2c5302069d7b3b9638a3ea52e5530059155d706af30df469ab929fa1c954efa6",
"0x181a99f989f2f853ae7db14bef800710a05ddc26ed65cd5e1588150864565829",
"0x248a2275485f8946848f0d9433ee1cf6501bbfa8f9404341ef81a9c4b128db3a",
"0x081fa1eb11e0e5198e7135c533688ad0b4e438773b9d99a610ece3dd414845ad",
"0x17b1a8626b79093deb27cfa548da7bf8499e71928d9433a7243037d493c08b53",
"0x0af8f7fc8f0ba49245ae28cfbb7b86bdf3f38b4229981b42ad8ba4af993ae5d8",
"0x19da094b62046661682693af49d35d72a055555b0b2f1a717ef61a0fbdc90169",
"0x287b1755734c8e691d9651ff53f3bae296bc16d33713bf32457869e3650dbc9e",
"0x26501a99afdb95154415e3de32b0d4790ff228ee94577537608d30d85a3349d0",
"0x0c7ca2af6c86f460df0b20ccb30b2a3395f2dabaf7f970f1e1955a1166e0460b",
"0x141cffa13da7885f34ff295561b5d2da8c5b785932ebcd7039752c0dd1cc08a5",
"0x188f478690e359cc0b468d095b37f314c53a5873054cbdb5eb4cde9b97d8c837",
"0x2daafa58220bc8ab507118fb29b65e48e6d8d3ad20d6fa24d57b8a90e21530d6",
"0x1c8eaf137b6310715fc0881b8a080e9391a0217e8e3980ccc3fbc6423ae10f1b",
"0x018864151eb108a9115379b3d3ec902aa961f1b846490266855ab48077487948",
"0x16a426c1847543857385ef8ed03325a50d5cbeff1ac61ef3b710099ab8be88ae",
"0x13d7ed015205feee9d09307b193811ea89b22bf4ecb3e8dcb951ff1e86ea1dbb",
"0x2b35afa98d5c3da62ae05e0e3ec587eacbd195fa3405260ce2b910cb198acf5f"
]
],
"M": [
[
[
"0x028540ffcb050250186bb64a9b6e6d0eaf493d2c72701392fa8de7dbd371fad4",
"0x1afa3a02008d8eab18725ff780b7f310156ddef81579367ae944478644e6367e"
],
[
"0x00b0cad1d2259f1f6dd07b4e5674057f531b5ce316f741437137b7615caf9fb0",
"0x1378798a617a99c07cd850cb3daab0a1b20cb2fe9125133ae092132a071eeffe"
]
],
[
[
"0x142d76a5176d04542cc86c20ad276af0f1c4b85a08f5c7fb7076c37bee91b0b0",
"0x1f020db9ae14abc9448d91922ce7e8a4b751468b692082ac74d4db30f9a20cbd",
"0x02f57e7420298b689cc5932b434d659054d7e9e1a28ce342a357d28d3d0e7ce6"
],
[
"0x0cc8c6aa7aa0f7a0191f236aad3b994b4e6d2671ef5cddef7395a663f18a82b6",
"0x132d968e1372659c4b77528bec8b46830564bbb1ef44e828966a07578b52db1e",
"0x2e7a166a1b7e646c9f9e04f451e541b3eb516fbad05901b4f37e7dd402a501de"
],
[
"0x0411c26273e6ac2f2b7ef6da84499413605b6099bda4254a31ab3bac526a1581",
"0x1e9d5cd096fd315de38e6e2490b8e9c406f954ba63a8be9f11756780af6315f1",
"0x198dfceb06c35ab9162320e55b68a7d160ac9caf74ff1098d62b4cd86823e74c"
]
],
[
[
"0x055042fce3759fd347470105116d64130f5cb362e345d7651c377a63f1c73f81",
"0x2ce35792e15aa0836ab5089a71903eb626bfe7fd6a460cb2f9d93f338b1c93a8",
"0x123324a5430d1e324553566a662bab9bd5b78bc183829124d3407352f3399a44",
"0x014b3af716655fd79b921fb8aba95bf4033d91eefddba964c6813b194ec2e92b"
],
[
"0x00f7a1e3ee734053ac96e44087e97819d5289c2e002339ed649d14df4416c664",
"0x158586db6e410642a1e221f5d80a482cc6ba3cfbe51a38502987db8c42d53bea",
"0x1607fd8dcba9cecf99fa9f882b7bf67c9bdf121aef9843d5d47301d812d23406",
"0x02afb3d945a884974edcf2b2ea59422bfbfb98ba0ea6ae232a2fbf2a98fce73c"
],
[
"0x1303c19d840c01975ac5f417c7d797c84e32937e82c3267a8a5abf86c2adc2dc",
"0x0dfbb78b621ce3f17ea1fca649c7fdf8936872b335d86c5f3ac83072f2b0804e",
"0x0c6d9cca76d73644645d39f6da45e32a5784eb278da4ba346226e3503767c559",
"0x271868e3480e8509ee5b7d057e0e85677220d4751c1475c8a07c578584dba071"
],
[
"0x1ce85b8925fef3258cf52dd26ea5dbe2616118a051fad03b174c55e6bf25c193",
"0x10a902db55c0d71628c51efcb7f01c28e3e60833c254e68d38833c0b577e7bf8",
"0x24afc938e9d8abe5f4cc11f1388ab83460681a00dced6ccd170860e03508ca5c",
"0x297a43fb5e3fefcf3ccabaacf30e9171e4fb359ab66c6ebc8bd6654bd387ab1b"
]
],
[
[
"0x098df2176f14c72d9ef76d268c6526704b2dce0d2ab0bf0d0b6506c598a12e39",
"0x1ee4a90d3dc9864851e9cefb41c3e19218f7ec9b97283b8781d74a9260a9b182",
"0x090becc1ca85079c519e9519456d0613c4dea08dc17ce3d3ac24c51780bbe653",
"0x24510d25f0893ebc56cb6d302b08ebc1fe23a842483a1cf105efccdb8f6623be",
"0x1836f551337cc92e446cda258313ddb9a1291f822c2120d3765f5bb29bccd044"
],
[
"0x235a03a1f31060c62a1bb1b6cbce38317dcf3501e3f0b3d92b4b01a070ee58b2",
"0x1b0481c924c00fd4b7809ff4a9f9daa7f12efea4821078b869159d34e7c9caca",
"0x2f1ced49ea067ad0f3a22b51ad12da2d7b0280f3f50977f9b09d4bea92e6b34e",
"0x28f301e64ff54c671bb7a9fc672a420e3af0382c71af2aec84d1b26d19bd01ee",
"0x05c29dff5d6ae85f7bc09637a86134c63a8052d1905a8057449cc7d92658f24d"
],
[
"0x2885788b4255180581aac93d5313e7489efc386deceaf13050ebcb8cdddff5fa",
"0x2a7f03d4b0954a37f9a33ebd9117e2c4cfaa3978e5f221a30db56a7403572a3c",
"0x291093f3d5182756f267566140d2d8f5356be8408b40ead3748484267f1e90cb",
"0x29ecfb524f4135deb55d9d9eb02839dedda189c17726aeef96019b205c8aab53",
"0x1650d221980ec72736322d9fa404a0fe6bea3d8530b71c9522096e455be52379"
],
[
"0x10d08ba1c37b79a36c9d3c9a3d8fd2ff41f2445e7d71dd5ede6f45987e5e1044",
"0x1eaa7441754632ffae99c9e2f2264c1bc89551e7bbf2c889d92af30bef70e817",
"0x062101fedd4ecff781f529f57f45e8b479b03d86a11acf549c6555a1293c70b3",
"0x1c1ec7db63405475e844b5cb6215d9e2919e903a7387721db150c9977a1818b5",
"0x0b5ca51ebe8fd98da6e8f4a4465e19dd210bf59e0841f50fcf0f06e43d83ce1f"
],
[
"0x0143b223ed92a0b426f8f2886cda3d8fdb565eb6acb4841897489e14cbc943a8",
"0x017f82dcfdf078265df4cfa1d9d79aeec0fee433eebc489a875785b99dc8832a",
"0x0013ae98ed23af18461bcde9ff99728edeec173e63c5467a209c2a34b503dc72",
"0x0e120df26061ea797bba1f6153995de0090ddb744ad23bfcdf1ecc28a9b18338",
"0x0233c1411c8cb5ff0d33e20a65bfd9c0347deb9a12a50e55fb01a40248ccc366"
]
]
]
}

View File

@ -2,36 +2,36 @@
// License: LGPL-3.0+ // License: LGPL-3.0+
// //
const Poseidon = require("./poseidon.js");
const Contract = require("./evmasm"); const Contract = require("./evmasm");
const { unstringifyBigInts } = require("@tornado/snarkjs");
const Web3Utils = require("web3-utils");
const SEED = "poseidon"; const { C: K, M } = unstringifyBigInts(require("./poseidon_constants.json"));
const NROUNDSF = 8;
const NROUNDSP = 57; const N_ROUNDS_F = 8;
const T = 6; const N_ROUNDS_P = 35;
function toHex256(a) { function toHex256(a) {
if (typeof a === "string" && a.startsWith("0x")) {
return a;
}
let S = a.toString(16); let S = a.toString(16);
while (S.length < 64) S = "0" + S; while (S.length < 64) S = "0" + S;
return "0x" + S; return "0x" + S;
} }
function createCode(t, nRoundsF, nRoundsP, seed) { function createCode(nInputs) {
if (typeof seed === "undefined") seed = SEED; if (nInputs < 1 || nInputs > 4) throw new Error("Invalid number of inputs. Must be 1<=nInputs<=8");
if (typeof nRoundsF === "undefined") nRoundsF = NROUNDSF; const t = nInputs + 1;
if (typeof nRoundsP === "undefined") nRoundsP = NROUNDSP; const nRoundsF = N_ROUNDS_F;
if (typeof t === "undefined") t = T; const nRoundsP = N_ROUNDS_P;
const K = Poseidon.getConstants(t, seed, nRoundsP + nRoundsF);
const M = Poseidon.getMatrix(t, seed, nRoundsP + nRoundsF);
const C = new Contract(); const C = new Contract();
function saveM() { function saveM() {
for (let i = 0; i < t; i++) { for (let i = 0; i < t; i++) {
for (let j = 0; j < t; j++) { 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.push((1 + i * t + j) * 32);
C.mstore(); C.mstore();
} }
@ -39,16 +39,15 @@ function createCode(t, nRoundsF, nRoundsP, seed) {
} }
function ark(r) { function ark(r) {
C.push(toHex256(K[r])); // K, st, q // st, q
for (let i = 0; i < t; i++) { for (let i = 0; i < t; i++) {
C.dup(1+t); // q, K, st, q C.dup(t); // q, st, q
C.dup(1); // K, q, K, st, q C.push(toHex256(K[t - 2][r * t + i])); // K, q, st, q
C.dup(3+i); // st[i], K, q, K, st, q C.dup(2 + i); // st[i], K, q, st, q
C.addmod(); // newSt[i], K, st, q C.addmod(); // newSt[i], st, q
C.swap(2 + i); // xx, K, st, q C.swap(1 + i); // xx, st, q
C.pop(); C.pop();
} }
C.pop();
} }
function sigma(p) { function sigma(p) {
@ -90,7 +89,7 @@ function createCode(t, nRoundsF, nRoundsP, seed) {
} }
} }
for (let i = 0; i < t; i++) { for (let i = 0; i < t; i++) {
C.swap((t -i) + (t -i-1)); C.swap(t - i + (t - i - 1));
C.pop(); C.pop();
} }
C.push(0); C.push(0);
@ -98,14 +97,18 @@ function createCode(t, nRoundsF, nRoundsP, seed) {
C.jmp(); C.jmp();
} }
// Check selector // Check selector
C.push("0x0100000000000000000000000000000000000000000000000000000000"); C.push("0x0100000000000000000000000000000000000000000000000000000000");
C.push(0); C.push(0);
C.calldataload(); C.calldataload();
C.div(); 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.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.jmpi("start");
C.invalid(); C.invalid();
@ -115,19 +118,18 @@ function createCode(t, nRoundsF, nRoundsP, seed) {
C.push("0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"); // q 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 // The function has a single array param param
// [Selector (4)] [Pointer (32)][Length (32)] [data1 (32)] .... // [Selector (4)] [item1 (32)] [item2 (32)] ....
// We ignore the pointer and the length and just load 6 values to the state // Stack positions 0-nInputs.
// (Stack positions 0-5) If the array is shorter, we just set zeros.
for (let i = 0; i < t; i++) { for (let i = 0; i < t; i++) {
C.push(0x44+(0x20*(5-i))); C.push(0x04 + 0x20 * (nInputs - i));
C.calldataload(); C.calldataload();
} }
for (let i=0; i<nRoundsF+nRoundsP; i++) { for (let i = 0; i < nRoundsF + nRoundsP - 1; i++) {
ark(i); ark(i);
if ((i<nRoundsF/2) || (i>=nRoundsP+nRoundsF/2)) { if (i < nRoundsF / 2 || i >= nRoundsP + nRoundsF / 2) {
for (let j = 0; j < t; j++) { for (let j = 0; j < t; j++) {
sigma(j); sigma(j);
} }
@ -142,6 +144,13 @@ function createCode(t, nRoundsF, nRoundsP, seed) {
C.label(strLabel); 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.push("0x00");
C.mstore(); // Save it to pos 0; C.mstore(); // Save it to pos 0;
C.push("0x20"); C.push("0x20");
@ -153,28 +162,52 @@ function createCode(t, nRoundsF, nRoundsP, seed) {
return C.createTxData(); return C.createTxData();
} }
module.exports.abi = [ function generateABI(nInputs) {
return [
{ {
"constant": true, constant: true,
"inputs": [ inputs: [
{ {
"name": "input", internalType: `bytes32[${nInputs}]`,
"type": "uint256[]" name: "input",
} type: `bytes32[${nInputs}]`,
},
], ],
"name": "poseidon", name: "poseidon",
"outputs": [ outputs: [
{ {
"name": "", internalType: "bytes32",
"type": "uint256" name: "",
} type: "bytes32",
},
], ],
"payable": false, payable: false,
"stateMutability": "pure", stateMutability: "pure",
"type": "function" type: "function",
} },
{
constant: true,
inputs: [
{
internalType: `uint256[${nInputs}]`,
name: "input",
type: `uint256[${nInputs}]`,
},
],
name: "poseidon",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256",
},
],
payable: false,
stateMutability: "pure",
type: "function",
},
]; ];
}
module.exports.generateABI = generateABI;
module.exports.createCode = createCode; 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"); 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,17 +1,15 @@
const bigInt = require("snarkjs").bigInt; const bigInt = require("@tornado/snarkjs").bigInt;
const SMTMemDB = require("./smt_memdb"); const SMTMemDB = require("./smt_memdb");
const { hash0, hash1 } = require("./smt_hashes_poseidon"); const { hash0, hash1 } = require("./smt_hashes_poseidon");
class SMT { class SMT {
constructor(db, root) { constructor(db, root) {
this.db = db; this.db = db;
this.root = root; this.root = root;
} }
_splitBits(_key) { _splitBits(_key) {
let k = bigInt(_key); let k = bigInt(_key);
const res = []; const res = [];
@ -33,7 +31,6 @@ class SMT {
const key = bigInt(_key); const key = bigInt(_key);
const newValue = bigInt(_newValue); const newValue = bigInt(_newValue);
const resFind = await this.find(key); const resFind = await this.find(key);
const res = {}; const res = {};
res.oldRoot = this.root; res.oldRoot = this.root;
@ -87,7 +84,7 @@ class SMT {
const res = { const res = {
siblings: [], siblings: [],
delKey: key, delKey: key,
delValue: resFind.foundValue delValue: resFind.foundValue,
}; };
const dels = []; const dels = [];
@ -99,7 +96,7 @@ class SMT {
let mixed; let mixed;
if (resFind.siblings.length > 0) { if (resFind.siblings.length > 0) {
const record = await this.db.get(resFind.siblings[resFind.siblings.length - 1]); 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 && record[0].equals(bigInt.one)) {
mixed = false; mixed = false;
res.oldKey = record[1]; res.oldKey = record[1];
res.oldValue = record[2]; res.oldValue = record[2];
@ -125,7 +122,7 @@ class SMT {
for (let level = resFind.siblings.length - 1; level >= 0; level--) { for (let level = resFind.siblings.length - 1; level >= 0; level--) {
let newSibling = resFind.siblings[level]; let newSibling = resFind.siblings[level];
if ((level == resFind.siblings.length-1)&&(!res.isOld0)) { if (level == resFind.siblings.length - 1 && !res.isOld0) {
newSibling = bigInt.zero; newSibling = bigInt.zero;
} }
const oldSibling = resFind.siblings[level]; const oldSibling = resFind.siblings[level];
@ -201,7 +198,7 @@ class SMT {
inserts.push([rt, [1, key, value]]); inserts.push([rt, [1, key, value]]);
for (let i = res.siblings.length - 1; i >= 0; i--) { 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 && !res.siblings[i].isZero()) {
mixed = true; mixed = true;
} }
if (mixed) { if (mixed) {
@ -214,7 +211,6 @@ class SMT {
dels.push(rtOld); dels.push(rtOld);
} }
let newRt; let newRt;
if (newKeyBits[i]) { if (newKeyBits[i]) {
newRt = hash0(res.siblings[i], rt); newRt = hash0(res.siblings[i], rt);
@ -227,7 +223,7 @@ class SMT {
} }
if (addedOne) res.siblings.pop(); if (addedOne) res.siblings.pop();
while ((res.siblings.length>0) && (res.siblings[res.siblings.length-1].isZero())) { while (res.siblings.length > 0 && res.siblings[res.siblings.length - 1].isZero()) {
res.siblings.pop(); res.siblings.pop();
} }
res.oldKey = resFind.notFoundKey; res.oldKey = resFind.notFoundKey;
@ -235,7 +231,6 @@ class SMT {
res.newRoot = rt; res.newRoot = rt;
res.isOld0 = resFind.isOld0; res.isOld0 = resFind.isOld0;
await this.db.multiIns(inserts); await this.db.multiIns(inserts);
await this.db.setRoot(rt); await this.db.setRoot(rt);
this.root = rt; this.root = rt;
@ -259,20 +254,20 @@ class SMT {
siblings: [], siblings: [],
notFoundKey: key, notFoundKey: key,
notFoundValue: bigInt.zero, notFoundValue: bigInt.zero,
isOld0: true isOld0: true,
}; };
return res; return res;
} }
const record = await this.db.get(root); const record = await this.db.get(root);
if ((record.length==3)&&(record[0].equals(bigInt.one))) { if (record.length == 3 && record[0].equals(bigInt.one)) {
if (record[1].equals(key)) { if (record[1].equals(key)) {
res = { res = {
found: true, found: true,
siblings: [], siblings: [],
foundValue: record[2], foundValue: record[2],
isOld0: false isOld0: false,
}; };
} else { } else {
res = { res = {
@ -280,7 +275,7 @@ class SMT {
siblings: [], siblings: [],
notFoundKey: record[1], notFoundKey: record[1],
notFoundValue: record[2], notFoundValue: record[2],
isOld0: false isOld0: false,
}; };
} }
} else { } else {
@ -296,9 +291,7 @@ class SMT {
} }
} }
async function loadFromFile(fileName) { async function loadFromFile(fileName) {}
}
async function newMemEmptyTrie() { async function newMemEmptyTrie() {
const db = new SMTMemDB(); const db = new SMTMemDB();

View File

@ -1,5 +1,5 @@
const mimc7 = require("./mimc7"); const mimc7 = require("./mimc7");
const bigInt = require("snarkjs").bigInt; const bigInt = require("@tornado/snarkjs").bigInt;
exports.hash0 = function (left, right) { exports.hash0 = function (left, right) {
return mimc7.multiHash(left, right); return mimc7.multiHash(left, right);

View File

@ -1,12 +1,10 @@
const Poseidon = require("./poseidon"); const poseidon = require("./poseidon");
const bigInt = require("snarkjs").bigInt; const bigInt = require("@tornado/snarkjs").bigInt;
const hash = Poseidon.createHash(6, 8, 57);
exports.hash0 = function (left, right) { exports.hash0 = function (left, right) {
return hash([left, right]); return poseidon([left, right]);
}; };
exports.hash1 = function (key, value) { exports.hash1 = function (key, value) {
return hash([key, value, bigInt.one]); return poseidon([key, value, bigInt.one]);
}; };

View File

@ -1,4 +1,4 @@
const bigInt = require("snarkjs").bigInt; const bigInt = require("@tornado/snarkjs").bigInt;
class SMTMemDb { class SMTMemDb {
constructor() { constructor() {
@ -27,6 +27,14 @@ class SMTMemDb {
return this.nodes[keyS]; 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) { async setRoot(rt) {
this.root = rt; this.root = rt;
} }

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
const assert = chai.assert; const assert = chai.assert;
@ -56,19 +56,19 @@ describe("Aliascheck test", () => {
circuit.calculateWitness({ in: inp }); circuit.calculateWitness({ in: inp });
assert(false); assert(false);
} catch (err) { } catch (err) {
assert.equal(err.message, "Constraint doesn't match: 1 != 0"); assert(/Constraint\sdoesn't\smatch(.*)1\s!=\s0/.test(err.message));
assert(err.message.indexOf("1 != 0") >= 0);
} }
}); });
it("Nhot not satisfy all ones", async () => { it("Nhot not satisfy all ones", async () => {
const inp = getBits(bigInt(1).shl(254).sub(bigInt(1)), 254); const inp = getBits(bigInt(1).shl(254).sub(bigInt(1)), 254);
try { try {
circuit.calculateWitness({ in: inp }); circuit.calculateWitness({ in: inp });
assert(false); assert(false);
} catch (err) { } catch (err) {
assert.equal(err.message, "Constraint doesn't match: 1 != 0"); assert(/Constraint\sdoesn't\smatch(.*)1\s!=\s0/.test(err.message));
assert(err.message.indexOf("1 != 0") >= 0);
} }
}); });
}); });

74
test/aliascheckbabyjub.js Normal file
View File

@ -0,0 +1,74 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom");
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
function print(circuit, w, s) {
console.log(s + ": " + w[circuit.getSignalIdx(s)]);
}
function getBits(v, n) {
const res = [];
for (let i = 0; i < n; i++) {
if (v.shr(i).isOdd()) {
res.push(bigInt.one);
} else {
res.push(bigInt.zero);
}
}
return res;
}
const r = bigInt("2736030358979909402780800718157159386076813972158567259200215660948447373041");
describe("Aliascheck test", () => {
let circuit;
before(async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "aliascheckbabyjub_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains: " + circuit.nConstraints);
});
it("Satisfy the aliastest 0", async () => {
const inp = getBits(bigInt.zero, 251);
circuit.calculateWitness({ in: inp });
});
it("Satisfy the aliastest 3", async () => {
const inp = getBits(bigInt(3), 251);
circuit.calculateWitness({ in: inp });
});
it("Satisfy the aliastest r-1", async () => {
const inp = getBits(r.sub(bigInt.one), 251);
circuit.calculateWitness({ in: inp });
});
it("Nhot not satisfy an input of r", async () => {
const inp = getBits(r, 251);
try {
circuit.calculateWitness({ in: inp });
assert(false);
} catch (err) {
assert(err.message.indexOf("Constraint doesn't match") >= 0);
assert(err.message.indexOf("1 != 0") >= 0);
}
});
it("Nhot not satisfy all ones", async () => {
const inp = getBits(bigInt(1).shl(251).sub(bigInt(1)), 251);
try {
circuit.calculateWitness({ in: inp });
assert(false);
} catch (err) {
assert(err.message.indexOf("Constraint doesn't match") >= 0);
assert(err.message.indexOf("1 != 0") >= 0);
}
});
});

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
const createBlakeHash = require("blake-hash"); const createBlakeHash = require("blake-hash");
@ -8,7 +8,7 @@ const eddsa = require("../src/eddsa.js");
const assert = chai.assert; const assert = chai.assert;
const bigInt = require("snarkjs").bigInt; const bigInt = require("@tornado/snarkjs").bigInt;
describe("Baby Jub test", function () { describe("Baby Jub test", function () {
let circuitAdd; let circuitAdd;
@ -28,16 +28,14 @@ describe("Baby Jub test", function () {
const cirDefPbk = await compiler(path.join(__dirname, "circuits", "babypbk_test.circom")); const cirDefPbk = await compiler(path.join(__dirname, "circuits", "babypbk_test.circom"));
circuitPbk = new snarkjs.Circuit(cirDefPbk); circuitPbk = new snarkjs.Circuit(cirDefPbk);
console.log("NConstrains BabyPbk: " + circuitPbk.nConstraints); console.log("NConstrains BabyPbk: " + circuitPbk.nConstraints);
}); });
it("Should add point (0,1) and (0,1)", async () => { it("Should add point (0,1) and (0,1)", async () => {
const input = { const input = {
x1: snarkjs.bigInt(0), x1: snarkjs.bigInt(0),
y1: snarkjs.bigInt(1), y1: snarkjs.bigInt(1),
x2: snarkjs.bigInt(0), x2: snarkjs.bigInt(0),
y2: snarkjs.bigInt(1) y2: snarkjs.bigInt(1),
}; };
const w = circuitAdd.calculateWitness(input); const w = circuitAdd.calculateWitness(input);
@ -50,12 +48,11 @@ describe("Baby Jub test", function () {
}); });
it("Should add 2 same numbers", async () => { it("Should add 2 same numbers", async () => {
const input = { const input = {
x1: snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"), x1: snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
y1: snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"), y1: snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
x2: snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"), x2: snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
y2: snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475") y2: snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
}; };
const w = circuitAdd.calculateWitness(input); const w = circuitAdd.calculateWitness(input);
@ -68,12 +65,11 @@ describe("Baby Jub test", function () {
}); });
it("Should add 2 different numbers", async () => { it("Should add 2 different numbers", async () => {
const input = { const input = {
x1: snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"), x1: snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
y1: snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"), y1: snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
x2: snarkjs.bigInt("16540640123574156134436876038791482806971768689494387082833631921987005038935"), x2: snarkjs.bigInt("16540640123574156134436876038791482806971768689494387082833631921987005038935"),
y2: snarkjs.bigInt("20819045374670962167435360035096875258406992893633759881276124905556507972311") y2: snarkjs.bigInt("20819045374670962167435360035096875258406992893633759881276124905556507972311"),
}; };
const w = circuitAdd.calculateWitness(input); const w = circuitAdd.calculateWitness(input);
@ -100,12 +96,12 @@ describe("Baby Jub test", function () {
circuitTest.calculateWitness({ x: 1, y: 0 }); circuitTest.calculateWitness({ x: 1, y: 0 });
assert(false, "Should be a valid point"); assert(false, "Should be a valid point");
} catch (err) { } catch (err) {
assert.equal(err.message, "Constraint doesn't match: 168700 != 1"); assert(/Constraint\sdoesn't\smatch(.*)168700\s!=\s1/.test(err.message));
assert(err.message.indexOf("168700 != 1") >= 0);
} }
}); });
it("Should extract the public key from the private one", async () => { it("Should extract the public key from the private one", async () => {
const rawpvk = Buffer.from("0001020304050607080900010203040506070809000102030405060708090021", "hex"); const rawpvk = Buffer.from("0001020304050607080900010203040506070809000102030405060708090021", "hex");
const pvk = eddsa.pruneBuffer(createBlakeHash("blake512").update(rawpvk).digest().slice(0, 32)); const pvk = eddsa.pruneBuffer(createBlakeHash("blake512").update(rawpvk).digest().slice(0, 32));
const S = bigInt.leBuff2int(pvk).shr(3); const S = bigInt.leBuff2int(pvk).shr(3);
@ -115,11 +111,10 @@ describe("Baby Jub test", function () {
const input = { const input = {
in: S, in: S,
Ax: A[0], Ax: A[0],
Ay : A[1] Ay: A[1],
} };
const w = circuitPbk.calculateWitness(input); const w = circuitPbk.calculateWitness(input);
assert(circuitPbk.checkWitness(w)); assert(circuitPbk.checkWitness(w));
}); });
}); });

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
const babyjub = require("../src/babyjub.js"); const babyjub = require("../src/babyjub.js");
@ -8,22 +8,14 @@ const assert = chai.assert;
// const bigInt = require("big-integer"); // const bigInt = require("big-integer");
describe("Baby Jub js test", function () { describe("Baby Jub js test", function () {
this.timeout(100000); this.timeout(100000);
it("Should add point (0,1) and (0,1)", () => { it("Should add point (0,1) and (0,1)", () => {
const p1 = [snarkjs.bigInt(0), snarkjs.bigInt(1)];
const p2 = [snarkjs.bigInt(0), snarkjs.bigInt(1)];
const p1 = [ const out = babyjub.addPoint(p1, p2);
snarkjs.bigInt(0),
snarkjs.bigInt(1)];
const p2 = [
snarkjs.bigInt(0),
snarkjs.bigInt(1)
];
const out = babyjub.addPoint(p1, p2)
assert(out[0].equals(0)); assert(out[0].equals(0));
assert(out[1].equals(1)); assert(out[1].equals(1));
}); });
@ -39,7 +31,6 @@ describe("Baby Jub js test", function () {
}); });
it("Should add 2 same numbers", () => { it("Should add 2 same numbers", () => {
const p1 = [ const p1 = [
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"), snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"), snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
@ -49,13 +40,12 @@ describe("Baby Jub js test", function () {
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"), snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
]; ];
const out = babyjub.addPoint(p1, p2) const out = babyjub.addPoint(p1, p2);
assert(out[0].equals(snarkjs.bigInt("6890855772600357754907169075114257697580319025794532037257385534741338397365"))); assert(out[0].equals(snarkjs.bigInt("6890855772600357754907169075114257697580319025794532037257385534741338397365")));
assert(out[1].equals(snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889"))); assert(out[1].equals(snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889")));
}); });
it("Should add 2 different numbers", () => { it("Should add 2 different numbers", () => {
const p1 = [ const p1 = [
snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"), snarkjs.bigInt("17777552123799933955779906779655732241715742912184938656739573121738514868268"),
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"), snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
@ -65,7 +55,7 @@ describe("Baby Jub js test", function () {
snarkjs.bigInt("20819045374670962167435360035096875258406992893633759881276124905556507972311"), snarkjs.bigInt("20819045374670962167435360035096875258406992893633759881276124905556507972311"),
]; ];
const out = babyjub.addPoint(p1, p2) const out = babyjub.addPoint(p1, p2);
assert(out[0].equals(snarkjs.bigInt("7916061937171219682591368294088513039687205273691143098332585753343424131937"))); assert(out[0].equals(snarkjs.bigInt("7916061937171219682591368294088513039687205273691143098332585753343424131937")));
assert(out[1].equals(snarkjs.bigInt("14035240266687799601661095864649209771790948434046947201833777492504781204499"))); assert(out[1].equals(snarkjs.bigInt("14035240266687799601661095864649209771790948434046947201833777492504781204499")));
@ -92,7 +82,10 @@ describe("Baby Jub js test", function () {
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"), snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
]; ];
const r = babyjub.mulPointEscalar(p, snarkjs.bigInt("14035240266687799601661095864649209771790948434046947201833777492504781204499")); const r = babyjub.mulPointEscalar(
p,
snarkjs.bigInt("14035240266687799601661095864649209771790948434046947201833777492504781204499")
);
assert.equal(r[0].toString(), "17070357974431721403481313912716834497662307308519659060910483826664480189605"); assert.equal(r[0].toString(), "17070357974431721403481313912716834497662307308519659060910483826664480189605");
assert.equal(r[1].toString(), "4014745322800118607127020275658861516666525056516280575712425373174125159339"); assert.equal(r[1].toString(), "4014745322800118607127020275658861516666525056516280575712425373174125159339");
}); });
@ -103,7 +96,10 @@ describe("Baby Jub js test", function () {
snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889"), snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889"),
]; ];
const r = babyjub.mulPointEscalar(p, snarkjs.bigInt("20819045374670962167435360035096875258406992893633759881276124905556507972311")); const r = babyjub.mulPointEscalar(
p,
snarkjs.bigInt("20819045374670962167435360035096875258406992893633759881276124905556507972311")
);
assert.equal(r[0].toString(), "13563888653650925984868671744672725781658357821216877865297235725727006259983"); assert.equal(r[0].toString(), "13563888653650925984868671744672725781658357821216877865297235725727006259983");
assert.equal(r[1].toString(), "8442587202676550862664528699803615547505326611544120184665036919364004251662"); assert.equal(r[1].toString(), "8442587202676550862664528699803615547505326611544120184665036919364004251662");
}); });
@ -146,7 +142,7 @@ describe("Baby Jub js test", function () {
snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"), snarkjs.bigInt("2626589144620713026669568689430873010625803728049924121243784502389097019475"),
]; ];
const buf = babyjub.packPoint(p); const buf = babyjub.packPoint(p);
assert.equal(buf.toString('hex'), '53b81ed5bffe9545b54016234682e7b2f699bd42a5e9eae27ff4051bc698ce85'); assert.equal(buf.toString("hex"), "53b81ed5bffe9545b54016234682e7b2f699bd42a5e9eae27ff4051bc698ce85");
const p2 = babyjub.unpackPoint(buf); const p2 = babyjub.unpackPoint(buf);
assert.equal(p2[0].toString(), "17777552123799933955779906779655732241715742912184938656739573121738514868268"); assert.equal(p2[0].toString(), "17777552123799933955779906779655732241715742912184938656739573121738514868268");
assert.equal(p2[1].toString(), "2626589144620713026669568689430873010625803728049924121243784502389097019475"); assert.equal(p2[1].toString(), "2626589144620713026669568689430873010625803728049924121243784502389097019475");
@ -158,7 +154,7 @@ describe("Baby Jub js test", function () {
snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889"), snarkjs.bigInt("4338620300185947561074059802482547481416142213883829469920100239455078257889"),
]; ];
const buf = babyjub.packPoint(p); const buf = babyjub.packPoint(p);
assert.equal(buf.toString('hex'), 'e114eb17eddf794f063a68fecac515e3620e131976108555735c8b0773929709'); assert.equal(buf.toString("hex"), "e114eb17eddf794f063a68fecac515e3620e131976108555735c8b0773929709");
const p2 = babyjub.unpackPoint(buf); const p2 = babyjub.unpackPoint(buf);
assert.equal(p2[0].toString(), "6890855772600357754907169075114257697580319025794532037257385534741338397365"); assert.equal(p2[0].toString(), "6890855772600357754907169075114257697580319025794532037257385534741338397365");
assert.equal(p2[1].toString(), "4338620300185947561074059802482547481416142213883829469920100239455078257889"); assert.equal(p2[1].toString(), "4338620300185947561074059802482547481416142213883829469920100239455078257889");

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
const assert = chai.assert; const assert = chai.assert;
@ -51,6 +51,4 @@ describe("BinSub test", () => {
checkSub(-2, 2, circuit); checkSub(-2, 2, circuit);
checkSub(-2, 3, circuit); checkSub(-2, 3, circuit);
}); });
}); });

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const crypto = require("crypto"); const crypto = require("crypto");
const compiler = require("circom"); const compiler = require("circom");
@ -9,25 +9,23 @@ const assert = chai.assert;
describe("Sum test", () => { describe("Sum test", () => {
it("Should create a constant circuit", async () => { it("Should create a constant circuit", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "constants_test.circom")); const cirDef = await compiler(path.join(__dirname, "circuits", "constants_test.circom"));
assert.equal(cirDef.nVars, 2); assert.equal(cirDef.nVars, 2);
const circuit = new snarkjs.Circuit(cirDef); const circuit = new snarkjs.Circuit(cirDef);
const witness = circuit.calculateWitness({ "in": "0xd807aa98" }); const witness = circuit.calculateWitness({ in: "0xd807aa98" });
assert(witness[0].equals(snarkjs.bigInt(1))); assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt("0xd807aa98"))); assert(witness[1].equals(snarkjs.bigInt("0xd807aa98")));
}); });
it("Should create a sum circuit", async () => { it("Should create a sum circuit", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "sum_test.circom")); const cirDef = await compiler(path.join(__dirname, "circuits", "sum_test.circom"));
assert.equal(cirDef.nVars, 101); assert.equal(cirDef.nVars, 97); // 32 (in1) + 32(in2) + 32(out) + 1 (carry)
const circuit = new snarkjs.Circuit(cirDef); const circuit = new snarkjs.Circuit(cirDef);
const witness = circuit.calculateWitness({ "a": "111", "b": "222" }); const witness = circuit.calculateWitness({ a: "111", b: "222" });
assert(witness[0].equals(snarkjs.bigInt(1))); assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt("333"))); assert(witness[1].equals(snarkjs.bigInt("333")));

View File

@ -0,0 +1,3 @@
include "../../circuits/aliascheck.circom";
component main = AliasCheckBabyJub()

View File

@ -0,0 +1,3 @@
include "../../circuits/eddsamimcsponge.circom";
component main = EdDSAMiMCSpongeVerifier();

View File

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

View File

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

View File

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

View File

@ -7,10 +7,10 @@ template Main() {
var base = [5299619240641551281634865583518297030282874472190772894086521144482721001553, var base = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203]; 16950150798460657717958625567821834550301663161624707787222815936182638968203];
component escalarMul = EscalarMulW4Table(base, 0); var escalarMul = EscalarMulW4Table(base, 0);
for (var i=0; i<16; i++) { for (var i=0; i<16; i++) {
out[i][0] <== escalarMul.out[i][0]*in; out[i][0] <== escalarMul[i][0]*in;
out[i][1] <== escalarMul.out[i][1]*in; out[i][1] <== escalarMul[i][1]*in;
} }
} }

View File

@ -7,10 +7,10 @@ template Main() {
var base = [5299619240641551281634865583518297030282874472190772894086521144482721001553, var base = [5299619240641551281634865583518297030282874472190772894086521144482721001553,
16950150798460657717958625567821834550301663161624707787222815936182638968203]; 16950150798460657717958625567821834550301663161624707787222815936182638968203];
component escalarMul = EscalarMulW4Table(base, 3); var escalarMul = EscalarMulW4Table(base, 3);
for (var i=0; i<16; i++) { for (var i=0; i<16; i++) {
out[i][0] <== escalarMul.out[i][0]*in; out[i][0] <== escalarMul[i][0]*in;
out[i][1] <== escalarMul.out[i][1]*in; out[i][1] <== escalarMul[i][1]*in;
} }
} }

View File

@ -1,3 +1,3 @@
include "../../circuits/mimcsponge.circom" include "../../circuits/mimcsponge.circom"
component main = MiMCSponge(2, 220, 3); component main = MiMCSponge(2, 3);

View File

@ -1,3 +1,3 @@
include "../../circuits/poseidon.circom" 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(4);

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const crypto = require("crypto"); const crypto = require("crypto");
const compiler = require("circom"); const compiler = require("circom");
@ -14,11 +14,11 @@ describe("Sum test", () => {
const circuit = new snarkjs.Circuit(cirDef); const circuit = new snarkjs.Circuit(cirDef);
let witness; let witness;
witness = circuit.calculateWitness({ "in": 111}); witness = circuit.calculateWitness({ in: 111 });
assert(witness[0].equals(snarkjs.bigInt(1))); assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(0))); assert(witness[1].equals(snarkjs.bigInt(0)));
witness = circuit.calculateWitness({ "in": 0 }); witness = circuit.calculateWitness({ in: 0 });
assert(witness[0].equals(snarkjs.bigInt(1))); assert(witness[0].equals(snarkjs.bigInt(1)));
assert(witness[1].equals(snarkjs.bigInt(1))); assert(witness[1].equals(snarkjs.bigInt(1)));
}); });

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
// const crypto = require("crypto"); // const crypto = require("crypto");
@ -29,7 +29,6 @@ function buffer2bits(buff) {
return res; return res;
} }
describe("EdDSA test", function () { describe("EdDSA test", function () {
let circuit; let circuit;
@ -69,6 +68,5 @@ describe("EdDSA test", function () {
const w = circuit.calculateWitness({ A: aBits, R8: r8Bits, S: sBits, msg: msgBits }); const w = circuit.calculateWitness({ A: aBits, R8: r8Bits, S: sBits, msg: msgBits });
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
}); });
}); });

View File

@ -1,5 +1,5 @@
const chai = require("chai"); const chai = require("chai");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const eddsa = require("../src/eddsa.js"); const eddsa = require("../src/eddsa.js");
const babyJub = require("../src/babyjub.js"); const babyJub = require("../src/babyjub.js");
@ -9,7 +9,6 @@ const assert = chai.assert;
const bigInt = snarkjs.bigInt; const bigInt = snarkjs.bigInt;
describe("EdDSA js test", function () { describe("EdDSA js test", function () {
this.timeout(100000); this.timeout(100000);
it("Sign (using Mimc7) a single 10 bytes from 0 to 9", () => { it("Sign (using Mimc7) a single 10 bytes from 0 to 9", () => {
@ -22,29 +21,26 @@ describe("EdDSA js test", function () {
const pubKey = eddsa.prv2pub(prvKey); const pubKey = eddsa.prv2pub(prvKey);
assert.equal(pubKey[0].toString(), assert.equal(pubKey[0].toString(), "13277427435165878497778222415993513565335242147425444199013288855685581939618");
"13277427435165878497778222415993513565335242147425444199013288855685581939618"); assert.equal(pubKey[1].toString(), "13622229784656158136036771217484571176836296686641868549125388198837476602820");
assert.equal(pubKey[1].toString(),
"13622229784656158136036771217484571176836296686641868549125388198837476602820");
const pPubKey = babyJub.packPoint(pubKey); const pPubKey = babyJub.packPoint(pubKey);
const signature = eddsa.signMiMC(prvKey, msg); const signature = eddsa.signMiMC(prvKey, msg);
assert.equal(signature.R8[0].toString(), assert.equal(signature.R8[0].toString(), "11384336176656855268977457483345535180380036354188103142384839473266348197733");
"11384336176656855268977457483345535180380036354188103142384839473266348197733"); assert.equal(signature.R8[1].toString(), "15383486972088797283337779941324724402501462225528836549661220478783371668959");
assert.equal(signature.R8[1].toString(), assert.equal(signature.S.toString(), "2523202440825208709475937830811065542425109372212752003460238913256192595070");
"15383486972088797283337779941324724402501462225528836549661220478783371668959");
assert.equal(signature.S.toString(),
"2523202440825208709475937830811065542425109372212752003460238913256192595070");
const pSignature = eddsa.packSignature(signature); const pSignature = eddsa.packSignature(signature);
assert.equal(pSignature.toString("hex"), ""+ assert.equal(
pSignature.toString("hex"),
"" +
"dfedb4315d3f2eb4de2d3c510d7a987dcab67089c8ace06308827bf5bcbe02a2" + "dfedb4315d3f2eb4de2d3c510d7a987dcab67089c8ace06308827bf5bcbe02a2" +
"7ed40dab29bf993c928e789d007387998901a24913d44fddb64b1f21fc149405"); "7ed40dab29bf993c928e789d007387998901a24913d44fddb64b1f21fc149405"
);
const uSignature = eddsa.unpackSignature(pSignature); const uSignature = eddsa.unpackSignature(pSignature);
assert(eddsa.verifyMiMC(msg, uSignature, pubKey)); assert(eddsa.verifyMiMC(msg, uSignature, pubKey));
}); });
it("Sign (using Poseidon) a single 10 bytes from 0 to 9", () => { it("Sign (using Poseidon) a single 10 bytes from 0 to 9", () => {
@ -55,28 +51,25 @@ describe("EdDSA js test", function () {
const pubKey = eddsa.prv2pub(prvKey); const pubKey = eddsa.prv2pub(prvKey);
assert.equal(pubKey[0].toString(), assert.equal(pubKey[0].toString(), "13277427435165878497778222415993513565335242147425444199013288855685581939618");
"13277427435165878497778222415993513565335242147425444199013288855685581939618"); assert.equal(pubKey[1].toString(), "13622229784656158136036771217484571176836296686641868549125388198837476602820");
assert.equal(pubKey[1].toString(),
"13622229784656158136036771217484571176836296686641868549125388198837476602820");
const pPubKey = babyJub.packPoint(pubKey); const pPubKey = babyJub.packPoint(pubKey);
const signature = eddsa.signPoseidon(prvKey, msg); const signature = eddsa.signPoseidon(prvKey, msg);
assert.equal(signature.R8[0].toString(), assert.equal(signature.R8[0].toString(), "11384336176656855268977457483345535180380036354188103142384839473266348197733");
"11384336176656855268977457483345535180380036354188103142384839473266348197733"); assert.equal(signature.R8[1].toString(), "15383486972088797283337779941324724402501462225528836549661220478783371668959");
assert.equal(signature.R8[1].toString(), assert.equal(signature.S.toString(), "1398758333392199195742243841591064350253744445503462896781493968760929513778");
"15383486972088797283337779941324724402501462225528836549661220478783371668959");
assert.equal(signature.S.toString(),
"248298168863866362217836334079793350221620631973732197668910946177382043688");
const pSignature = eddsa.packSignature(signature); const pSignature = eddsa.packSignature(signature);
assert.equal(pSignature.toString("hex"), ""+ assert.equal(
pSignature.toString("hex"),
"" +
"dfedb4315d3f2eb4de2d3c510d7a987dcab67089c8ace06308827bf5bcbe02a2" + "dfedb4315d3f2eb4de2d3c510d7a987dcab67089c8ace06308827bf5bcbe02a2" +
"28506bce274aa1b3f7e7c2fd7e4fe09bff8f9aa37a42def7994e98f322888c00"); "32f16b0f2f4c4e1169aa59685637e1429b6581a9531d058d65f4ab224eab1703"
);
const uSignature = eddsa.unpackSignature(pSignature); const uSignature = eddsa.unpackSignature(pSignature);
assert(eddsa.verifyPoseidon(msg, uSignature, pubKey)); assert(eddsa.verifyPoseidon(msg, uSignature, pubKey));
}); });
}); });

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
const eddsa = require("../src/eddsa.js"); const eddsa = require("../src/eddsa.js");
@ -40,7 +40,8 @@ describe("EdDSA MiMC test", function () {
R8x: signature.R8[0], R8x: signature.R8[0],
R8y: signature.R8[1], R8y: signature.R8[1],
S: signature.S, S: signature.S,
M: msg}); M: msg,
});
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
}); });
@ -52,7 +53,6 @@ describe("EdDSA MiMC test", function () {
const pubKey = eddsa.prv2pub(prvKey); const pubKey = eddsa.prv2pub(prvKey);
const signature = eddsa.signMiMC(prvKey, msg); const signature = eddsa.signMiMC(prvKey, msg);
assert(eddsa.verifyMiMC(msg, signature, pubKey)); assert(eddsa.verifyMiMC(msg, signature, pubKey));
@ -64,14 +64,14 @@ describe("EdDSA MiMC test", function () {
R8x: signature.R8[0].add(bigInt(1)), R8x: signature.R8[0].add(bigInt(1)),
R8y: signature.R8[1], R8y: signature.R8[1],
S: signature.S, S: signature.S,
M: msg}); M: msg,
});
assert(false); assert(false);
} catch (err) { } 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 () => { it("Test a dissabled circuit with a bad signature", async () => {
const msg = bigInt(1234); const msg = bigInt(1234);
@ -79,7 +79,6 @@ describe("EdDSA MiMC test", function () {
const pubKey = eddsa.prv2pub(prvKey); const pubKey = eddsa.prv2pub(prvKey);
const signature = eddsa.signMiMC(prvKey, msg); const signature = eddsa.signMiMC(prvKey, msg);
assert(eddsa.verifyMiMC(msg, signature, pubKey)); assert(eddsa.verifyMiMC(msg, signature, pubKey));
@ -91,7 +90,8 @@ describe("EdDSA MiMC test", function () {
R8x: signature.R8[0].add(bigInt(1)), R8x: signature.R8[0].add(bigInt(1)),
R8y: signature.R8[1], R8y: signature.R8[1],
S: signature.S, S: signature.S,
M: msg}); M: msg,
});
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
}); });

99
test/eddsamimcsponge.js Normal file
View File

@ -0,0 +1,99 @@
const chai = require("chai");
const path = require("path");
const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom");
const eddsa = require("../src/eddsa.js");
const assert = chai.assert;
const bigInt = snarkjs.bigInt;
describe("EdDSA MiMCSponge test", function () {
let circuit;
this.timeout(100000);
before(async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "eddsamimcsponge_test.circom"));
circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains EdDSA MiMCSponge: " + circuit.nConstraints);
});
it("Sign a single number", async () => {
const msg = bigInt(1234);
const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex");
const pubKey = eddsa.prv2pub(prvKey);
const signature = eddsa.signMiMCSponge(prvKey, msg);
assert(eddsa.verifyMiMCSponge(msg, signature, pubKey));
const w = circuit.calculateWitness({
enabled: 1,
Ax: pubKey[0],
Ay: pubKey[1],
R8x: signature.R8[0],
R8y: signature.R8[1],
S: signature.S,
M: msg,
});
assert(circuit.checkWitness(w));
});
it("Detect Invalid signature", async () => {
const msg = bigInt(1234);
const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex");
const pubKey = eddsa.prv2pub(prvKey);
const signature = eddsa.signMiMCSponge(prvKey, msg);
assert(eddsa.verifyMiMCSponge(msg, signature, pubKey));
try {
const w = circuit.calculateWitness({
enabled: 1,
Ax: pubKey[0],
Ay: pubKey[1],
R8x: signature.R8[0].add(bigInt(1)),
R8y: signature.R8[1],
S: signature.S,
M: msg,
});
assert(false);
} catch (err) {
assert(err.message.indexOf("Constraint doesn't match") >= 0);
assert(err.message.indexOf("1 != 0") >= 0);
}
});
it("Test a dissabled circuit with a bad signature", async () => {
const msg = bigInt(1234);
const prvKey = Buffer.from("0001020304050607080900010203040506070809000102030405060708090001", "hex");
const pubKey = eddsa.prv2pub(prvKey);
const signature = eddsa.signMiMCSponge(prvKey, msg);
assert(eddsa.verifyMiMCSponge(msg, signature, pubKey));
const w = circuit.calculateWitness({
enabled: 0,
Ax: pubKey[0],
Ay: pubKey[1],
R8x: signature.R8[0].add(bigInt(1)),
R8y: signature.R8[1],
S: signature.S,
M: msg,
});
assert(circuit.checkWitness(w));
});
});

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
const eddsa = require("../src/eddsa.js"); const eddsa = require("../src/eddsa.js");
@ -40,7 +40,8 @@ describe("EdDSA Poseidon test", function () {
R8x: signature.R8[0], R8x: signature.R8[0],
R8y: signature.R8[1], R8y: signature.R8[1],
S: signature.S, S: signature.S,
M: msg}); M: msg,
});
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
}); });
@ -52,7 +53,6 @@ describe("EdDSA Poseidon test", function () {
const pubKey = eddsa.prv2pub(prvKey); const pubKey = eddsa.prv2pub(prvKey);
const signature = eddsa.signPoseidon(prvKey, msg); const signature = eddsa.signPoseidon(prvKey, msg);
assert(eddsa.verifyPoseidon(msg, signature, pubKey)); assert(eddsa.verifyPoseidon(msg, signature, pubKey));
@ -64,14 +64,14 @@ describe("EdDSA Poseidon test", function () {
R8x: signature.R8[0].add(bigInt(1)), R8x: signature.R8[0].add(bigInt(1)),
R8y: signature.R8[1], R8y: signature.R8[1],
S: signature.S, S: signature.S,
M: msg}); M: msg,
});
assert(false); assert(false);
} catch (err) { } 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 () => { it("Test a dissabled circuit with a bad signature", async () => {
const msg = bigInt(1234); const msg = bigInt(1234);
@ -79,7 +79,6 @@ describe("EdDSA Poseidon test", function () {
const pubKey = eddsa.prv2pub(prvKey); const pubKey = eddsa.prv2pub(prvKey);
const signature = eddsa.signPoseidon(prvKey, msg); const signature = eddsa.signPoseidon(prvKey, msg);
assert(eddsa.verifyPoseidon(msg, signature, pubKey)); assert(eddsa.verifyPoseidon(msg, signature, pubKey));
@ -91,7 +90,8 @@ describe("EdDSA Poseidon test", function () {
R8x: signature.R8[0].add(bigInt(1)), R8x: signature.R8[0].add(bigInt(1)),
R8y: signature.R8[1], R8y: signature.R8[1],
S: signature.S, S: signature.S,
M: msg}); M: msg,
});
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
}); });

View File

@ -1,13 +1,12 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
const assert = chai.assert; const assert = chai.assert;
const bigInt = snarkjs.bigInt; const bigInt = snarkjs.bigInt;
const q = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"); const q = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
function addPoint(a, b) { function addPoint(a, b) {
const cta = bigInt("168700"); const cta = bigInt("168700");
@ -25,7 +24,6 @@ function print(circuit, w, s) {
describe("Exponentioation test", () => { describe("Exponentioation test", () => {
it("Should generate the Exponentiation table in k=0", async () => { it("Should generate the Exponentiation table in k=0", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "escalarmulw4table_test.circom")); const cirDef = await compiler(path.join(__dirname, "circuits", "escalarmulw4table_test.circom"));
// console.log(JSON.stringify(cirDef, null, 1)); // console.log(JSON.stringify(cirDef, null, 1));
@ -38,30 +36,32 @@ describe("Exponentioation test", () => {
const w = circuit.calculateWitness({ in: 1 }); const w = circuit.calculateWitness({ in: 1 });
let g = [bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"), assert(circuit.checkWitness(w));
bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")]
let g = [
bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203"),
];
dbl = [bigInt("0"), snarkjs.bigInt("1")]; dbl = [bigInt("0"), snarkjs.bigInt("1")];
for (let i = 0; i < 16; i++) { for (let i = 0; i < 16; i++) {
const xout1 = w[circuit.getSignalIdx(`main.out[${i}][0]`)]; const xout1 = w[circuit.getSignalIdx(`main.out[${i}][0]`)];
const yout1 = w[circuit.getSignalIdx(`main.out[${i}][1]`)]; const yout1 = w[circuit.getSignalIdx(`main.out[${i}][1]`)];
/*
console.log(xout1.toString()); // console.log(xout1.toString());
console.log(yout1.toString()); // console.log(yout1.toString());
console.log(dbl[0]); // console.log(dbl[0]);
console.log(dbl[1]); // console.log(dbl[1]);
*/
assert(xout1.equals(dbl[0])); assert(xout1.equals(dbl[0]));
assert(yout1.equals(dbl[1])); assert(yout1.equals(dbl[1]));
dbl = addPoint([xout1, yout1], g); dbl = addPoint([xout1, yout1], g);
} }
}); });
it("Should generate the Exponentiation table in k=3", async () => { it("Should generate the Exponentiation table in k=3", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "escalarmulw4table_test3.circom")); const cirDef = await compiler(path.join(__dirname, "circuits", "escalarmulw4table_test3.circom"));
// console.log(JSON.stringify(cirDef, null, 1)); // console.log(JSON.stringify(cirDef, null, 1));
@ -74,8 +74,12 @@ describe("Exponentioation test", () => {
const w = circuit.calculateWitness({ in: 1 }); const w = circuit.calculateWitness({ in: 1 });
let g = [snarkjs.bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"), assert(circuit.checkWitness(w));
snarkjs.bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")]
let g = [
snarkjs.bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
snarkjs.bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203"),
];
for (let i = 0; i < 12; i++) { for (let i = 0; i < 12; i++) {
g = addPoint(g, g); g = addPoint(g, g);
@ -87,22 +91,20 @@ describe("Exponentioation test", () => {
const xout1 = w[circuit.getSignalIdx(`main.out[${i}][0]`)]; const xout1 = w[circuit.getSignalIdx(`main.out[${i}][0]`)];
const yout1 = w[circuit.getSignalIdx(`main.out[${i}][1]`)]; const yout1 = w[circuit.getSignalIdx(`main.out[${i}][1]`)];
/* // console.log(xout1.toString());
console.log(xout1.toString()); // console.log(yout1.toString());
console.log(yout1.toString()); // console.log(dbl[0]);
console.log(dbl[0]); // console.log(dbl[1]);
console.log(dbl[1]);
*/
assert(xout1.equals(dbl[0])); assert(xout1.equals(dbl[0]));
assert(yout1.equals(dbl[1])); assert(yout1.equals(dbl[1]));
dbl = addPoint([xout1, yout1], g); dbl = addPoint([xout1, yout1], g);
} }
}); });
it("Should exponentiate g^31", async () => { it("Should exponentiate g^31", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "escalarmul_test.circom")); const cirDef = await compiler(path.join(__dirname, "circuits", "escalarmul_test.circom"), { reduceConstraints: true });
// console.log(JSON.stringify(cirDef, null, 1)); // console.log(JSON.stringify(cirDef, null, 1));
@ -112,12 +114,14 @@ describe("Exponentioation test", () => {
console.log("NConstrains: " + circuit.nConstraints); console.log("NConstrains: " + circuit.nConstraints);
const w = circuit.calculateWitness({"in": 31}); const w = circuit.calculateWitness({ in: 31 });
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
let g = [snarkjs.bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"), let g = [
snarkjs.bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")] snarkjs.bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
snarkjs.bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203"),
];
let c = [0n, 1n]; let c = [0n, 1n];
@ -135,8 +139,8 @@ describe("Exponentioation test", () => {
assert(xout.equals(c[0])); assert(xout.equals(c[0]));
assert(yout.equals(c[1])); assert(yout.equals(c[1]));
console.log("-------") console.log("-------");
const w2 = circuit.calculateWitness({"in": (1n<<252n)+1n}); const w2 = circuit.calculateWitness({ in: (1n << 252n) + 1n });
const xout2 = w2[circuit.getSignalIdx(`main.out[0]`)]; const xout2 = w2[circuit.getSignalIdx(`main.out[0]`)];
const yout2 = w2[circuit.getSignalIdx(`main.out[1]`)]; const yout2 = w2[circuit.getSignalIdx(`main.out[1]`)];
@ -146,15 +150,14 @@ describe("Exponentioation test", () => {
c = addPoint(c, c); c = addPoint(c, c);
} }
c = addPoint(c, g); c = addPoint(c, g);
/*
console.log(xout2.toString()); // console.log(xout2.toString());
console.log(yout2.toString()); // console.log(yout2.toString());
console.log(c[0].toString()); // console.log(c[0].toString());
console.log(c[1].toString()); // console.log(c[1].toString());
*/
assert(xout2.equals(c[0])); assert(xout2.equals(c[0]));
assert(yout2.equals(c[1])); assert(yout2.equals(c[1]));
}).timeout(10000000); }).timeout(10000000);
it("Number of constrains for 256 bits", async () => { it("Number of constrains for 256 bits", async () => {
@ -164,5 +167,4 @@ describe("Exponentioation test", () => {
console.log("NConstrains: " + circuit.nConstraints); console.log("NConstrains: " + circuit.nConstraints);
}).timeout(10000000); }).timeout(10000000);
}); });

View File

@ -1,13 +1,12 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
const assert = chai.assert; const assert = chai.assert;
const bigInt = snarkjs.bigInt; const bigInt = snarkjs.bigInt;
function print(circuit, w, s) { function print(circuit, w, s) {
console.log(s + ": " + w[circuit.getSignalIdx(s)]); console.log(s + ": " + w[circuit.getSignalIdx(s)]);
} }
@ -19,7 +18,7 @@ describe("Escalarmul test", function () {
let g = [ let g = [
snarkjs.bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"), snarkjs.bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
snarkjs.bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203") snarkjs.bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203"),
]; ];
before(async () => { before(async () => {
@ -29,8 +28,7 @@ describe("Escalarmul test", function () {
}); });
it("Should generate Same escalar mul", async () => { it("Should generate Same escalar mul", async () => {
const w = circuitEMulAny.calculateWitness({ e: 1, p: g });
const w = circuitEMulAny.calculateWitness({"e": 1, "p": g});
assert(circuitEMulAny.checkWitness(w)); assert(circuitEMulAny.checkWitness(w));
@ -42,9 +40,8 @@ describe("Escalarmul test", function () {
}); });
it("If multiply by order should return 0", async () => { it("If multiply by order should return 0", async () => {
const r = bigInt("2736030358979909402780800718157159386076813972158567259200215660948447373041"); const r = bigInt("2736030358979909402780800718157159386076813972158567259200215660948447373041");
const w = circuitEMulAny.calculateWitness({"e": r, "p": g}); const w = circuitEMulAny.calculateWitness({ e: r, p: g });
assert(circuitEMulAny.checkWitness(w)); assert(circuitEMulAny.checkWitness(w));
@ -54,6 +51,4 @@ describe("Escalarmul test", function () {
assert(xout.equals(bigInt.zero)); assert(xout.equals(bigInt.zero));
assert(yout.equals(bigInt.one)); assert(yout.equals(bigInt.one));
}); });
}); });

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
const babyjub = require("../src/babyjub"); const babyjub = require("../src/babyjub");
@ -8,7 +8,6 @@ const assert = chai.assert;
const bigInt = snarkjs.bigInt; const bigInt = snarkjs.bigInt;
function print(circuit, w, s) { function print(circuit, w, s) {
console.log(s + ": " + w[circuit.getSignalIdx(s)]); console.log(s + ": " + w[circuit.getSignalIdx(s)]);
} }
@ -25,8 +24,7 @@ describe("Escalarmul test", function () {
}); });
it("Should generate Same escalar mul", async () => { it("Should generate Same escalar mul", async () => {
const w = circuit.calculateWitness({ e: 0 });
const w = circuit.calculateWitness({"e": 0});
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
@ -38,8 +36,7 @@ describe("Escalarmul test", function () {
}); });
it("Should generate Same escalar mul", async () => { it("Should generate Same escalar mul", async () => {
const w = circuit.calculateWitness({ e: 1 });
const w = circuit.calculateWitness({"e": 1});
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
@ -51,14 +48,13 @@ describe("Escalarmul test", function () {
}); });
it("Should generate scalar mul of a specific constant", async () => { it("Should generate scalar mul of a specific constant", async () => {
const s = bigInt("2351960337287830298912035165133676222414898052661454064215017316447594616519"); const s = bigInt("2351960337287830298912035165133676222414898052661454064215017316447594616519");
const base8 = [ const base8 = [
bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"), bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203") bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203"),
]; ];
const w = circuit.calculateWitness({"e": s}); const w = circuit.calculateWitness({ e: s });
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
@ -72,16 +68,15 @@ describe("Escalarmul test", function () {
}); });
it("Should generate scalar mul of the firsts 50 elements", async () => { it("Should generate scalar mul of the firsts 50 elements", async () => {
const base8 = [ const base8 = [
bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"), bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203") bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203"),
]; ];
for (let i = 0; i < 50; i++) { for (let i = 0; i < 50; i++) {
const s = bigInt(i); const s = bigInt(i);
const w = circuit.calculateWitness({"e": s}); const w = circuit.calculateWitness({ e: s });
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
@ -96,8 +91,7 @@ describe("Escalarmul test", function () {
}); });
it("If multiply by order should return 0", async () => { it("If multiply by order should return 0", async () => {
const w = circuit.calculateWitness({ e: babyjub.subOrder });
const w = circuit.calculateWitness({"e": babyjub.subOrder });
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
@ -107,6 +101,4 @@ describe("Escalarmul test", function () {
assert(xout.equals(bigInt.zero)); assert(xout.equals(bigInt.zero));
assert(yout.equals(bigInt.one)); assert(yout.equals(bigInt.one));
}); });
}); });

View File

@ -1,5 +1,4 @@
const snarkjs = require("@tornado/snarkjs");
const snarkjs = require("snarkjs");
const bigInt = snarkjs.bigInt; const bigInt = snarkjs.bigInt;

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
const mimcjs = require("../src/mimc7.js"); const mimcjs = require("../src/mimc7.js");
@ -30,6 +30,5 @@ describe("MiMC Circuit test", function () {
assert.equal(res.toString(), res2.toString()); assert.equal(res.toString(), res2.toString());
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
}); });
}); });

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
const mimcjs = require("../src/mimcsponge.js"); const mimcjs = require("../src/mimcsponge.js");
@ -30,7 +30,6 @@ describe("MiMC Sponge Circuit test", function () {
assert.equal(xRout.toString(), out2.xR.toString()); assert.equal(xRout.toString(), out2.xR.toString());
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
}); });
it("Should check hash", async () => { it("Should check hash", async () => {
@ -53,6 +52,5 @@ describe("MiMC Sponge Circuit test", function () {
assert.equal(o3.toString(), out2[2].toString()); assert.equal(o3.toString(), out2[2].toString());
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
}); });
}); });

View File

@ -33,8 +33,8 @@ describe("MiMC Sponge Smart contract test", () => {
}); });
it("Shold calculate the mimc correctly", async () => { it("Shold calculate the mimc correctly", async () => {
const res = await mimc.methods.MiMCSponge(1,2,3).call(); const res = await mimc.methods.MiMCSponge(1,2).call();
const res2 = await mimcjs.hash(1,2,3); const res2 = await mimcjs.hash(1,2, 0);
assert.equal(res.xL.toString(), res2.xL.toString()); assert.equal(res.xL.toString(), res2.xL.toString());
assert.equal(res.xR.toString(), res2.xR.toString()); assert.equal(res.xR.toString(), res2.xR.toString());

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
const babyJub = require("../src/babyjub.js"); const babyJub = require("../src/babyjub.js");
@ -16,7 +16,8 @@ describe("Montgomery test", function () {
let g = [ let g = [
snarkjs.bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"), snarkjs.bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
snarkjs.bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")]; snarkjs.bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203"),
];
let mg, mg2, g2, g3, mg3; let mg, mg2, g2, g3, mg3;

View File

@ -1,16 +1,14 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
const assert = chai.assert; const assert = chai.assert;
const bigInt = snarkjs.bigInt; const bigInt = snarkjs.bigInt;
describe("Mux4 test", () => { describe("Mux4 test", () => {
it("Should create a constant multiplexer 4", async () => { it("Should create a constant multiplexer 4", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "mux4_1.circom")); const cirDef = await compiler(path.join(__dirname, "circuits", "mux4_1.circom"));
// console.log(JSON.stringify(cirDef, null, 1)); // console.log(JSON.stringify(cirDef, null, 1));
@ -37,11 +35,13 @@ describe("Mux4 test", () => {
bigInt("1223"), bigInt("1223"),
bigInt("4546"), bigInt("4546"),
bigInt("4256"), bigInt("4256"),
bigInt("4456") bigInt("4456"),
]; ];
for (let i = 0; i < 16; i++) { for (let i = 0; i < 16; i++) {
const w = circuit.calculateWitness({ "selector": i }); const w = circuit.calculateWitness({ selector: i });
assert(circuit.checkWitness(w));
assert(w[0].equals(bigInt(1))); assert(w[0].equals(bigInt(1)));
@ -51,26 +51,16 @@ describe("Mux4 test", () => {
}); });
it("Should create a constant multiplexer 3", async () => { it("Should create a constant multiplexer 3", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "mux3_1.circom")); const cirDef = await compiler(path.join(__dirname, "circuits", "mux3_1.circom"));
const circuit = new snarkjs.Circuit(cirDef); const circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains Mux3: " + circuit.nConstraints); console.log("NConstrains Mux3: " + circuit.nConstraints);
const ct8 = [ const ct8 = [bigInt("37"), bigInt("47"), bigInt("53"), bigInt("71"), bigInt("89"), bigInt("107"), bigInt("163"), bigInt("191")];
bigInt("37"),
bigInt("47"),
bigInt("53"),
bigInt("71"),
bigInt("89"),
bigInt("107"),
bigInt("163"),
bigInt("191")
];
for (let i = 0; i < 8; i++) { for (let i = 0; i < 8; i++) {
const w = circuit.calculateWitness({ "selector": i }); const w = circuit.calculateWitness({ selector: i });
assert(w[0].equals(bigInt(1))); assert(w[0].equals(bigInt(1)));
@ -79,22 +69,18 @@ describe("Mux4 test", () => {
} }
}); });
it("Should create a constant multiplexer 2", async () => { it("Should create a constant multiplexer 2", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "mux2_1.circom")); const cirDef = await compiler(path.join(__dirname, "circuits", "mux2_1.circom"));
const circuit = new snarkjs.Circuit(cirDef); const circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains Mux2: " + circuit.nConstraints); console.log("NConstrains Mux2: " + circuit.nConstraints);
const ct8 = [ const ct8 = [bigInt("37"), bigInt("47"), bigInt("53"), bigInt("71")];
bigInt("37"),
bigInt("47"),
bigInt("53"),
bigInt("71"),
];
for (let i = 0; i < 4; i++) { for (let i = 0; i < 4; i++) {
const w = circuit.calculateWitness({ "selector": i }); const w = circuit.calculateWitness({ selector: i });
assert(circuit.checkWitness(w));
assert(w[0].equals(bigInt(1))); assert(w[0].equals(bigInt(1)));
@ -103,20 +89,18 @@ describe("Mux4 test", () => {
} }
}); });
it("Should create a constant multiplexer 1", async () => { it("Should create a constant multiplexer 1", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "mux1_1.circom")); const cirDef = await compiler(path.join(__dirname, "circuits", "mux1_1.circom"));
const circuit = new snarkjs.Circuit(cirDef); const circuit = new snarkjs.Circuit(cirDef);
console.log("NConstrains Mux1: " + circuit.nConstraints); console.log("NConstrains Mux1: " + circuit.nConstraints);
const ct8 = [ const ct8 = [bigInt("37"), bigInt("47")];
bigInt("37"),
bigInt("47"),
];
for (let i = 0; i < 2; i++) { for (let i = 0; i < 2; i++) {
const w = circuit.calculateWitness({ "selector": i }); const w = circuit.calculateWitness({ selector: i });
assert(circuit.checkWitness(w));
assert(w[0].equals(bigInt(1))); assert(w[0].equals(bigInt(1)));

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
const assert = chai.assert; const assert = chai.assert;
@ -9,13 +9,27 @@ const bigInt = snarkjs.bigInt;
const babyJub = require("../src/babyjub.js"); const babyJub = require("../src/babyjub.js");
const PBASE = const PBASE = [
[ [
[bigInt("10457101036533406547632367118273992217979173478358440826365724437999023779287"),bigInt("19824078218392094440610104313265183977899662750282163392862422243483260492317")], bigInt("10457101036533406547632367118273992217979173478358440826365724437999023779287"),
[bigInt("2671756056509184035029146175565761955751135805354291559563293617232983272177"),bigInt("2663205510731142763556352975002641716101654201788071096152948830924149045094")], bigInt("19824078218392094440610104313265183977899662750282163392862422243483260492317"),
[bigInt("5802099305472655231388284418920769829666717045250560929368476121199858275951"),bigInt("5980429700218124965372158798884772646841287887664001482443826541541529227896")], ],
[bigInt("7107336197374528537877327281242680114152313102022415488494307685842428166594"),bigInt("2857869773864086953506483169737724679646433914307247183624878062391496185654")], [
[bigInt("20265828622013100949498132415626198973119240347465898028410217039057588424236"),bigInt("1160461593266035632937973507065134938065359936056410650153315956301179689506")] bigInt("2671756056509184035029146175565761955751135805354291559563293617232983272177"),
bigInt("2663205510731142763556352975002641716101654201788071096152948830924149045094"),
],
[
bigInt("5802099305472655231388284418920769829666717045250560929368476121199858275951"),
bigInt("5980429700218124965372158798884772646841287887664001482443826541541529227896"),
],
[
bigInt("7107336197374528537877327281242680114152313102022415488494307685842428166594"),
bigInt("2857869773864086953506483169737724679646433914307247183624878062391496185654"),
],
[
bigInt("20265828622013100949498132415626198973119240347465898028410217039057588424236"),
bigInt("1160461593266035632937973507065134938065359936056410650153315956301179689506"),
],
]; ];
describe("Double Pedersen test", function () { describe("Double Pedersen test", function () {
@ -29,7 +43,6 @@ describe("Double Pedersen test", function() {
console.log("NConstrains: " + circuit.nConstraints); console.log("NConstrains: " + circuit.nConstraints);
}); });
it("Should pedersen at zero", async () => { it("Should pedersen at zero", async () => {
let w, xout, yout; let w, xout, yout;
w = circuit.calculateWitness({ in: ["0", "0"] }); w = circuit.calculateWitness({ in: ["0", "0"] });
@ -61,7 +74,6 @@ describe("Double Pedersen test", function() {
assert(xout.equals(PBASE[1][0])); assert(xout.equals(PBASE[1][0]));
assert(yout.equals(PBASE[1][1])); assert(yout.equals(PBASE[1][1]));
}); });
it("Should pedersen at mixed generators", async () => { it("Should pedersen at mixed generators", async () => {
let w, xout, yout; let w, xout, yout;
@ -70,15 +82,10 @@ describe("Double Pedersen test", function() {
xout = w[circuit.getSignalIdx("main.out[0]")]; xout = w[circuit.getSignalIdx("main.out[0]")];
yout = w[circuit.getSignalIdx("main.out[1]")]; yout = w[circuit.getSignalIdx("main.out[1]")];
const r = babyJub.addPoint(babyJub.mulPointEscalar(PBASE[0], 3), babyJub.mulPointEscalar(PBASE[1], 7));
const r = babyJub.addPoint(
babyJub.mulPointEscalar(PBASE[0], 3),
babyJub.mulPointEscalar(PBASE[1], 7)
);
assert(xout.equals(r[0])); assert(xout.equals(r[0]));
assert(yout.equals(r[1])); assert(yout.equals(r[1]));
}); });
it("Should pedersen all ones", async () => { it("Should pedersen all ones", async () => {
let w, xout, yout; let w, xout, yout;
@ -89,10 +96,7 @@ describe("Double Pedersen test", function() {
xout = w[circuit.getSignalIdx("main.out[0]")]; xout = w[circuit.getSignalIdx("main.out[0]")];
yout = w[circuit.getSignalIdx("main.out[1]")]; yout = w[circuit.getSignalIdx("main.out[1]")];
const r2 = babyJub.addPoint( const r2 = babyJub.addPoint(babyJub.mulPointEscalar(PBASE[0], allOnes), babyJub.mulPointEscalar(PBASE[1], allOnes));
babyJub.mulPointEscalar(PBASE[0], allOnes),
babyJub.mulPointEscalar(PBASE[1], allOnes)
);
assert(xout.equals(r2[0])); assert(xout.equals(r2[0]));
assert(yout.equals(r2[1])); assert(yout.equals(r2[1]));

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
const assert = chai.assert; const assert = chai.assert;
@ -10,7 +10,6 @@ const bigInt = snarkjs.bigInt;
const babyJub = require("../src/babyjub.js"); const babyJub = require("../src/babyjub.js");
const pedersen = require("../src/pedersenHash.js"); const pedersen = require("../src/pedersenHash.js");
describe("Pedersen test", function () { describe("Pedersen test", function () {
let circuit; let circuit;
this.timeout(100000); this.timeout(100000);
@ -22,7 +21,6 @@ describe("Pedersen test", function() {
console.log("NConstrains Pedersen2: " + circuit.nConstraints); console.log("NConstrains Pedersen2: " + circuit.nConstraints);
}); });
it("Should pedersen at zero", async () => { it("Should pedersen at zero", async () => {
let w, xout, yout; let w, xout, yout;
w = circuit.calculateWitness({ in: 0 }); w = circuit.calculateWitness({ in: 0 });
@ -44,7 +42,6 @@ describe("Pedersen test", function() {
assert(yout.equals(hP[1])); assert(yout.equals(hP[1]));
}); });
it("Should pedersen with 253 ones", async () => { it("Should pedersen with 253 ones", async () => {
let w, xout, yout; let w, xout, yout;
const n = bigInt.one.shl(253).sub(bigInt.one); const n = bigInt.one.shl(253).sub(bigInt.one);
@ -56,9 +53,8 @@ describe("Pedersen test", function() {
yout = w[circuit.getSignalIdx("main.out[1]")]; yout = w[circuit.getSignalIdx("main.out[1]")];
const b = Buffer.alloc(32); const b = Buffer.alloc(32);
for (let i=0; i<31; i++) b[i] = 0xFF; for (let i = 0; i < 31; i++) b[i] = 0xff;
b[31] = 0x1F; b[31] = 0x1f;
const h = pedersen.hash(b); const h = pedersen.hash(b);
const hP = babyJub.unpackPoint(h); const hP = babyJub.unpackPoint(h);

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
const assert = chai.assert; const assert = chai.assert;
@ -9,7 +9,6 @@ const bigInt = snarkjs.bigInt;
const babyJub = require("../src/babyjub.js"); const babyJub = require("../src/babyjub.js");
describe("Point 2 bits test", function () { describe("Point 2 bits test", function () {
let circuit; let circuit;
this.timeout(100000); this.timeout(100000);

View File

@ -1,60 +1,59 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
var blake2b = require('blake2b');
const poseidon = require("../src/poseidon.js"); const poseidon = require("../src/poseidon.js");
const assert = chai.assert; 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 () { describe("Poseidon Circuit test", function () {
let circuit; let circuit2;
let circuit4;
this.timeout(100000); this.timeout(100000);
before(async () => { before(async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "poseidon_test.circom")); const cirDef2 = await compiler(path.join(__dirname, "circuits", "poseidon2_test.circom"));
const cirDef4 = await compiler(path.join(__dirname, "circuits", "poseidon4_test.circom"));
circuit = new snarkjs.Circuit(cirDef); circuit2 = new snarkjs.Circuit(cirDef2);
circuit4 = new snarkjs.Circuit(cirDef4);
console.log("Poseidon constraints: " + circuit.nConstraints);
}); });
it("Should check constrain of hash([1, 2])", async () => { it("Should check constrain of hash([1, 2])", async () => {
const w = circuit.calculateWitness({inputs: [1, 2]}); const hash = poseidon([1, 2]);
assert.equal("0x11ad302b36a2d7e09653c8e90618f00c06cd0a7348e52cdf2ccced3c3abec679", "0x" + hash.toString(16));
const res = w[circuit.getSignalIdx("main.out")]; const w = await circuit2.calculateWitness({ inputs: [1, 2] }, true);
const res = w[circuit2.getSignalIdx("main.out")];
const hash = poseidon.createHash(6, 8, 57); assert.equal(res.toString(), hash.toString());
await circuit2.checkWitness(w);
const res2 = hash([1,2]);
assert.equal('12242166908188651009877250812424843524687801523336557272219921456462821518061', res2.toString());
assert.equal(res.toString(), res2.toString());
assert(circuit.checkWitness(w));
}); });
it("Should check constrain of hash([3, 4])", async () => { it("Should check constrain of hash([3, 4])", async () => {
const w = circuit.calculateWitness({inputs: [3, 4]}); const hash = poseidon([3, 4]);
assert.equal("0x23939f0972e764d6e252060279aabaca8ec650ab30b17d2c13551bec2a66bcef", "0x" + hash.toString(16));
const w = await circuit2.calculateWitness({ inputs: [3, 4] });
const res = w[circuit2.getSignalIdx("main.out")];
assert.equal(res.toString(), hash.toString());
await circuit2.checkWitness(w);
});
const res = w[circuit.getSignalIdx("main.out")]; it("Should check constrain of hash([1, 2, 3, 4])", async () => {
const hash = poseidon([1, 2, 3, 4]);
assert.equal("0x2e4fb80ce74868b0d33f4acb22071d8d8f8da7d30ebf972e6e4f72a64bb0633f", "0x" + hash.toString(16));
const w = await circuit4.calculateWitness({ inputs: [1, 2, 3, 4] });
const res = w[circuit4.getSignalIdx("main.out")];
assert.equal(res.toString(), hash.toString());
await circuit4.checkWitness(w);
});
const hash = poseidon.createHash(6, 8, 57); it("Should check constrain of hash([5, 6, 7, 8])", async () => {
const hash = poseidon([5, 6, 7, 8]);
const res2 = hash([3, 4]); assert.equal("0x2a3fc67aa97766917ee06e927f35fd70f4655ad6c1f2e7bcd5c5c85aa3a8a974", "0x" + hash.toString(16));
assert.equal('17185195740979599334254027721507328033796809509313949281114643312710535000993', res2.toString()); const w = await circuit4.calculateWitness({ inputs: [5, 6, 7, 8] });
const res = w[circuit4.getSignalIdx("main.out")];
assert.equal(res.toString(), res2.toString()); assert.equal(res.toString(), hash.toString());
await circuit4.checkWitness(w);
assert(circuit.checkWitness(w));
}); });
}); });

View File

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

23
test/rawsmt3.circom Normal file
View File

@ -0,0 +1,23 @@
include "../circuits/smt/smtverifier.circom";
template SMT(nLevels) {
signal input root;
signal input mtp[nLevels];
signal input hi;
signal input hv;
component smtClaimExists = SMTVerifier(nLevels);
smtClaimExists.enabled <== 1;
smtClaimExists.fnc <== 0;
smtClaimExists.root <== root;
for (var i=0; i<nLevels; i++) {
smtClaimExists.siblings[i] <== mtp[i];
}
smtClaimExists.oldKey <== 0;
smtClaimExists.oldValue <== 0;
smtClaimExists.isOld0 <== 0;
smtClaimExists.key <== hi;
smtClaimExists.value <== hv;
}
component main = SMT(4);

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const crypto = require("crypto"); const crypto = require("crypto");
const compiler = require("circom"); const compiler = require("circom");
@ -11,12 +11,11 @@ const sha256 = require("./helpers/sha256");
// const printSignal = require("./helpers/printsignal"); // const printSignal = require("./helpers/printsignal");
function buffer2bitArray(b) { function buffer2bitArray(b) {
const res = []; const res = [];
for (let i = 0; i < b.length; i++) { for (let i = 0; i < b.length; i++) {
for (let j = 0; j < 8; j++) { for (let j = 0; j < 8; j++) {
res.push((b[i] >> (7-j) &1)); res.push((b[i] >> (7 - j)) & 1);
} }
} }
return res; return res;
@ -33,10 +32,7 @@ function bitArray2buffer(a) {
return b; return b;
} }
describe("SHA256 test", () => { describe("SHA256 test", () => {
it("Should work bits to array and array to bits", async () => { it("Should work bits to array and array to bits", async () => {
const b = new Buffer.alloc(64); const b = new Buffer.alloc(64);
for (let i = 0; i < 64; i++) { for (let i = 0; i < 64; i++) {
@ -55,15 +51,13 @@ describe("SHA256 test", () => {
console.log("Vars: " + circuit.nVars); console.log("Vars: " + circuit.nVars);
console.log("Constraints: " + circuit.nConstraints); console.log("Constraints: " + circuit.nConstraints);
const witness = circuit.calculateWitness({ "a": "1", "b": "2" }); const witness = circuit.calculateWitness({ a: "1", b: "2" });
const b = new Buffer.alloc(54); const b = new Buffer.alloc(54);
b[26] = 1; b[26] = 1;
b[53] = 2; b[53] = 2;
const hash = crypto.createHash("sha256") const hash = crypto.createHash("sha256").update(b).digest("hex");
.update(b)
.digest("hex");
const r = "0x" + hash.slice(10); const r = "0x" + hash.slice(10);
const hash2 = sha256.hash(b.toString("hex"), { msgFormat: "hex-bytes" }); const hash2 = sha256.hash(b.toString("hex"), { msgFormat: "hex-bytes" });
@ -90,21 +84,17 @@ describe("SHA256 test", () => {
b[i] = i + 1; b[i] = i + 1;
} }
const hash = crypto.createHash("sha256") const hash = crypto.createHash("sha256").update(b).digest("hex");
.update(b)
.digest("hex");
const arrIn = buffer2bitArray(b); const arrIn = buffer2bitArray(b);
const witness = circuit.calculateWitness({ "in": arrIn } /*, {logOutput: true} */); const witness = circuit.calculateWitness({ in: arrIn } /*, {logOutput: true} */);
const arrOut = witness.slice(1, 257); const arrOut = witness.slice(1, 257);
const hash2 = bitArray2buffer(arrOut).toString("hex"); const hash2 = bitArray2buffer(arrOut).toString("hex");
assert.equal(hash, hash2); assert.equal(hash, hash2);
}).timeout(1000000); }).timeout(1000000);
it("Should calculate a hash of 2 compressor", async () => { it("Should calculate a hash of 2 compressor", async () => {
const cirDef = await compiler(path.join(__dirname, "circuits", "sha256_test448.circom"), { reduceConstraints: false }); const cirDef = await compiler(path.join(__dirname, "circuits", "sha256_test448.circom"), { reduceConstraints: false });
const circuit = new snarkjs.Circuit(cirDef); const circuit = new snarkjs.Circuit(cirDef);
@ -112,25 +102,21 @@ describe("SHA256 test", () => {
console.log("Vars: " + circuit.nVars); console.log("Vars: " + circuit.nVars);
console.log("Constraints: " + circuit.nConstraints); console.log("Constraints: " + circuit.nConstraints);
const testStr = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; const testStr = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
const b = Buffer.from(testStr, 'utf8'); const b = Buffer.from(testStr, "utf8");
for (let i = 0; i < 64; i++) { for (let i = 0; i < 64; i++) {
b[i] = i + 1; b[i] = i + 1;
} }
const hash = crypto.createHash("sha256") const hash = crypto.createHash("sha256").update(b).digest("hex");
.update(b)
.digest("hex");
const arrIn = buffer2bitArray(b); const arrIn = buffer2bitArray(b);
const witness = circuit.calculateWitness({ "in": arrIn } /*, {logOutput: true} */); const witness = circuit.calculateWitness({ in: arrIn } /*, {logOutput: true} */);
const arrOut = witness.slice(1, 257); const arrOut = witness.slice(1, 257);
const hash2 = bitArray2buffer(arrOut).toString("hex"); const hash2 = bitArray2buffer(arrOut).toString("hex");
assert.equal(hash, hash2); assert.equal(hash, hash2);
}).timeout(1000000); }).timeout(1000000);
}); });

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
const assert = chai.assert; const assert = chai.assert;
@ -83,6 +83,4 @@ describe("Sign test", () => {
assert(w[circuit.getSignalIdx("main.sign")].equals(bigInt(1))); assert(w[circuit.getSignalIdx("main.sign")].equals(bigInt(1)));
}); });
}); });

View File

@ -1,5 +1,5 @@
const chai = require("chai"); const chai = require("chai");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const smt = require("../src/smt.js"); const smt = require("../src/smt.js");
@ -7,9 +7,8 @@ const assert = chai.assert;
const bigInt = snarkjs.bigInt; const bigInt = snarkjs.bigInt;
function stringifyBigInts(o) { function stringifyBigInts(o) {
if ((typeof(o) == "bigint") || (o instanceof bigInt)) { if (typeof o == "bigint" || o instanceof bigInt) {
return o.toString(10); return o.toString(10);
} else if (Array.isArray(o)) { } else if (Array.isArray(o)) {
return o.map(stringifyBigInts); return o.map(stringifyBigInts);
@ -26,8 +25,7 @@ function stringifyBigInts(o) {
describe("SMT Javascript test", function () { describe("SMT Javascript test", function () {
this.timeout(100000); this.timeout(100000);
before( async () => { before(async () => {});
});
it("Should insert 2 elements and empty them", async () => { it("Should insert 2 elements and empty them", async () => {
const tree = await smt.newMemEmptyTrie(); const tree = await smt.newMemEmptyTrie();
@ -165,7 +163,7 @@ describe("SMT Javascript test", function () {
const tree2 = await smt.newMemEmptyTrie(); const tree2 = await smt.newMemEmptyTrie();
await tree1.insert(8, 88); await tree1.insert(8, 88);
await tree1.insert(9,99,); await tree1.insert(9, 99);
await tree1.insert(32, 3232); await tree1.insert(32, 3232);
await tree2.insert(8, 888); await tree2.insert(8, 888);
@ -178,5 +176,4 @@ describe("SMT Javascript test", function () {
assert(tree1.root.equals(tree2.root)); assert(tree1.root.equals(tree2.root));
}); });
}); });

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
const smt = require("../src/smt.js"); const smt = require("../src/smt.js");
@ -14,12 +14,12 @@ function print(circuit, w, s) {
} }
async function testInsert(tree, key, value, circuit, log) { async function testInsert(tree, key, value, circuit, log) {
const res = await tree.insert(key, value); const res = await tree.insert(key, value);
let siblings = res.siblings; let siblings = res.siblings;
while (siblings.length < 10) siblings.push(bigInt(0)); while (siblings.length < 10) siblings.push(bigInt(0));
const w = circuit.calculateWitness({ const w = circuit.calculateWitness(
{
fnc: [1, 0], fnc: [1, 0],
oldRoot: res.oldRoot, oldRoot: res.oldRoot,
siblings: siblings, siblings: siblings,
@ -27,8 +27,10 @@ async function testInsert(tree, key, value, circuit, log ) {
oldValue: res.isOld0 ? 0 : res.oldValue, oldValue: res.isOld0 ? 0 : res.oldValue,
isOld0: res.isOld0 ? 1 : 0, isOld0: res.isOld0 ? 1 : 0,
newKey: key, newKey: key,
newValue: value newValue: value,
}, log); },
log
);
const root1 = w[circuit.getSignalIdx("main.newRoot")]; const root1 = w[circuit.getSignalIdx("main.newRoot")];
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
@ -48,7 +50,7 @@ async function testDelete(tree, key, circuit) {
oldValue: res.isOld0 ? 0 : res.oldValue, oldValue: res.isOld0 ? 0 : res.oldValue,
isOld0: res.isOld0 ? 1 : 0, isOld0: res.isOld0 ? 1 : 0,
newKey: res.delKey, newKey: res.delKey,
newValue: res.delValue newValue: res.delValue,
}); });
const root1 = w[circuit.getSignalIdx("main.newRoot")]; const root1 = w[circuit.getSignalIdx("main.newRoot")];
@ -70,7 +72,7 @@ async function testUpdate(tree, key, newValue, circuit) {
oldValue: res.oldValue, oldValue: res.oldValue,
isOld0: 0, isOld0: 0,
newKey: res.newKey, newKey: res.newKey,
newValue: res.newValue newValue: res.newValue,
}); });
const root1 = w[circuit.getSignalIdx("main.newRoot")]; const root1 = w[circuit.getSignalIdx("main.newRoot")];
@ -79,7 +81,6 @@ async function testUpdate(tree, key, newValue, circuit) {
assert(root1.equals(res.newRoot)); assert(root1.equals(res.newRoot));
} }
describe("SMT test", function () { describe("SMT test", function () {
let circuit; let circuit;
let tree; let tree;
@ -110,8 +111,6 @@ describe("SMT test", function () {
await testInsert(tree, key, value, circuit); await testInsert(tree, key, value, circuit);
}); });
it("Should remove an element", async () => { it("Should remove an element", async () => {
await testDelete(tree, 111, circuit); await testDelete(tree, 111, circuit);
await testDelete(tree, 333, circuit); await testDelete(tree, 333, circuit);
@ -151,7 +150,6 @@ describe("SMT test", function () {
await testInsert(tree6, keys[1], values[1], circuit); await testInsert(tree6, keys[1], values[1], circuit);
await testInsert(tree6, keys[0], values[0], circuit); await testInsert(tree6, keys[0], values[0], circuit);
await testDelete(tree1, keys[0], circuit); await testDelete(tree1, keys[0], circuit);
await testDelete(tree1, keys[1], circuit); await testDelete(tree1, keys[1], circuit);
await testDelete(tree2, keys[1], circuit); await testDelete(tree2, keys[1], circuit);
@ -162,7 +160,6 @@ describe("SMT test", function () {
await testDelete(tree4, keys[2], circuit); await testDelete(tree4, keys[2], circuit);
await testDelete(tree4, keys[0], circuit); await testDelete(tree4, keys[0], circuit);
await testDelete(tree5, keys[1], circuit); await testDelete(tree5, keys[1], circuit);
await testDelete(tree5, keys[2], circuit); await testDelete(tree5, keys[2], circuit);
await testDelete(tree6, keys[2], circuit); await testDelete(tree6, keys[2], circuit);
@ -187,7 +184,7 @@ describe("SMT test", function () {
oldValue: 44, oldValue: 44,
isOld0: 55, isOld0: 55,
newKey: 66, newKey: 66,
newValue: 77 newValue: 77,
}); });
const root1 = w[circuit.getSignalIdx("main.oldRoot")]; const root1 = w[circuit.getSignalIdx("main.oldRoot")];
@ -195,7 +192,6 @@ describe("SMT test", function () {
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
assert(root1.equals(root2)); assert(root1.equals(root2));
}); });
it("Should update an element", async () => { it("Should update an element", async () => {
const tree1 = await smt.newMemEmptyTrie(); const tree1 = await smt.newMemEmptyTrie();
@ -213,5 +209,4 @@ describe("SMT test", function () {
await testUpdate(tree1, 9, 999, circuit); await testUpdate(tree1, 9, 999, circuit);
await testUpdate(tree1, 32, 323232, circuit); await testUpdate(tree1, 32, 323232, circuit);
}); });
}); });

View File

@ -1,6 +1,6 @@
const chai = require("chai"); const chai = require("chai");
const path = require("path"); const path = require("path");
const snarkjs = require("snarkjs"); const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom"); const compiler = require("circom");
const smt = require("../src/smt.js"); const smt = require("../src/smt.js");
@ -14,7 +14,6 @@ function print(circuit, w, s) {
} }
async function testInclusion(tree, key, circuit) { async function testInclusion(tree, key, circuit) {
const res = await tree.find(key); const res = await tree.find(key);
assert(res.found); assert(res.found);
@ -30,7 +29,7 @@ async function testInclusion(tree, key, circuit) {
oldValue: 0, oldValue: 0,
isOld0: 0, isOld0: 0,
key: key, key: key,
value: res.foundValue value: res.foundValue,
}); });
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
@ -52,7 +51,7 @@ async function testExclusion(tree, key, circuit) {
oldValue: res.isOld0 ? 0 : res.notFoundValue, oldValue: res.isOld0 ? 0 : res.notFoundValue,
isOld0: res.isOld0 ? 1 : 0, isOld0: res.isOld0 ? 1 : 0,
key: key, key: key,
value: 0 value: 0,
}); });
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
@ -106,10 +105,31 @@ describe("SMT test", function () {
oldValue: 33, oldValue: 33,
isOld0: 0, isOld0: 0,
key: 44, key: 44,
value: 0 value: 0,
}); });
assert(circuit.checkWitness(w)); assert(circuit.checkWitness(w));
}); });
it("Check inclussion Adria case", async () => {
const e1_hi = bigInt("17124152697573569611556136390143205198134245887034837071647643529178599000839");
const e1_hv = bigInt("19650379996168153643111744440707177573540245771926102415571667548153444658179");
const e2ok_hi = bigInt("16498254692537945203721083102154618658340563351558973077349594629411025251262");
const e2ok_hv = bigInt("19650379996168153643111744440707177573540245771926102415571667548153444658179");
const e2fail_hi = bigInt("17195092312975762537892237130737365903429674363577646686847513978084990105579");
const e2fail_hv = bigInt("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);
});
}); });

93
test/smtverifier_adria.js Normal file
View File

@ -0,0 +1,93 @@
const path = require("path");
const snarkjs = require("@tornado/snarkjs");
const compiler = require("circom");
const fs = require("fs");
const bigInt = snarkjs.bigInt;
const smt = require("../src/smt.js");
const circuitSource = `
include "../circuits/smt/smtverifier.circom";
template SMT(nLevels) {
signal input root;
signal input mtp[nLevels];
signal input hi;
signal input hv;
component smtClaimExists = SMTVerifier(nLevels);
smtClaimExists.enabled <== 1;
smtClaimExists.fnc <== 0;
smtClaimExists.root <== root;
for (var i=0; i<nLevels; i++) {
smtClaimExists.siblings[i] <== mtp[i];
}
smtClaimExists.oldKey <== 0;
smtClaimExists.oldValue <== 0;
smtClaimExists.isOld0 <== 0;
smtClaimExists.key <== hi;
smtClaimExists.value <== hv;
}
component main = SMT(4);
`;
describe("smt3test", function () {
this.timeout(200000);
let circuitFileName;
before(async () => {
circuitFileName = path.join(__dirname, ".", "rawsmt3.circom");
fs.writeFileSync(circuitFileName, circuitSource);
});
const levels = 4;
async function testsmt3(e1, e2) {
let tree = await smt.newMemEmptyTrie();
// insert e1, e2
await tree.insert(e1.hi, e1.hv);
await tree.insert(e2.hi, e2.hv);
// generate proof for e1
const findInfo = await tree.find(e1.hi);
const siblings = findInfo.siblings;
while (siblings.length < levels) siblings.push(bigInt(0));
const input = {
root: tree.root,
mtp: siblings,
hi: e1.hi,
hv: e1.hv,
};
const compiledCircuit = await compiler(circuitFileName, { reduceConstraints: false });
const circuit = new snarkjs.Circuit(compiledCircuit);
const witness = circuit.calculateWitness(input);
circuit.checkWitness(witness);
}
it("TestSmts", async () => {
const e1 = {
hi: bigInt("17124152697573569611556136390143205198134245887034837071647643529178599000839"),
hv: bigInt("19650379996168153643111744440707177573540245771926102415571667548153444658179"),
};
const e2ok = {
hi: bigInt("16498254692537945203721083102154618658340563351558973077349594629411025251262"),
hv: bigInt("19650379996168153643111744440707177573540245771926102415571667548153444658179"),
};
const e2fail = {
hi: bigInt("17195092312975762537892237130737365903429674363577646686847513978084990105579"),
hv: bigInt("19650379996168153643111744440707177573540245771926102415571667548153444658179"),
};
console.log("test e1, e2ok");
await testsmt3(e1, e2ok);
console.log("test e1, e2fail");
await testsmt3(e1, e2fail);
});
});