From eb7b83ca1961afc5876c128326d3e2e8fbd25930 Mon Sep 17 00:00:00 2001 From: poma Date: Sat, 21 Aug 2021 15:23:17 +0300 Subject: [PATCH 1/7] Use mocha for tests, add typechain --- .gitignore | 1 + .prettierignore | 1 + hardhat.config.js | 5 ++ package.json | 6 +- test/.mocharc.json | 4 ++ test/full.test.js | 10 ++- yarn.lock | 175 +++++++++++++++++++++++++++++++++++++++++++-- 7 files changed, 193 insertions(+), 9 deletions(-) create mode 100644 test/.mocharc.json diff --git a/.gitignore b/.gitignore index 5ca85c4..2c6ba41 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ node_modules build cache artifacts +src/types \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index 9c43edb..e4796dc 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,3 +3,4 @@ artifacts cache contracts/Verifier*.sol +src/types \ No newline at end of file diff --git a/hardhat.config.js b/hardhat.config.js index 06538dd..ee3914a 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -1,3 +1,5 @@ +require('@typechain/hardhat') +require('@nomiclabs/hardhat-ethers') require('@nomiclabs/hardhat-waffle') require('dotenv').config() @@ -24,6 +26,9 @@ const config = { mocha: { timeout: 600000000, }, + typechain: { + outDir: 'src/types', + }, } module.exports = config diff --git a/package.json b/package.json index e75482e..9f5e056 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,8 @@ "@nomiclabs/hardhat-ethers": "^2.0.2", "@nomiclabs/hardhat-waffle": "^2.0.1", "@openzeppelin/contracts": "^3.4.0", + "@typechain/ethers-v5": "^7.0.1", + "@typechain/hardhat": "^2.3.0", "bignumber.js": "^9.0.0", "chai": "^4.3.4", "circom": "^0.5.45", @@ -37,8 +39,10 @@ "ffjavascript": "^0.2.36", "fixed-merkle-tree": "^0.5.1", "hardhat": "^2.3.0", + "mocha": "^9.1.0", "snarkjs": "git+https://github.com/tornadocash/snarkjs.git#616c2d30699f28c8f3ab737b877402ccbb604cfe", - "tmp-promise": "^3.0.2" + "tmp-promise": "^3.0.2", + "typechain": "^5.1.2" }, "devDependencies": { "babel-eslint": "^10.1.0", diff --git a/test/.mocharc.json b/test/.mocharc.json new file mode 100644 index 0000000..2abd065 --- /dev/null +++ b/test/.mocharc.json @@ -0,0 +1,4 @@ +{ + "require": "hardhat/register", + "timeout": 20000 +} diff --git a/test/full.test.js b/test/full.test.js index 9512d8a..61d209b 100644 --- a/test/full.test.js +++ b/test/full.test.js @@ -1,4 +1,5 @@ -/* global ethers */ +const hre = require('hardhat') +const ethers = hre.ethers const { expect, should } = require('chai') should() @@ -11,8 +12,11 @@ const MerkleTree = require('fixed-merkle-tree') const { transaction, registerAndTransact } = require('../src/index') const { Keypair } = require('../src/keypair') -describe('TornadoPool', () => { - let snapshotId, tornadoPool, sender +describe('TornadoPool', function () { + this.timeout(20000) + let snapshotId, sender + /** @type {TornadoPool} */ + let tornadoPool /* prettier-ignore */ before(async function () { diff --git a/yarn.lock b/yarn.lock index 1e2c34c..8009a18 100644 --- a/yarn.lock +++ b/yarn.lock @@ -831,6 +831,18 @@ dependencies: ethers "^5.0.2" +"@typechain/ethers-v5@^7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-7.0.1.tgz#f9ae60ae5bd9e8ea8a996f66244147e8e74034ae" + integrity sha512-mXEJ7LG0pOYO+MRPkHtbf30Ey9X2KAsU0wkeoVvjQIn7iAY6tB3k3s+82bbmJAUMyENbQ04RDOZit36CgSG6Gg== + +"@typechain/hardhat@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-2.3.0.tgz#dc7f29281637b38b77c7c046ae82700703395d0f" + integrity sha512-zERrtNol86L4DX60ktnXxP7Cq8rSZHPaQvsChyiQQVuvVs2FTLm24Yi+MYnfsIdbUBIXZG7SxDWhtCF5I0tJNQ== + dependencies: + fs-extra "^9.1.0" + "@types/abstract-leveldown@*": version "5.0.1" resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-5.0.1.tgz#3c7750d0186b954c7f2d2f6acc8c3c7ba0c3412e" @@ -1145,7 +1157,7 @@ antlr4ts@^0.5.0-alpha.4: resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== -anymatch@~3.1.1: +anymatch@~3.1.1, anymatch@~3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== @@ -1287,6 +1299,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" @@ -2281,6 +2298,14 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -2328,6 +2353,21 @@ chokidar@3.5.1, chokidar@^3.4.0: optionalDependencies: fsevents "~2.3.1" +chokidar@3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" + integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + chownr@^1.1.1: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" @@ -4388,6 +4428,16 @@ fs-extra@^7.0.0, fs-extra@^7.0.1: jsonfile "^4.0.0" universalify "^0.1.0" +fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-minipass@^1.2.5: version "1.2.7" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" @@ -4405,7 +4455,7 @@ fsevents@~2.1.1: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== -fsevents@~2.3.1: +fsevents@~2.3.1, fsevents@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== @@ -4512,7 +4562,7 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -glob-parent@^5.1.2, glob-parent@~5.1.0: +glob-parent@^5.1.2, glob-parent@~5.1.0, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -4543,7 +4593,7 @@ glob@7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.2, glob@^7.1.3, glob@~7.1.6: +glob@7.1.7, glob@^7.1.2, glob@^7.1.3, glob@^7.1.6, glob@~7.1.6: version "7.1.7" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== @@ -4622,6 +4672,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== +graceful-fs@^4.2.0: + version "4.2.8" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" + integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== + growl@1.10.5: version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" @@ -5270,6 +5325,11 @@ is-typedarray@^1.0.0, is-typedarray@~1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + is-url@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" @@ -5377,6 +5437,13 @@ js-yaml@4.0.0: dependencies: argparse "^2.0.1" +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + js-yaml@^3.13.0, js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" @@ -5485,6 +5552,15 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -5875,6 +5951,14 @@ log-symbols@4.0.0: dependencies: chalk "^4.0.0" +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + logplease@^1.2.15: version "1.2.15" resolved "https://registry.yarnpkg.com/logplease/-/logplease-1.2.15.tgz#3da442e93751a5992cc19010a826b08d0293c48a" @@ -6207,7 +6291,7 @@ mkdirp-promise@^5.0.1: dependencies: mkdirp "*" -mkdirp@*: +mkdirp@*, mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -6287,6 +6371,37 @@ mocha@^8.2.1: yargs-parser "20.2.4" yargs-unparser "2.0.0" +mocha@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.1.0.tgz#0a7aa6fc4f59d1015d4e11747d9104b752553c67" + integrity sha512-Kjg/XxYOFFUi0h/FwMOeb6RoroiZ+P1yOfya6NK7h3dNhahrJx1r2XIT3ge4ZQvJM86mdjNA+W5phqRQh7DwCg== + dependencies: + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.2" + debug "4.3.1" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.1.7" + growl "1.10.5" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "3.0.4" + ms "2.1.3" + nanoid "3.1.23" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + which "2.0.2" + wide-align "1.1.3" + workerpool "6.1.5" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + mock-fs@^4.1.0: version "4.14.0" resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" @@ -6377,6 +6492,11 @@ nanoid@3.1.20: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788" integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw== +nanoid@3.1.23: + version "3.1.23" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81" + integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -7316,6 +7436,13 @@ readdirp@~3.5.0: dependencies: picomatch "^2.2.1" +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + readline@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/readline/-/readline-1.3.0.tgz#c580d77ef2cfc8752b132498060dc9793a7ac01c" @@ -7673,6 +7800,13 @@ serialize-javascript@5.0.1: dependencies: randombytes "^2.1.0" +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + serve-static@1.14.1: version "1.14.1" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" @@ -8453,6 +8587,11 @@ ts-essentials@^6.0.3: resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-6.0.7.tgz#5f4880911b7581a873783740ce8b94da163d18a6" integrity sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw== +ts-essentials@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" + integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== + ts-generator@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ts-generator/-/ts-generator-0.1.1.tgz#af46f2fb88a6db1f9785977e9590e7bcd79220ab" @@ -8565,6 +8704,22 @@ typechain@^3.0.0: ts-essentials "^6.0.3" ts-generator "^0.1.1" +typechain@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-5.1.2.tgz#c8784d6155a8e69397ca47f438a3b4fb2aa939da" + integrity sha512-FuaCxJd7BD3ZAjVJoO+D6TnqKey3pQdsqOBsC83RKYWKli5BDhdf0TPkwfyjt20TUlZvOzJifz+lDwXsRkiSKA== + dependencies: + "@types/prettier" "^2.1.1" + command-line-args "^4.0.7" + debug "^4.1.1" + fs-extra "^7.0.0" + glob "^7.1.6" + js-sha3 "^0.8.0" + lodash "^4.17.15" + mkdirp "^1.0.4" + prettier "^2.1.2" + ts-essentials "^7.0.1" + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -8639,6 +8794,11 @@ universalify@^0.1.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + unorm@^1.3.3: version "1.6.0" resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af" @@ -9438,6 +9598,11 @@ workerpool@6.1.0: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.0.tgz#a8e038b4c94569596852de7a8ea4228eefdeb37b" integrity sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg== +workerpool@6.1.5: + version "6.1.5" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.5.tgz#0f7cf076b6215fd7e1da903ff6f22ddd1886b581" + integrity sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw== + wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" From 576ba47938380366a622d0a90d463b3f21f7ce20 Mon Sep 17 00:00:00 2001 From: poma Date: Sat, 21 Aug 2021 15:46:17 +0300 Subject: [PATCH 2/7] use waffle --- src/utils.js | 9 -------- test/full.test.js | 53 ++++++++++++++++++++++++----------------------- 2 files changed, 27 insertions(+), 35 deletions(-) diff --git a/src/utils.js b/src/utils.js index 87b9e5f..33ab330 100644 --- a/src/utils.js +++ b/src/utils.js @@ -75,13 +75,6 @@ function shuffle(array) { return array } -async function takeSnapshot() { - return await ethers.provider.send('evm_snapshot', []) -} - -async function revertSnapshot(id) { - await ethers.provider.send('evm_revert', [id]) -} module.exports = { FIELD_SIZE, @@ -91,7 +84,5 @@ module.exports = { poseidonHash, poseidonHash2, getExtDataHash, - takeSnapshot, - revertSnapshot, shuffle, } diff --git a/test/full.test.js b/test/full.test.js index 61d209b..4790fb3 100644 --- a/test/full.test.js +++ b/test/full.test.js @@ -1,9 +1,9 @@ const hre = require('hardhat') -const ethers = hre.ethers -const { expect, should } = require('chai') -should() +const { ethers, waffle } = hre +const { loadFixture } = waffle +const { expect } = require('chai') -const { poseidonHash2, toFixedHex, takeSnapshot, revertSnapshot } = require('../src/utils') +const { poseidonHash2, toFixedHex } = require('../src/utils') const Utxo = require('../src/utxo') const MERKLE_TREE_HEIGHT = 5 @@ -14,30 +14,29 @@ const { Keypair } = require('../src/keypair') describe('TornadoPool', function () { this.timeout(20000) - let snapshotId, sender - /** @type {TornadoPool} */ - let tornadoPool - /* prettier-ignore */ - before(async function () { - ;[sender] = await ethers.getSigners() + async function deploy(contractName, ...args) { + const Factory = await ethers.getContractFactory(contractName) + const instance = await Factory.deploy(...args) + await instance.deployed() - const Verifier2 = await ethers.getContractFactory('Verifier2') - const verifier2 = await Verifier2.deploy() - await verifier2.deployed() + return instance + } - const Verifier16 = await ethers.getContractFactory('Verifier16') - const verifier16 = await Verifier16.deploy() - await verifier16.deployed() + async function fixture() { + const [deployer] = await ethers.getSigners() + + const verifier2 = await deploy('Verifier2') + + const verifier16 = await deploy('Verifier16') const tree = new MerkleTree(MERKLE_TREE_HEIGHT, [], { hashFunction: poseidonHash2 }) const root = await tree.root() + /** @type {TornadoPool} */ + const tornadoPool = await deploy('TornadoPool', verifier2.address, verifier16.address, toFixedHex(root)) - const Pool = await ethers.getContractFactory('TornadoPool') - tornadoPool = await Pool.deploy(verifier2.address, verifier16.address, toFixedHex(root)) - - snapshotId = await takeSnapshot() - }) + return { tornadoPool, deployer } + } it('encrypt -> decrypt should work', () => { const data = Buffer.from([0xff, 0xaa, 0x00, 0x01]) @@ -49,6 +48,7 @@ describe('TornadoPool', function () { }) it('constants check', async () => { + const { tornadoPool } = await loadFixture(fixture) const maxFee = await tornadoPool.MAX_FEE() const maxExtAmount = await tornadoPool.MAX_EXT_AMOUNT() const fieldSize = await tornadoPool.FIELD_SIZE() @@ -57,6 +57,9 @@ describe('TornadoPool', function () { }) it('should register and deposit', async function () { + let { tornadoPool } = await loadFixture(fixture) + const sender = (await ethers.getSigners())[1] + // Alice deposits into tornado pool const aliceDepositAmount = 1e7 const aliceDepositUtxo = new Utxo({ amount: aliceDepositAmount }) @@ -115,6 +118,8 @@ describe('TornadoPool', function () { }) it('should deposit, transact and withdraw', async function () { + const { tornadoPool } = await loadFixture(fixture) + // Alice deposits into tornado pool const aliceDepositAmount = 1e7 const aliceDepositUtxo = new Utxo({ amount: aliceDepositAmount }) @@ -162,11 +167,7 @@ describe('TornadoPool', function () { }) it('should work with 16 inputs', async function () { + const { tornadoPool } = await loadFixture(fixture) await transaction({ tornadoPool, inputs: [new Utxo(), new Utxo(), new Utxo()] }) }) - - afterEach(async () => { - await revertSnapshot(snapshotId) - snapshotId = await takeSnapshot() - }) }) From 454adf37206808ef247e04b5bb69ae2240926ee0 Mon Sep 17 00:00:00 2001 From: poma Date: Sat, 21 Aug 2021 15:54:24 +0300 Subject: [PATCH 3/7] minor refactor --- test/full.test.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/test/full.test.js b/test/full.test.js index 4790fb3..f12c09e 100644 --- a/test/full.test.js +++ b/test/full.test.js @@ -18,24 +18,23 @@ describe('TornadoPool', function () { async function deploy(contractName, ...args) { const Factory = await ethers.getContractFactory(contractName) const instance = await Factory.deploy(...args) - await instance.deployed() - - return instance + return instance.deployed() } async function fixture() { - const [deployer] = await ethers.getSigners() - const verifier2 = await deploy('Verifier2') - const verifier16 = await deploy('Verifier16') const tree = new MerkleTree(MERKLE_TREE_HEIGHT, [], { hashFunction: poseidonHash2 }) - const root = await tree.root() /** @type {TornadoPool} */ - const tornadoPool = await deploy('TornadoPool', verifier2.address, verifier16.address, toFixedHex(root)) + const tornadoPool = await deploy( + 'TornadoPool', + verifier2.address, + verifier16.address, + toFixedHex(tree.root()), + ) - return { tornadoPool, deployer } + return { tornadoPool } } it('encrypt -> decrypt should work', () => { From d93a6d62981ee901948187ee1a52bbc61dac5ae1 Mon Sep 17 00:00:00 2001 From: poma Date: Tue, 24 Aug 2021 19:19:26 +0300 Subject: [PATCH 4/7] Use switcher from circomlib --- circuits/merkleTree.circom | 46 +++++++++---------------------------- circuits/treeUpdater.circom | 8 +++---- 2 files changed, 15 insertions(+), 39 deletions(-) diff --git a/circuits/merkleTree.circom b/circuits/merkleTree.circom index 302c0d7..feeacb0 100644 --- a/circuits/merkleTree.circom +++ b/circuits/merkleTree.circom @@ -1,28 +1,5 @@ include "../node_modules/circomlib/circuits/poseidon.circom"; - -// Computes MiMC([left, right]) -template HashLeftRight() { - signal input left; - signal input right; - signal output hash; - - component hasher = Poseidon(2); - hasher.inputs[0] <== left; - hasher.inputs[1] <== right; - hash <== hasher.out; -} - -// if s == 0 returns [in[0], in[1]] -// if s == 1 returns [in[1], in[0]] -template DualMux() { - signal input in[2]; - signal input s; - signal output out[2]; - - s * (1 - s) === 0 - out[0] <== (in[1] - in[0])*s + in[0]; - out[1] <== (in[0] - in[1])*s + in[1]; -} +include "../node_modules/circomlib/circuits/switcher.circom"; // Verifies that merkle proof is correct for given merkle root and a leaf // pathIndices input is an array of 0/1 selectors telling whether given pathElement is on the left or right side of merkle path @@ -30,25 +7,24 @@ template MerkleTree(levels) { signal input leaf; signal input pathElements[levels]; signal input pathIndices; - signal output root; - component selectors[levels]; - component hashers[levels]; + component switcher[levels]; + component hasher[levels]; component indexBits = Num2Bits(levels); indexBits.in <== pathIndices; for (var i = 0; i < levels; i++) { - selectors[i] = DualMux(); - selectors[i].in[0] <== i == 0 ? leaf : hashers[i - 1].hash; - selectors[i].in[1] <== pathElements[i]; - selectors[i].s <== indexBits.out[i]; + switcher[i] = Switcher(); + switcher[i].L <== i == 0 ? leaf : hasher[i - 1].out; + switcher[i].R <== pathElements[i]; + switcher[i].sel <== indexBits.out[i]; - hashers[i] = HashLeftRight(); - hashers[i].left <== selectors[i].out[0]; - hashers[i].right <== selectors[i].out[1]; + hasher[i] = Poseidon(2); + hasher[i].inputs[0] <== switcher[i].outL; + hasher[i].inputs[1] <== switcher[i].outR; } - root <== hashers[levels - 1].hash; + root <== hasher[levels - 1].out; } diff --git a/circuits/treeUpdater.circom b/circuits/treeUpdater.circom index c77ae7a..6495a1e 100644 --- a/circuits/treeUpdater.circom +++ b/circuits/treeUpdater.circom @@ -17,9 +17,9 @@ template TreeUpdater(levels, subtreeLevels, zeroSubtreeRoot) { // calculate subtree root // todo: make it work with arbitrary subtree levels // currently it works only with 1-level subtrees - component leafPair = HashLeftRight(); - leafPair.left <== leaf[0]; - leafPair.right <== leaf[1]; + component leafPair = Poseidon(2); + leafPair.inputs[0] <== leaf[0]; + leafPair.inputs[1] <== leaf[1]; component treeBefore = MerkleTree(remainingLevels); for(var i = 0; i < remainingLevels; i++) { @@ -34,6 +34,6 @@ template TreeUpdater(levels, subtreeLevels, zeroSubtreeRoot) { treeAfter.pathElements[i] <== pathElements[i]; } treeAfter.pathIndices <== pathIndices; - treeAfter.leaf <== leafPair.hash; + treeAfter.leaf <== leafPair.out; treeAfter.root === newRoot; } From 98b2e238b95e281c7591bc274664e2112f28e1f6 Mon Sep 17 00:00:00 2001 From: poma Date: Wed, 25 Aug 2021 01:23:16 +0300 Subject: [PATCH 5/7] support any output count, some refactorings --- circuits/merkleProof.circom | 30 +++++++++++++++++++++ circuits/merkleTree.circom | 54 +++++++++++++++++++------------------ circuits/transaction.circom | 6 ++--- circuits/treeUpdater.circom | 20 +++++++------- 4 files changed, 70 insertions(+), 40 deletions(-) create mode 100644 circuits/merkleProof.circom diff --git a/circuits/merkleProof.circom b/circuits/merkleProof.circom new file mode 100644 index 0000000..5c31b83 --- /dev/null +++ b/circuits/merkleProof.circom @@ -0,0 +1,30 @@ +include "../node_modules/circomlib/circuits/poseidon.circom"; +include "../node_modules/circomlib/circuits/switcher.circom"; + +// Verifies that merkle proof is correct for given merkle root and a leaf +// pathIndices bits is an array of 0/1 selectors telling whether given pathElement is on the left or right side of merkle path +template MerkleProof(levels) { + signal input leaf; + signal input pathElements[levels]; + signal input pathIndices; + signal output root; + + component switcher[levels]; + component hasher[levels]; + + component indexBits = Num2Bits(levels); + indexBits.in <== pathIndices; + + for (var i = 0; i < levels; i++) { + switcher[i] = Switcher(); + switcher[i].L <== i == 0 ? leaf : hasher[i - 1].out; + switcher[i].R <== pathElements[i]; + switcher[i].sel <== indexBits.out[i]; + + hasher[i] = Poseidon(2); + hasher[i].inputs[0] <== switcher[i].outL; + hasher[i].inputs[1] <== switcher[i].outR; + } + + root <== hasher[levels - 1].out; +} diff --git a/circuits/merkleTree.circom b/circuits/merkleTree.circom index feeacb0..fafb746 100644 --- a/circuits/merkleTree.circom +++ b/circuits/merkleTree.circom @@ -1,30 +1,32 @@ include "../node_modules/circomlib/circuits/poseidon.circom"; -include "../node_modules/circomlib/circuits/switcher.circom"; -// Verifies that merkle proof is correct for given merkle root and a leaf -// pathIndices input is an array of 0/1 selectors telling whether given pathElement is on the left or right side of merkle path -template MerkleTree(levels) { - signal input leaf; - signal input pathElements[levels]; - signal input pathIndices; - signal output root; +// Helper template that computes hashes of the next tree layer +template TreeLayer(height) { + var nItems = 1 << height; + signal input ins[nItems * 2]; + signal output outs[nItems]; - component switcher[levels]; - component hasher[levels]; - - component indexBits = Num2Bits(levels); - indexBits.in <== pathIndices; - - for (var i = 0; i < levels; i++) { - switcher[i] = Switcher(); - switcher[i].L <== i == 0 ? leaf : hasher[i - 1].out; - switcher[i].R <== pathElements[i]; - switcher[i].sel <== indexBits.out[i]; - - hasher[i] = Poseidon(2); - hasher[i].inputs[0] <== switcher[i].outL; - hasher[i].inputs[1] <== switcher[i].outR; - } - - root <== hasher[levels - 1].out; + component hash[nItems]; + for(var i = 0; i < nItems; i++) { + hash[i] = Poseidon(2); + hash[i].inputs[0] <== ins[i * 2]; + hash[i].inputs[1] <== ins[i * 2 + 1]; + hash[i].out ==> outs[i]; + } } + +// Builds a merkle tree from leaf array +template MerkleTree(levels) { + signal input leaves[1 << levels]; + signal output root; + + component layers[levels]; + for(var level = levels - 1; level >= 0; level--) { + layers[level] = TreeLayer(level); + for(var i = 0; i < (1 << (level + 1)); i++) { + layers[level].ins[i] <== level == levels - 1 ? leaves[i] : layers[level + 1].outs[i]; + } + } + + root <== levels > 0 ? layers[0].outs[0] : leaves[0]; +} \ No newline at end of file diff --git a/circuits/transaction.circom b/circuits/transaction.circom index e083c1e..27520f8 100644 --- a/circuits/transaction.circom +++ b/circuits/transaction.circom @@ -1,4 +1,4 @@ -include "./merkleTree.circom" +include "./merkleProof.circom" include "./treeUpdater.circom" include "./utils.circom" @@ -64,7 +64,7 @@ template Transaction(levels, nIns, nOuts, zeroLeaf) { nullifierHasher[tx].privateKey <== inPrivateKey[tx]; nullifierHasher[tx].nullifier === inputNullifier[tx]; - tree[tx] = MerkleTree(levels); + tree[tx] = MerkleProof(levels); tree[tx].leaf <== inUtxoHasher[tx].commitment; tree[tx].pathIndices <== inPathIndices[tx]; for (var i = 0; i < levels; i++) { @@ -124,7 +124,7 @@ template Transaction(levels, nIns, nOuts, zeroLeaf) { treeUpdater.oldRoot <== root; treeUpdater.newRoot <== newRoot; for (var i = 0; i < nOuts; i++) { - treeUpdater.leaf[i] <== outputCommitment[i]; + treeUpdater.leaves[i] <== outputCommitment[i]; } treeUpdater.pathIndices <== outPathIndices; for (var i = 0; i < levels - 1; i++) { diff --git a/circuits/treeUpdater.circom b/circuits/treeUpdater.circom index 6495a1e..63de031 100644 --- a/circuits/treeUpdater.circom +++ b/circuits/treeUpdater.circom @@ -1,27 +1,25 @@ +include "./merkleProof.circom"; include "./merkleTree.circom"; // inserts a subtree into a merkle tree // checks that tree previously contained zeroes is the same positions // zeroSubtreeRoot is a root of a subtree that contains only zeroes template TreeUpdater(levels, subtreeLevels, zeroSubtreeRoot) { - // currently it works only with 1-level subtrees - assert(subtreeLevels == 1); var remainingLevels = levels - subtreeLevels; signal input oldRoot; signal input newRoot; - signal input leaf[1 << subtreeLevels]; + signal input leaves[1 << subtreeLevels]; signal input pathIndices; signal private input pathElements[remainingLevels]; // calculate subtree root - // todo: make it work with arbitrary subtree levels - // currently it works only with 1-level subtrees - component leafPair = Poseidon(2); - leafPair.inputs[0] <== leaf[0]; - leafPair.inputs[1] <== leaf[1]; + component subtree = MerkleTree(subtreeLevels); + for(var i = 0; i < (1 << subtreeLevels); i++) { + subtree.leaves[i] <== leaves[i]; + } - component treeBefore = MerkleTree(remainingLevels); + component treeBefore = MerkleProof(remainingLevels); for(var i = 0; i < remainingLevels; i++) { treeBefore.pathElements[i] <== pathElements[i]; } @@ -29,11 +27,11 @@ template TreeUpdater(levels, subtreeLevels, zeroSubtreeRoot) { treeBefore.leaf <== zeroSubtreeRoot; treeBefore.root === oldRoot; - component treeAfter = MerkleTree(remainingLevels); + component treeAfter = MerkleProof(remainingLevels); for(var i = 0; i < remainingLevels; i++) { treeAfter.pathElements[i] <== pathElements[i]; } treeAfter.pathIndices <== pathIndices; - treeAfter.leaf <== leafPair.out; + treeAfter.leaf <== subtree.root; treeAfter.root === newRoot; } From 5b9f1567e7ea1c58fb26cf54e4b3829406478fc1 Mon Sep 17 00:00:00 2001 From: poma Date: Wed, 25 Aug 2021 13:20:48 +0300 Subject: [PATCH 6/7] remove input range check --- circuits/transaction.circom | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/circuits/transaction.circom b/circuits/transaction.circom index 27520f8..24f7c80 100644 --- a/circuits/transaction.circom +++ b/circuits/transaction.circom @@ -43,7 +43,6 @@ template Transaction(levels, nIns, nOuts, zeroLeaf) { component inKeypair[nIns]; component inUtxoHasher[nIns]; component nullifierHasher[nIns]; - component inAmountCheck[nIns]; component tree[nIns]; component checkRoot[nIns]; var sumIns = 0; @@ -77,9 +76,9 @@ template Transaction(levels, nIns, nOuts, zeroLeaf) { checkRoot[tx].in[1] <== tree[tx].root; checkRoot[tx].enabled <== inAmount[tx]; - // Check that amount fits into 248 bits to prevent overflow - inAmountCheck[tx] = Num2Bits(248); - inAmountCheck[tx].in <== inAmount[tx]; + // We don't need to range check input amounts, since all inputs are valid UTXOs that + // were already checked as outputs in the previous transaction (or zero amount UTXOs that don't + // need to be checked either). sumIns += inAmount[tx]; } From 0f55ffac040ec49fe05d80f437f71541edf5503d Mon Sep 17 00:00:00 2001 From: poma Date: Wed, 25 Aug 2021 13:21:08 +0300 Subject: [PATCH 7/7] minor style change --- circuits/utils.circom | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/circuits/utils.circom b/circuits/utils.circom index d7ce7df..a32ccfb 100644 --- a/circuits/utils.circom +++ b/circuits/utils.circom @@ -16,7 +16,6 @@ template TransactionHasher() { signal input amount; signal input blinding; signal input publicKey; - signal output commitment; component hasher = Poseidon(3); @@ -27,10 +26,9 @@ template TransactionHasher() { } template NullifierHasher() { - signal input privateKey; - signal input merklePath; signal input commitment; - + signal input merklePath; + signal input privateKey; signal output nullifier; component hasher = Poseidon(3);