Compare commits

...

24 Commits

Author SHA1 Message Date
5db3741ea9 Bump required node version to 16 2023-09-18 07:11:28 -07:00
427ebea84b Resolve dependencies via self-hosted registry & move package to tornado scope 2023-09-18 06:45:35 -07:00
h-ivor
2a26a90940 package.json 2.1.5 2021-09-23 21:16:55 +03:00
h-ivor
9d0262189e lint 2021-09-23 21:16:55 +03:00
fried
b3277137ba fix constructor visibility 2021-09-23 21:16:55 +03:00
Alexey
d93d7c8870 lint 2021-08-23 13:20:32 +03:00
Alexey
9f095bfcb2 updates all functions so they can be easily overriden 2021-08-13 17:05:23 +03:00
nikdementev
6d219e19ee fix: optimism poseidon hash for events 2021-04-02 21:35:59 +03:00
Alexey
18518856ff fix Note.fromString method parsing 2021-04-01 12:04:38 +03:00
poma
ca446c79cd
proxy light 2021-03-29 09:10:32 +03:00
poma
3ae6087f65
update dependency 2021-03-22 20:38:23 +03:00
poma
87babe41d3
update version 2021-03-22 20:30:14 +03:00
poma
e42a2afb43
Fix CVF-49 2021-03-22 20:30:01 +03:00
poma
adf675edd9
Rename event 2021-03-21 01:01:44 +03:00
poma
15eaac2f2e
Fix CVF-52 2021-03-21 01:01:35 +03:00
poma
cd2ea92084
Fix CVF-53 2021-03-21 01:00:59 +03:00
poma
6850d6a6c4
Fix CVF-55, CVF-54 2021-03-21 00:57:22 +03:00
poma
97b486b9ba
fix interface 2021-03-16 23:51:35 +03:00
poma
f02347500b
bump version 2021-03-16 22:39:22 +03:00
Alexey
a326f3e14f backupNotes 2021-03-16 01:05:33 +04:00
Alexey
b9570ea3c3 _updateInstance updates 2021-03-12 15:12:20 +03:00
Alexey
44e9d7d645 refactoring 2021-03-12 15:12:20 +03:00
Alexey
5a82105f24 updates 2021-03-12 15:12:20 +03:00
poma
01ca620e7c
InstanceStateUpdate event 2021-03-06 15:44:17 +03:00
20 changed files with 6075 additions and 2663 deletions

1
.npmrc Normal file
View File

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

View File

@ -2,11 +2,11 @@
## v2 changes
`TornadoTrees.sol` is no longer part of this project. It migrated to [tornado-trees](https://github.com/tornadocash/tornado-trees)
`TornadoTrees.sol` is no longer part of this project. It migrated to [@tornado/trees](https://git.tornado.ws/tornado-packages/tornado-trees)
## Dependencies
1. node 12
1. node 16
2. yarn
3. zkutil (`brew install rust && cargo install zkutil`)

View File

@ -1,5 +1,5 @@
include "../node_modules/circomlib/circuits/poseidon.circom";
include "../node_modules/circomlib/circuits/bitify.circom";
include "../node_modules/@tornado/circomlib/circuits/poseidon.circom";
include "../node_modules/@tornado/circomlib/circuits/bitify.circom";
// Computes Poseidon([left, right])
template HashLeftRight() {

View File

@ -1,6 +1,6 @@
include "../node_modules/circomlib/circuits/poseidon.circom";
include "../node_modules/circomlib/circuits/bitify.circom";
include "../node_modules/circomlib/circuits/comparators.circom";
include "../node_modules/@tornado/circomlib/circuits/poseidon.circom";
include "../node_modules/@tornado/circomlib/circuits/bitify.circom";
include "../node_modules/@tornado/circomlib/circuits/comparators.circom";
include "./Utils.circom";
include "./MerkleTree.circom";
include "./MerkleTreeUpdater.circom";

View File

@ -1,5 +1,5 @@
include "../node_modules/circomlib/circuits/bitify.circom";
include "../node_modules/circomlib/circuits/pedersen.circom";
include "../node_modules/@tornado/circomlib/circuits/bitify.circom";
include "../node_modules/@tornado/circomlib/circuits/pedersen.circom";
// computes Pedersen(nullifier + secret)
template TornadoCommitmentHasher() {

View File

@ -1,5 +1,5 @@
include "../node_modules/circomlib/circuits/poseidon.circom";
include "../node_modules/circomlib/circuits/bitify.circom";
include "../node_modules/@tornado/circomlib/circuits/poseidon.circom";
include "../node_modules/@tornado/circomlib/circuits/bitify.circom";
include "./Utils.circom";
include "./MerkleTree.circom";
include "./MerkleTreeUpdater.circom";

View File

@ -5,7 +5,7 @@ pragma experimental ABIEncoderV2;
import "./interfaces/IVerifier.sol";
import "./interfaces/IRewardSwap.sol";
import "tornado-trees/contracts/TornadoTrees.sol";
import "@tornado/trees/contracts/TornadoTrees.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "torn-token/contracts/ENS.sol";
@ -105,11 +105,9 @@ contract Miner is EnsResolve {
_setRates(_rates);
// prettier-ignore
_setVerifiers([
IVerifier(resolve(_verifiers[0])),
IVerifier(resolve(_verifiers[1])),
IVerifier(resolve(_verifiers[2]))
]);
_setVerifiers(
[IVerifier(resolve(_verifiers[0])), IVerifier(resolve(_verifiers[1])), IVerifier(resolve(_verifiers[2]))]
);
}
function reward(bytes memory _proof, RewardArgs memory _args) public {
@ -239,15 +237,15 @@ contract Miner is EnsResolve {
// ------VIEW-------
/**
@dev Whether the root is present in the root history
*/
* @dev Whether the root is present in the root history
*/
function isKnownAccountRoot(bytes32 _root, uint256 _index) public view returns (bool) {
return _root != 0 && accountRoots[_index % ACCOUNT_ROOT_HISTORY_SIZE] == _root;
}
/**
@dev Returns the last root
*/
* @dev Returns the last root
*/
function getLastAccountRoot() public view returns (bytes32) {
return accountRoots[accountCount % ACCOUNT_ROOT_HISTORY_SIZE];
}

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
pragma solidity >=0.6.0 <0.8.0;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
@ -13,15 +13,25 @@ contract TornadoProxy {
using SafeERC20 for IERC20;
event EncryptedNote(address indexed sender, bytes encryptedNote);
enum InstanceState { Disabled, Enabled, Mineable }
event InstanceStateUpdated(ITornadoInstance indexed instance, InstanceState state);
event TornadoTreesUpdated(ITornadoTrees addr);
enum InstanceState { DISABLED, ENABLED, MINEABLE }
struct Instance {
address instance;
bool isERC20;
IERC20 token;
InstanceState state;
}
struct Tornado {
ITornadoInstance addr;
Instance instance;
}
ITornadoTrees public tornadoTrees;
address public immutable governance;
mapping(ITornadoInstance => InstanceState) public instances;
mapping(ITornadoInstance => Instance) public instances;
modifier onlyGovernance() {
require(msg.sender == governance, "Not authorized");
@ -31,13 +41,13 @@ contract TornadoProxy {
constructor(
address _tornadoTrees,
address _governance,
Instance[] memory _instances
Tornado[] memory _instances
) public {
tornadoTrees = ITornadoTrees(_tornadoTrees);
governance = _governance;
for (uint256 i = 0; i < _instances.length; i++) {
instances[ITornadoInstance(_instances[i].instance)] = _instances[i].state;
_updateInstance(_instances[i]);
}
}
@ -45,11 +55,16 @@ contract TornadoProxy {
ITornadoInstance _tornado,
bytes32 _commitment,
bytes calldata _encryptedNote
) external payable {
require(instances[_tornado] != InstanceState.Disabled, "The instance is not supported");
) public payable virtual {
Instance memory instance = instances[_tornado];
require(instance.state != InstanceState.DISABLED, "The instance is not supported");
if (instance.isERC20) {
instance.token.safeTransferFrom(msg.sender, address(this), _tornado.denomination());
}
_tornado.deposit{ value: msg.value }(_commitment);
if (instances[_tornado] == InstanceState.Mineable) {
if (instance.state == InstanceState.MINEABLE) {
tornadoTrees.registerDeposit(address(_tornado), _commitment);
}
emit EncryptedNote(msg.sender, _encryptedNote);
@ -64,42 +79,66 @@ contract TornadoProxy {
address payable _relayer,
uint256 _fee,
uint256 _refund
) external payable {
require(instances[_tornado] != InstanceState.Disabled, "The instance is not supported");
) public payable virtual {
Instance memory instance = instances[_tornado];
require(instance.state != InstanceState.DISABLED, "The instance is not supported");
_tornado.withdraw{ value: msg.value }(_proof, _root, _nullifierHash, _recipient, _relayer, _fee, _refund);
if (instances[_tornado] == InstanceState.Mineable) {
if (instance.state == InstanceState.MINEABLE) {
tornadoTrees.registerWithdrawal(address(_tornado), _nullifierHash);
}
}
function updateInstance(ITornadoInstance _instance, InstanceState _state) external onlyGovernance {
instances[_instance] = _state;
function backupNotes(bytes[] calldata _encryptedNotes) external virtual {
for (uint256 i = 0; i < _encryptedNotes.length; i++) {
emit EncryptedNote(msg.sender, _encryptedNotes[i]);
}
}
function setTornadoTreesContract(address _instance) external onlyGovernance {
tornadoTrees = ITornadoTrees(_instance);
function updateInstance(Tornado calldata _tornado) external virtual onlyGovernance {
_updateInstance(_tornado);
}
function setTornadoTreesContract(ITornadoTrees _tornadoTrees) external virtual onlyGovernance {
tornadoTrees = _tornadoTrees;
emit TornadoTreesUpdated(_tornadoTrees);
}
/// @dev Method to claim junk and accidentally sent tokens
function rescueTokens(
IERC20 _token,
address payable _to,
uint256 _balance
) external onlyGovernance {
uint256 _amount
) external virtual onlyGovernance {
require(_to != address(0), "TORN: can not send to zero address");
if (_token == IERC20(0)) {
// for Ether
uint256 totalBalance = address(this).balance;
uint256 balance = _balance == 0 ? totalBalance : Math.min(totalBalance, _balance);
uint256 balance = Math.min(totalBalance, _amount);
_to.transfer(balance);
} else {
// any other erc20
uint256 totalBalance = _token.balanceOf(address(this));
uint256 balance = _balance == 0 ? totalBalance : Math.min(totalBalance, _balance);
uint256 balance = Math.min(totalBalance, _amount);
require(balance > 0, "TORN: trying to send 0 balance");
_token.safeTransfer(_to, balance);
}
}
function _updateInstance(Tornado memory _tornado) internal {
instances[_tornado.addr] = _tornado.instance;
if (_tornado.instance.isERC20) {
IERC20 token = IERC20(_tornado.addr.token());
require(token == _tornado.instance.token, "Incorrect token");
uint256 allowance = token.allowance(address(this), address(_tornado.addr));
if (_tornado.instance.state != InstanceState.DISABLED && allowance == 0) {
token.safeApprove(address(_tornado.addr), uint256(-1));
} else if (_tornado.instance.state == InstanceState.DISABLED && allowance != 0) {
token.safeApprove(address(_tornado.addr), 0);
}
}
emit InstanceStateUpdated(_tornado.addr, _tornado.instance.state);
}
}

View File

@ -0,0 +1,36 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
import "./interfaces/ITornadoInstance.sol";
contract TornadoProxyLight {
event EncryptedNote(address indexed sender, bytes encryptedNote);
function deposit(
ITornadoInstance _tornado,
bytes32 _commitment,
bytes calldata _encryptedNote
) external payable {
_tornado.deposit{ value: msg.value }(_commitment);
emit EncryptedNote(msg.sender, _encryptedNote);
}
function withdraw(
ITornadoInstance _tornado,
bytes calldata _proof,
bytes32 _root,
bytes32 _nullifierHash,
address payable _recipient,
address payable _relayer,
uint256 _fee,
uint256 _refund
) external payable {
_tornado.withdraw{ value: msg.value }(_proof, _root, _nullifierHash, _recipient, _relayer, _fee, _refund);
}
function backupNotes(bytes[] calldata _encryptedNotes) external {
for (uint256 i = 0; i < _encryptedNotes.length; i++) {
emit EncryptedNote(msg.sender, _encryptedNotes[i]);
}
}
}

View File

@ -1,8 +1,12 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
pragma solidity >=0.6.0 <0.8.0;
interface ITornadoInstance {
function token() external view returns (address);
function denomination() external view returns (uint256);
function deposit(bytes32 commitment) external payable;
function withdraw(

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
pragma solidity >=0.6.0 <0.8.0;
interface ITornadoTrees {
function registerDeposit(address instance, bytes32 commitment) external;

View File

@ -3,4 +3,4 @@
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
import "tornado-trees/contracts/mocks/TornadoTreesMock.sol";
import "@tornado/trees/contracts/mocks/TornadoTreesMock.sol";

View File

@ -2,4 +2,4 @@
pragma solidity ^0.6.0;
import "tornado-trees/contracts/mocks/TornadoTreesV1Mock.sol";
import "@tornado/trees/contracts/mocks/TornadoTreesV1Mock.sol";

View File

@ -1,8 +1,8 @@
{
"name": "tornado-anonymity-mining",
"version": "2.0.2",
"name": "@tornado/anonymity-mining",
"version": "2.1.5",
"main": "index.js",
"repository": "https://github.com/tornadocash/tornado-anonymity-mining.git",
"repository": "https://git.tornado.ws/tornado-packages/anonymity-mining.git",
"author": "Tornadocash team <hello@tornado.cash>",
"license": "MIT",
"files": [
@ -47,13 +47,13 @@
"truffle-plugin-verify": "^0.3.11"
},
"dependencies": {
"circomlib": "git+https://github.com/tornadocash/circomlib.git#3b492f9801573eebcfe1b6c584afe8a3beecf2b4",
"@tornado/circomlib": "^0.0.21",
"@tornado/fixed-merkle-tree": "0.3.4",
"@tornado/snarkjs": "0.1.20",
"@tornado/trees": "^0.0.11",
"@tornado/websnark": "^0.0.4",
"decimal.js": "^10.2.0",
"eth-sig-util": "^2.5.3",
"fixed-merkle-tree": "^0.3.4",
"snarkjs": "git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5",
"tornado-trees": "^0.0.7",
"web3": "^1.2.11",
"websnark": "git+https://github.com/tornadocash/websnark.git#86a526718cd6f6f5d31bdb1fe26a9ec8819f633e"
"web3": "^1.2.11"
}
}

View File

@ -3,6 +3,6 @@ npx circom circuits/$1.circom -o build/circuits/$1.json
npx snarkjs info -c build/circuits/$1.json
zkutil setup -c build/circuits/$1.json -p build/circuits/$1.params
zkutil export-keys -c build/circuits/$1.json -p build/circuits/$1.params --pk build/circuits/$1_proving_key.json --vk build/circuits/$1_verification_key.json
node node_modules/websnark/tools/buildpkey.js -i build/circuits/$1_proving_key.json -o build/circuits/$1_proving_key.bin
node node_modules/@tornado/websnark/tools/buildpkey.js -i build/circuits/$1_proving_key.json -o build/circuits/$1_proving_key.bin
zkutil generate-verifier -p build/circuits/$1.params -v build/circuits/${1}Verifier.sol
sed -i.bak "s/contract Verifier/contract ${1}Verifier/g" build/circuits/${1}Verifier.sol

View File

@ -11,9 +11,9 @@ const {
RewardArgs,
} = require('./utils')
const Account = require('./account')
const MerkleTree = require('fixed-merkle-tree')
const websnarkUtils = require('websnark/src/utils')
const buildGroth16 = require('websnark/src/groth16')
const MerkleTree = require('@tornado/fixed-merkle-tree')
const websnarkUtils = require('@tornado/websnark/src/utils')
const buildGroth16 = require('@tornado/websnark/src/groth16')
const web3 = new Web3()
@ -131,7 +131,13 @@ class Controller {
const newAccount = new Account({ amount: newAmount })
depositDataEvents = depositDataEvents || (await this._fetchDepositDataEvents())
const depositLeaves = depositDataEvents.map((x) => poseidonHash([x.instance, x.hash, x.block]))
const depositLeaves = depositDataEvents.map((x) => {
if (x.poseidon) {
return x.poseidon
}
return poseidonHash([x.instance, x.hash, x.block])
})
const depositTree = new MerkleTree(this.merkleTreeHeight, depositLeaves, { hashFunction: poseidonHash2 })
const depositItem = depositDataEvents.filter((x) => x.hash === toFixedHex(note.commitment))
if (depositItem.length === 0) {
@ -140,7 +146,13 @@ class Controller {
const depositPath = depositTree.path(depositItem[0].index)
withdrawalDataEvents = withdrawalDataEvents || (await this._fetchWithdrawalDataEvents())
const withdrawalLeaves = withdrawalDataEvents.map((x) => poseidonHash([x.instance, x.hash, x.block]))
const withdrawalLeaves = withdrawalDataEvents.map((x) => {
if (x.poseidon) {
return x.poseidon
}
return poseidonHash([x.instance, x.hash, x.block])
})
const withdrawalTree = new MerkleTree(this.merkleTreeHeight, withdrawalLeaves, {
hashFunction: poseidonHash2,
})

View File

@ -25,11 +25,10 @@ class Note {
}
static fromString(note, instance, depositBlock, withdrawalBlock) {
note = note.split('-')
const [, currency, amount, netId] = note
const hexNote = note[4].slice(2)
const nullifier = new BN(hexNote.slice(0, 62), 16, 'le')
const secret = new BN(hexNote.slice(62), 16, 'le')
const [, currency, amount, netId, noteHex] = note.split('-')
const noteBuff = Buffer.from(noteHex.slice(2), 'hex')
const nullifier = new BN(noteBuff.slice(0, 31), 16, 'le')
const secret = new BN(noteBuff.slice(31), 16, 'le')
return new Note({
secret,
nullifier,

View File

@ -1,10 +1,10 @@
const crypto = require('crypto')
const Decimal = require('decimal.js')
const { bigInt } = require('snarkjs')
const { bigInt } = require('@tornado/snarkjs')
const { toBN, soliditySha3 } = require('web3-utils')
const Web3 = require('web3')
const web3 = new Web3()
const { babyJub, pedersenHash, mimcsponge, poseidon } = require('circomlib')
const { babyJub, pedersenHash, mimcsponge, poseidon } = require('@tornado/circomlib')
const RewardExtData = {
RewardExtData: {

View File

@ -34,7 +34,7 @@ const provingKeys = {
withdrawProvingKey: fs.readFileSync('./build/circuits/Withdraw_proving_key.bin').buffer,
treeUpdateProvingKey: fs.readFileSync('./build/circuits/TreeUpdate_proving_key.bin').buffer,
}
const MerkleTree = require('fixed-merkle-tree')
const MerkleTree = require('@tornado/fixed-merkle-tree')
// Set time to beginning of a second
async function timeReset() {
@ -225,6 +225,22 @@ contract('Miner', (accounts) => {
note.commitment.should.be.eq.BN(
toBN('0x1a08fd10dae9806ce25b62582e44d237c1cb9f8d6bf73e756f18d0e5d7a7351a'),
)
const note1 = Note.fromString(
'tornado-eth-1-5-0x00b9787ae8b877cc612acfc3d46eb1303c618ef386cb4383b75be5b300ac9b94818f3f7a589b4667612e879dbfd44198231c86aaa412a3770fd86d8fc045',
'0x8b3f5393bA08c24cc7ff5A66a832562aAB7bC95f',
10,
15,
)
note1.secret.should.be.eq.BN(toBN('0x45c08f6dd80f77a312a4aa861c239841d4bf9d872e6167469b587a3f8f8194'))
note1.nullifier.should.be.eq.BN(
toBN('0x9bac00b3e55bb78343cb86f38e613c30b16ed4c3cf2a61cc77b8e87a78b900'),
)
note1.nullifierHash.should.be.eq.BN(
toBN('0x1892018e434ed0476992c7e05e6022b69eacf746a978191117194d180104aed1'),
)
note1.commitment.should.be.eq.BN(
toBN('0x270a865e2bf7de26b0a6de08c527f4d13e2b49026f6aaeeea0866a9dd39e19f6'),
)
})
})

8497
yarn.lock

File diff suppressed because it is too large Load Diff