initial
This commit is contained in:
commit
b8f254c005
|
@ -0,0 +1,2 @@
|
||||||
|
node_modules
|
||||||
|
.env
|
|
@ -0,0 +1,9 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
|
@ -0,0 +1,13 @@
|
||||||
|
RPC_URL=
|
||||||
|
REDIS_URL=redis://127.0.0.1:6379
|
||||||
|
|
||||||
|
AGGREGATOR=0x466121060aD4dCE1E421027297d7e263236cbfc3
|
||||||
|
PRIVATE_KEY=
|
||||||
|
|
||||||
|
MERKLE_TREE_LEVELS=20
|
||||||
|
# the block of the tornadoTrees contract deployment
|
||||||
|
STARTING_BLOCK=22015916
|
||||||
|
INSERT_BATCH_SIZE=500
|
||||||
|
# should not be more often than CONFIRMATION_BLOCKS time. e.g every 3 minutes
|
||||||
|
CRON_EXPRESSION="0 */3 * * * *"
|
||||||
|
CONFIRMATION_BLOCKS=3
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"node": true,
|
||||||
|
"browser": true,
|
||||||
|
"es6": true,
|
||||||
|
"mocha": true
|
||||||
|
},
|
||||||
|
"extends": "eslint:recommended",
|
||||||
|
"globals": {
|
||||||
|
"Atomics": "readonly",
|
||||||
|
"SharedArrayBuffer": "readonly"
|
||||||
|
},
|
||||||
|
"parser": "babel-eslint",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 2018
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"indent": ["error", 2],
|
||||||
|
"linebreak-style": ["error", "unix"],
|
||||||
|
"quotes": ["error", "single"],
|
||||||
|
"semi": ["error", "never"],
|
||||||
|
"object-curly-spacing": ["error", "always"],
|
||||||
|
"comma-dangle": ["error", "always-multiline"],
|
||||||
|
"require-await": "error"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
name: build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ '*' ]
|
||||||
|
tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ]
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 12
|
||||||
|
# - run: yarn install
|
||||||
|
# - run: yarn lint
|
||||||
|
# - name: Telegram Failure Notification
|
||||||
|
# uses: appleboy/telegram-action@0.0.7
|
||||||
|
# if: failure()
|
||||||
|
# with:
|
||||||
|
# message: ❗ Build failed for [${{ github.repository }}](https://github.com/${{ github.repository }}/actions) because of ${{ github.actor }}
|
||||||
|
# format: markdown
|
||||||
|
# to: ${{ secrets.TELEGRAM_CHAT_ID }}
|
||||||
|
# token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
||||||
|
#
|
||||||
|
# publish:
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
|
# needs: build
|
||||||
|
# if: startsWith(github.ref, 'refs/tags')
|
||||||
|
# steps:
|
||||||
|
# - name: Checkout
|
||||||
|
# uses: actions/checkout@v2
|
||||||
|
#
|
||||||
|
# - name: Set vars
|
||||||
|
# id: vars
|
||||||
|
# run: |
|
||||||
|
# echo "::set-output name=version::$(echo ${GITHUB_REF#refs/tags/v})"
|
||||||
|
# echo "::set-output name=repo_name::$(echo ${GITHUB_REPOSITORY#*/})"
|
||||||
|
#
|
||||||
|
# - name: Check package.json version vs tag
|
||||||
|
# run: |
|
||||||
|
# [ ${{ steps.vars.outputs.version }} = $(grep '"version":' package.json | grep -o "[0-9.]*") ] || (echo "Git tag doesn't match version in package.json" && false)
|
||||||
|
#
|
||||||
|
# - name: Build and push Docker image
|
||||||
|
# uses: docker/build-push-action@v1.1.0
|
||||||
|
# with:
|
||||||
|
# dockerfile: Dockerfile
|
||||||
|
# repository: ${{ github.repository }}
|
||||||
|
# cache_froms: ${{ github.repository }}:latest
|
||||||
|
# tag_with_ref: true
|
||||||
|
# tags: latest
|
||||||
|
# username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
# password: ${{ secrets.DOCKER_TOKEN }}
|
||||||
|
#
|
||||||
|
# - name: Telegram Notification
|
||||||
|
# uses: appleboy/telegram-action@0.0.7
|
||||||
|
# with:
|
||||||
|
# message: 🚀 Published a [${{ steps.vars.outputs.repo_name }}](https://github.com/${{ github.repository }}) version [${{ steps.vars.outputs.version }}](https://hub.docker.com/repository/docker/${{ github.repository }}) to docker hub
|
||||||
|
# format: markdown
|
||||||
|
# to: ${{ secrets.TELEGRAM_CHAT_ID }}
|
||||||
|
# token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
||||||
|
#
|
||||||
|
# - name: Telegram Failure Notification
|
||||||
|
# uses: appleboy/telegram-action@0.0.7
|
||||||
|
# if: failure()
|
||||||
|
# with:
|
||||||
|
# message: ❗ Failed to publish [${{ steps.vars.outputs.repo_name }}](https://github.com/${{ github.repository }}/actions) because of ${{ env.GITHUB_ACTOR }}
|
||||||
|
# format: markdown
|
||||||
|
# to: ${{ secrets.TELEGRAM_CHAT_ID }}
|
||||||
|
# token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
|
@ -0,0 +1,2 @@
|
||||||
|
node_modules
|
||||||
|
.env
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "all",
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"semi": false,
|
||||||
|
"printWidth": 110
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
# syntax=docker/dockerfile:experimental
|
||||||
|
# export DOCKER_BUILDKIT=1
|
||||||
|
|
||||||
|
FROM node:12
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts && echo "Host github.com\n\tUser git" > ~/.ssh/config
|
||||||
|
|
||||||
|
COPY package.json yarn.lock ./
|
||||||
|
RUN --mount=type=ssh yarn && yarn cache clean --force
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
CMD ["yarn", "start"]
|
|
@ -0,0 +1,22 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2018 Truffle
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Root updater [![Build Status](https://github.com/tornadocash/root-updater/workflows/build/badge.svg)](https://github.com/tornadocash/root-updater/actions) [![Docker Image Version (latest semver)](https://img.shields.io/docker/v/tornadocash/root-updater?logo=docker&logoColor=%23FFFFFF&sort=semver)](https://hub.docker.com/repository/docker/tornadocash/root-updater)
|
||||||
|
|
||||||
|
Uploads deposit and withdrawal events from tornado instances into merkle tree
|
||||||
|
|
||||||
|
## Usage with docker
|
||||||
|
|
||||||
|
```shell script
|
||||||
|
wget https://raw.githubusercontent.com/tornadocash/root-updater/master/docker-compose.yml
|
||||||
|
wget https://raw.githubusercontent.com/tornadocash/root-updater/master/.env.example -O .env
|
||||||
|
vi .env # update env vars
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage for development
|
||||||
|
|
||||||
|
```shell script
|
||||||
|
yarn
|
||||||
|
cp .env.example .env
|
||||||
|
yarn start
|
||||||
|
```
|
||||||
|
|
||||||
|
Caches events from both mining and tornado cash instances
|
|
@ -0,0 +1,319 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32[]",
|
||||||
|
"name": "domains",
|
||||||
|
"type": "bytes32[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "bulkResolve",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address[]",
|
||||||
|
"name": "result",
|
||||||
|
"type": "address[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "contract Governance",
|
||||||
|
"name": "governance",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "getAllProposals",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "proposer",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "target",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "startTime",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "endTime",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "forVotes",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "againstVotes",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "executed",
|
||||||
|
"type": "bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "extended",
|
||||||
|
"type": "bool"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "enum Governance.ProposalState",
|
||||||
|
"name": "state",
|
||||||
|
"type": "uint8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"internalType": "struct GovernanceAggregator.Proposal[]",
|
||||||
|
"name": "proposals",
|
||||||
|
"type": "tuple[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "contract Governance",
|
||||||
|
"name": "governance",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address[]",
|
||||||
|
"name": "accs",
|
||||||
|
"type": "address[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "getGovernanceBalances",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256[]",
|
||||||
|
"name": "amounts",
|
||||||
|
"type": "uint256[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address[]",
|
||||||
|
"name": "fromTokens",
|
||||||
|
"type": "address[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256[]",
|
||||||
|
"name": "oneUnitAmounts",
|
||||||
|
"type": "uint256[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "getPricesInETH",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256[]",
|
||||||
|
"name": "prices",
|
||||||
|
"type": "uint256[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "contract Governance",
|
||||||
|
"name": "governance",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "account",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "getUserData",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "balance",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "latestProposalId",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "latestProposalIdState",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "timelock",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "delegatee",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "contract Miner",
|
||||||
|
"name": "miner",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address[]",
|
||||||
|
"name": "instances",
|
||||||
|
"type": "address[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "minerRates",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256[]",
|
||||||
|
"name": "_rates",
|
||||||
|
"type": "uint256[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "node",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "resolve",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "contract RewardSwap",
|
||||||
|
"name": "swap",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "swapState",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "balance",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "poolWeight",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "contract Miner",
|
||||||
|
"name": "miner",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address[]",
|
||||||
|
"name": "instances",
|
||||||
|
"type": "address[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "contract RewardSwap",
|
||||||
|
"name": "swap",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "miningData",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256[]",
|
||||||
|
"name": "_rates",
|
||||||
|
"type": "uint256[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "balance",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "poolWeight",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address[]",
|
||||||
|
"name": "fromTokens",
|
||||||
|
"type": "address[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256[]",
|
||||||
|
"name": "oneUnitAmounts",
|
||||||
|
"type": "uint256[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "contract RewardSwap",
|
||||||
|
"name": "swap",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "marketData",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256[]",
|
||||||
|
"name": "prices",
|
||||||
|
"type": "uint256[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "balance",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,519 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "_newOperator",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "changeOperator",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "nullifierHashes",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes",
|
||||||
|
"name": "_proof",
|
||||||
|
"type": "bytes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "_root",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "_nullifierHash",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address payable",
|
||||||
|
"name": "_recipient",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address payable",
|
||||||
|
"name": "_relayer",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "_fee",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "_refund",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "withdraw",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": true,
|
||||||
|
"stateMutability": "payable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "verifier",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "contract IVerifier",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "_left",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "_right",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "hashLeftRight",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "pure",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "FIELD_SIZE",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "levels",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint32",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "operator",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "_root",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "isKnownRoot",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "commitments",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "denomination",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "currentRootIndex",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint32",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "_newVerifier",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "updateVerifier",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32[]",
|
||||||
|
"name": "_nullifierHashes",
|
||||||
|
"type": "bytes32[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "isSpentArray",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool[]",
|
||||||
|
"name": "spent",
|
||||||
|
"type": "bool[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "_commitment",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "deposit",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": true,
|
||||||
|
"stateMutability": "payable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "getLastRoot",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "roots",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "ROOT_HISTORY_SIZE",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint32",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "_nullifierHash",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "isSpent",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "zeros",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "ZERO_VALUE",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "filledSubtrees",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "nextIndex",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint32",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "contract IVerifier",
|
||||||
|
"name": "_verifier",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "_denomination",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint32",
|
||||||
|
"name": "_merkleTreeHeight",
|
||||||
|
"type": "uint32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "_operator",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "constructor"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": true,
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "commitment",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "uint32",
|
||||||
|
"name": "leafIndex",
|
||||||
|
"type": "uint32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "timestamp",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "Deposit",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "to",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "nullifierHash",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": true,
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "relayer",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "fee",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "Withdrawal",
|
||||||
|
"type": "event"
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,475 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "_tornadoProxy",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "_hasher2",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "_hasher3",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint32",
|
||||||
|
"name": "_levels",
|
||||||
|
"type": "uint32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "constructor"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "instance",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": true,
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "hash",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "block",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "index",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "DepositData",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "instance",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": true,
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "hash",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "block",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "index",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "WithdrawalData",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32[]",
|
||||||
|
"name": "domains",
|
||||||
|
"type": "bytes32[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "bulkResolve",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address[]",
|
||||||
|
"name": "result",
|
||||||
|
"type": "address[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "depositTree",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "contract OwnableMerkleTree",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "deposits",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "hasher",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "contract IHasher",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "lastProcessedDepositLeaf",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "lastProcessedWithdrawalLeaf",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "node",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "resolve",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "tornadoProxy",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "withdrawalTree",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "contract OwnableMerkleTree",
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "withdrawals",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "_instance",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "_commitment",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "registerNewDeposit",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "_instance",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "_nullifier",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "registerNewWithdrawal",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "instance",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "hash",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "block",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"internalType": "struct TornadoTrees.TreeLeaf[]",
|
||||||
|
"name": "_deposits",
|
||||||
|
"type": "tuple[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "instance",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "hash",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "block",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"internalType": "struct TornadoTrees.TreeLeaf[]",
|
||||||
|
"name": "_withdrawals",
|
||||||
|
"type": "tuple[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "updateRoots",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "instance",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "hash",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "block",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"internalType": "struct TornadoTrees.TreeLeaf[]",
|
||||||
|
"name": "_deposits",
|
||||||
|
"type": "tuple[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "updateDepositTree",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "instance",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "hash",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "block",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"internalType": "struct TornadoTrees.TreeLeaf[]",
|
||||||
|
"name": "_withdrawals",
|
||||||
|
"type": "tuple[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "updateWithdrawalTree",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "_depositRoot",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "_withdrawalRoot",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "validateRoots",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "depositRoot",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "withdrawalRoot",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "getRegisteredDeposits",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32[]",
|
||||||
|
"name": "_deposits",
|
||||||
|
"type": "bytes32[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "getRegisteredWithdrawals",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32[]",
|
||||||
|
"name": "_withdrawals",
|
||||||
|
"type": "bytes32[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "blockNumber",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,22 @@
|
||||||
|
version: '2'
|
||||||
|
|
||||||
|
# ssh-agent && ssh-add -K ~/.ssh/id_rsa
|
||||||
|
# DOCKER_BUILDKIT=1 docker build --ssh default -t tornadocash/root-updater .
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
image: tornadocash/root-updater
|
||||||
|
depends_on: [redis]
|
||||||
|
restart: always
|
||||||
|
env_file: .env
|
||||||
|
environment:
|
||||||
|
REDIS_URL: redis://redis/0
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis
|
||||||
|
restart: always
|
||||||
|
command: [redis-server, --appendonly, 'yes']
|
||||||
|
volumes:
|
||||||
|
- redis:/data
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
redis:
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"name": "root-updater",
|
||||||
|
"version": "1.0.4",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint --ext .js --ignore-path .gitignore .",
|
||||||
|
"start": "node src/index.js"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "Roman Semenov <semenov.roma@gmail.com>",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"circomlib": "git+https://github.com/tornadocash/circomlib.git#3b492f9801573eebcfe1b6c584afe8a3beecf2b4",
|
||||||
|
"cron": "^1.8.2",
|
||||||
|
"dotenv": "^8.2.0",
|
||||||
|
"eth-ens-namehash": "^2.0.8",
|
||||||
|
"fixed-merkle-tree": "^0.3.4",
|
||||||
|
"ioredis": "^4.17.3",
|
||||||
|
"snarkjs": "git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5",
|
||||||
|
"tx-manager": "^0.2.9",
|
||||||
|
"web3": "^1.2.11",
|
||||||
|
"torn-token": "git+ssh://git@github.com/tornadocash/torn-token.git#04c4df88d470ca7503ef5d97882c56cba4f3647d"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"babel-eslint": "^10.1.0",
|
||||||
|
"eslint": "^7.5.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
// This module is used only for tests
|
||||||
|
function send(method, params = []) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
web3.currentProvider.send(
|
||||||
|
{
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: Date.now(),
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
},
|
||||||
|
(err, res) => {
|
||||||
|
return err ? reject(err) : resolve(res)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const takeSnapshot = async () => {
|
||||||
|
return await send('evm_snapshot')
|
||||||
|
}
|
||||||
|
|
||||||
|
const traceTransaction = async (tx) => {
|
||||||
|
return await send('debug_traceTransaction', [tx, {}])
|
||||||
|
}
|
||||||
|
|
||||||
|
const revertSnapshot = async (id) => {
|
||||||
|
await send('evm_revert', [id])
|
||||||
|
}
|
||||||
|
|
||||||
|
const mineBlock = async (timestamp) => {
|
||||||
|
await send('evm_mine', [timestamp])
|
||||||
|
}
|
||||||
|
|
||||||
|
const increaseTime = async (seconds) => {
|
||||||
|
await send('evm_increaseTime', [seconds])
|
||||||
|
}
|
||||||
|
|
||||||
|
const minerStop = async () => {
|
||||||
|
await send('miner_stop', [])
|
||||||
|
}
|
||||||
|
|
||||||
|
const minerStart = async () => {
|
||||||
|
await send('miner_start', [])
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
takeSnapshot,
|
||||||
|
revertSnapshot,
|
||||||
|
mineBlock,
|
||||||
|
minerStop,
|
||||||
|
minerStart,
|
||||||
|
increaseTime,
|
||||||
|
traceTransaction,
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
const { web3, getTornadoTrees } = require('./singletons')
|
||||||
|
const tornadoAbi = require('../abi/tornado.json')
|
||||||
|
const { poseidonHash } = require('./utils')
|
||||||
|
const { soliditySha3 } = require('web3-utils')
|
||||||
|
|
||||||
|
async function getTornadoEvents({ instances, startBlock, endBlock, type }) {
|
||||||
|
const hashName = type === 'deposit' ? 'commitment' : 'nullifierHash'
|
||||||
|
const promises = instances.map((instance) => getInstanceEvents({ type, instance, startBlock, endBlock }))
|
||||||
|
|
||||||
|
const raw = await Promise.all(promises)
|
||||||
|
|
||||||
|
const events = raw.flat().reduce((acc, e) => {
|
||||||
|
const encodedData = web3.eth.abi.encodeParameters(
|
||||||
|
['address', 'bytes32', 'uint256'],
|
||||||
|
[e.address, e.returnValues[hashName], e.blockNumber],
|
||||||
|
)
|
||||||
|
const leafHash = soliditySha3({ t: 'bytes', v: encodedData })
|
||||||
|
acc[leafHash] = {
|
||||||
|
instance: e.address,
|
||||||
|
hash: e.returnValues[hashName],
|
||||||
|
block: e.blockNumber,
|
||||||
|
}
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
return events
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getInstanceEvents({ type, instance, startBlock, endBlock }) {
|
||||||
|
const eventName = type === 'deposit' ? 'Deposit' : 'Withdrawal'
|
||||||
|
|
||||||
|
const contract = new web3.eth.Contract(tornadoAbi, instance)
|
||||||
|
const events = await contract.getPastEvents(eventName, {
|
||||||
|
fromBlock: startBlock,
|
||||||
|
toBlock: endBlock,
|
||||||
|
})
|
||||||
|
return events
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getMiningEvents(startBlock, endBlock, type) {
|
||||||
|
const eventName = type === 'deposit' ? 'DepositData' : 'WithdrawalData'
|
||||||
|
const tornadoTrees = await getTornadoTrees()
|
||||||
|
const events = await tornadoTrees.getPastEvents(eventName, {
|
||||||
|
fromBlock: startBlock,
|
||||||
|
toBlock: endBlock,
|
||||||
|
})
|
||||||
|
return events
|
||||||
|
.sort((a, b) => a.returnValues.index - b.returnValues.index)
|
||||||
|
.map((e) => poseidonHash([e.returnValues.instance, e.returnValues.hash, e.returnValues.block]))
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getRegisteredEvents({ type }) {
|
||||||
|
const method = type === 'deposit' ? 'getRegisteredDeposits' : 'getRegisteredWithdrawals'
|
||||||
|
const tornadoTrees = await getTornadoTrees()
|
||||||
|
const events = await tornadoTrees.methods[method]().call()
|
||||||
|
return events
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getTornadoEvents,
|
||||||
|
getMiningEvents,
|
||||||
|
getRegisteredEvents,
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
require('dotenv').config()
|
||||||
|
const cron = require('cron')
|
||||||
|
const { web3, redis, getTornadoTrees, txManager } = require('./singletons')
|
||||||
|
const config = require('torn-token')
|
||||||
|
const { getTornadoEvents, getRegisteredEvents } = require('./events')
|
||||||
|
|
||||||
|
const STARTING_BLOCK = process.env.STARTING_BLOCK || 0
|
||||||
|
const prefix = {
|
||||||
|
1: '',
|
||||||
|
42: 'kovan.',
|
||||||
|
5: 'goerli.',
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main(isRetry = false) {
|
||||||
|
const tornadoTrees = await getTornadoTrees()
|
||||||
|
const newEvents = {}
|
||||||
|
const startBlock = Number((await redis.get('lastBlock')) || STARTING_BLOCK) + 1
|
||||||
|
const netId = await web3.eth.getChainId()
|
||||||
|
const currentBlock = await web3.eth.getBlockNumber()
|
||||||
|
const explorer = `https://${prefix[netId]}etherscan.io`
|
||||||
|
const instances = Object.values(config.instances[`netId${netId}`].eth.instanceAddress)
|
||||||
|
console.log(`Getting events for blocks ${startBlock} to ${currentBlock}`)
|
||||||
|
for (const type of ['deposit', 'withdrawal']) {
|
||||||
|
const newRegisteredEvents = await getRegisteredEvents({ type })
|
||||||
|
const tornadoEvents = await getTornadoEvents({ instances, startBlock, endBlock: currentBlock, type })
|
||||||
|
|
||||||
|
newEvents[type] = newRegisteredEvents.map((e) => tornadoEvents[e])
|
||||||
|
if (newEvents[type].some((e) => e === undefined)) {
|
||||||
|
console.log('Tree contract expects unknown tornado event')
|
||||||
|
console.log(newRegisteredEvents.find((e) => !tornadoEvents[e]))
|
||||||
|
if (isRetry) {
|
||||||
|
console.log('Quitting')
|
||||||
|
} else {
|
||||||
|
console.log('Retrying')
|
||||||
|
await redis.set('lastBlock', STARTING_BLOCK)
|
||||||
|
await main(true)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (newEvents['deposit'].length || newEvents['withdrawal'].length) {
|
||||||
|
const chunks = {}
|
||||||
|
for (const type of ['deposit', 'withdrawal']) {
|
||||||
|
chunks[type] = newEvents[type].splice(0, process.env.INSERT_BATCH_SIZE)
|
||||||
|
}
|
||||||
|
console.log(
|
||||||
|
`Submitting tree update with ${chunks['deposit'].length} deposits and ${chunks['withdrawal'].length} withdrawals`,
|
||||||
|
)
|
||||||
|
const data = tornadoTrees.methods.updateRoots(chunks['deposit'], chunks['withdrawal']).encodeABI()
|
||||||
|
const tx = txManager.createTx({
|
||||||
|
to: tornadoTrees._address,
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
|
||||||
|
try {
|
||||||
|
await tx
|
||||||
|
.send()
|
||||||
|
.on('transactionHash', (hash) => console.log(`Transaction: ${explorer}/tx/${hash}`))
|
||||||
|
.on('mined', (receipt) => console.log('Mined in block', receipt.blockNumber))
|
||||||
|
.on('confirmations', (n) => console.log(`Got ${n} confirmations`))
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Tx failed...', e)
|
||||||
|
if (isRetry) {
|
||||||
|
console.log('Quitting')
|
||||||
|
} else {
|
||||||
|
await redis.set('lastBlock', STARTING_BLOCK)
|
||||||
|
console.log('Retrying')
|
||||||
|
await main(true)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await redis.set('lastBlock', currentBlock)
|
||||||
|
console.log('Done')
|
||||||
|
}
|
||||||
|
|
||||||
|
cron.job(process.env.CRON_EXPRESSION, main, null, true, null, null, true)
|
|
@ -0,0 +1,29 @@
|
||||||
|
const Web3 = require('web3')
|
||||||
|
const web3 = new Web3(process.env.RPC_URL)
|
||||||
|
const aggregator = new web3.eth.Contract(require('../abi/Aggregator.abi.json'), process.env.AGGREGATOR)
|
||||||
|
const ens = require('eth-ens-namehash')
|
||||||
|
|
||||||
|
class ENSResolver {
|
||||||
|
constructor() {
|
||||||
|
this.addresses = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
async resolve(domains) {
|
||||||
|
if (!Array.isArray(domains)) {
|
||||||
|
domains = [domains]
|
||||||
|
}
|
||||||
|
|
||||||
|
const unresolved = domains.filter((d) => !this.addresses[d])
|
||||||
|
if (unresolved.length) {
|
||||||
|
const resolved = await aggregator.methods.bulkResolve(unresolved.map(ens.hash)).call()
|
||||||
|
for (let i = 0; i < resolved.length; i++) {
|
||||||
|
this.addresses[domains[i]] = resolved[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const addresses = domains.map((domain) => this.addresses[domain])
|
||||||
|
return addresses.length === 1 ? addresses[0] : addresses
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ENSResolver
|
|
@ -0,0 +1,37 @@
|
||||||
|
require('dotenv').config()
|
||||||
|
const Web3 = require('web3')
|
||||||
|
const { TxManager } = require('tx-manager')
|
||||||
|
const tornadoTreesAbi = require('../abi/tornadoTrees.json')
|
||||||
|
const Redis = require('ioredis')
|
||||||
|
const ENSResolver = require('./resolver')
|
||||||
|
const resolver = new ENSResolver()
|
||||||
|
const redis = new Redis(process.env.REDIS_URL)
|
||||||
|
const config = require('torn-token')
|
||||||
|
let tornadoTrees
|
||||||
|
|
||||||
|
const web3 = new Web3(process.env.RPC_URL)
|
||||||
|
web3.eth.accounts.wallet.add('0x' + process.env.PRIVATE_KEY)
|
||||||
|
web3.eth.defaultAccount = web3.eth.accounts.privateKeyToAccount('0x' + process.env.PRIVATE_KEY).address
|
||||||
|
|
||||||
|
const txManager = new TxManager({
|
||||||
|
privateKey: process.env.PRIVATE_KEY,
|
||||||
|
rpcUrl: process.env.RPC_URL,
|
||||||
|
config: {
|
||||||
|
CONFIRMATIONS: process.env.CONFIRMATION_BLOCKS,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
async function getTornadoTrees() {
|
||||||
|
if (!tornadoTrees) {
|
||||||
|
tornadoTrees = new web3.eth.Contract(tornadoTreesAbi, await resolver.resolve(config.tornadoTrees.address))
|
||||||
|
console.log('Resolved tornadoTrees contract:', tornadoTrees._address)
|
||||||
|
}
|
||||||
|
return tornadoTrees
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
web3,
|
||||||
|
redis,
|
||||||
|
getTornadoTrees,
|
||||||
|
txManager,
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
const { bigInt } = require('snarkjs')
|
||||||
|
const { poseidon } = require('circomlib')
|
||||||
|
|
||||||
|
/** BigNumber to hex string of specified length */
|
||||||
|
const toFixedHex = (number, length = 32) =>
|
||||||
|
'0x' +
|
||||||
|
(number instanceof Buffer ? number.toString('hex') : bigInt(number).toString(16)).padStart(length * 2, '0')
|
||||||
|
|
||||||
|
const poseidonHash = (items) => toFixedHex(poseidon(items))
|
||||||
|
const poseidonHash2 = (a, b) => poseidonHash([a, b])
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
toFixedHex,
|
||||||
|
poseidonHash,
|
||||||
|
poseidonHash2,
|
||||||
|
}
|
Loading…
Reference in New Issue