Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
02642f122d | |||
|
d95b53862f | ||
|
f6bfbf09be | ||
|
17fc574af3 | ||
|
a18cc18e91 | ||
|
790f049719 | ||
|
53e7a69556 | ||
|
8a82afba42 | ||
|
a04fe966f7 | ||
|
9321740be7 | ||
|
a3da216e03 | ||
|
87ce87532e | ||
|
a8b93f6d5b | ||
|
7d076e8af1 | ||
|
0895afbc30 | ||
|
e8954ec6ce | ||
|
73b9369abc | ||
|
628d3bd64a |
1
.npmrc
Normal file
1
.npmrc
Normal file
@ -0,0 +1 @@
|
|||||||
|
@tornado:registry=https://git.tornado.ws/api/packages/tornado-packages/npm/
|
@ -1,14 +1,16 @@
|
|||||||
include "../node_modules/circomlib/circuits/poseidon.circom";
|
include "../node_modules/@tornado/circomlib/circuits/poseidon.circom";
|
||||||
include "../node_modules/circomlib/circuits/bitify.circom";
|
include "../node_modules/@tornado/circomlib/circuits/bitify.circom";
|
||||||
include "./MerkleTreeUpdater.circom";
|
include "./MerkleTreeUpdater.circom";
|
||||||
include "./Utils.circom";
|
include "./TreeUpdateArgsHasher.circom";
|
||||||
|
|
||||||
|
// Computes hashes of the next tree layer
|
||||||
template TreeLayer(height) {
|
template TreeLayer(height) {
|
||||||
signal input ins[1 << (height + 1)];
|
var nItems = 1 << height;
|
||||||
signal output outs[1 << height];
|
signal input ins[nItems * 2];
|
||||||
|
signal output outs[nItems];
|
||||||
|
|
||||||
component hash[1 << height];
|
component hash[nItems];
|
||||||
for(var i = 0; i < (1 << height); i++) {
|
for(var i = 0; i < nItems; i++) {
|
||||||
hash[i] = HashLeftRight();
|
hash[i] = HashLeftRight();
|
||||||
hash[i].left <== ins[i * 2];
|
hash[i].left <== ins[i * 2];
|
||||||
hash[i].right <== ins[i * 2 + 1];
|
hash[i].right <== ins[i * 2 + 1];
|
||||||
@ -18,6 +20,8 @@ template TreeLayer(height) {
|
|||||||
|
|
||||||
// Inserts a leaf batch into a tree
|
// Inserts a leaf batch into a tree
|
||||||
// Checks that tree previously contained zero leaves in the same position
|
// Checks that tree previously contained zero leaves in the same position
|
||||||
|
// Hashes leaves with Poseidon hash
|
||||||
|
// `batchLevels` should be less than `levels`
|
||||||
template BatchTreeUpdate(levels, batchLevels, zeroBatchLeaf) {
|
template BatchTreeUpdate(levels, batchLevels, zeroBatchLeaf) {
|
||||||
var height = levels - batchLevels;
|
var height = levels - batchLevels;
|
||||||
var nLeaves = 1 << batchLevels;
|
var nLeaves = 1 << batchLevels;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
include "../node_modules/circomlib/circuits/poseidon.circom";
|
include "../node_modules/@tornado/circomlib/circuits/poseidon.circom";
|
||||||
include "../node_modules/circomlib/circuits/bitify.circom";
|
include "../node_modules/@tornado/circomlib/circuits/bitify.circom";
|
||||||
|
|
||||||
// Computes Poseidon([left, right])
|
// Computes Poseidon([left, right])
|
||||||
template HashLeftRight() {
|
template HashLeftRight() {
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
include "../node_modules/circomlib/circuits/bitify.circom";
|
include "../node_modules/@tornado/circomlib/circuits/bitify.circom";
|
||||||
include "../node_modules/circomlib/circuits/sha256/sha256.circom";
|
include "../node_modules/@tornado/circomlib/circuits/sha256/sha256.circom";
|
||||||
|
|
||||||
|
// Computes a SHA256 hash of all inputs packed into a byte array
|
||||||
|
// Field elements are padded to 256 bits with zeroes
|
||||||
template TreeUpdateArgsHasher(nLeaves) {
|
template TreeUpdateArgsHasher(nLeaves) {
|
||||||
signal private input oldRoot;
|
signal input oldRoot;
|
||||||
signal private input newRoot;
|
signal input newRoot;
|
||||||
signal private input pathIndices;
|
signal input pathIndices;
|
||||||
signal private input instances[nLeaves];
|
signal input instances[nLeaves];
|
||||||
signal private input hashes[nLeaves];
|
signal input hashes[nLeaves];
|
||||||
signal private input blocks[nLeaves];
|
signal input blocks[nLeaves];
|
||||||
signal output out;
|
signal output out;
|
||||||
|
|
||||||
var header = 256 + 256 + 32;
|
var header = 256 + 256 + 32;
|
||||||
var bitsPerLeaf = 160 + 256 + 32;
|
var bitsPerLeaf = 256 + 160 + 32;
|
||||||
component hasher = Sha256(header + nLeaves * bitsPerLeaf);
|
component hasher = Sha256(header + nLeaves * bitsPerLeaf);
|
||||||
|
|
||||||
// the range check on old root is optional, it's enforced by smart contract anyway
|
// the range check on old root is optional, it's enforced by smart contract anyway
|
||||||
@ -26,18 +28,20 @@ template TreeUpdateArgsHasher(nLeaves) {
|
|||||||
bitsNewRoot.in <== newRoot;
|
bitsNewRoot.in <== newRoot;
|
||||||
bitsPathIndices.in <== pathIndices;
|
bitsPathIndices.in <== pathIndices;
|
||||||
|
|
||||||
hasher.in[0] <== 0;
|
var index = 0;
|
||||||
hasher.in[1] <== 0;
|
|
||||||
|
hasher.in[index++] <== 0;
|
||||||
|
hasher.in[index++] <== 0;
|
||||||
for(var i = 0; i < 254; i++) {
|
for(var i = 0; i < 254; i++) {
|
||||||
hasher.in[i + 2] <== bitsOldRoot.out[253 - i];
|
hasher.in[index++] <== bitsOldRoot.out[253 - i];
|
||||||
}
|
}
|
||||||
hasher.in[256] <== 0;
|
hasher.in[index++] <== 0;
|
||||||
hasher.in[257] <== 0;
|
hasher.in[index++] <== 0;
|
||||||
for(var i = 0; i < 254; i++) {
|
for(var i = 0; i < 254; i++) {
|
||||||
hasher.in[i + 258] <== bitsNewRoot.out[253 - i];
|
hasher.in[index++] <== bitsNewRoot.out[253 - i];
|
||||||
}
|
}
|
||||||
for(var i = 0; i < 32; i++) {
|
for(var i = 0; i < 32; i++) {
|
||||||
hasher.in[i + 512] <== bitsPathIndices.out[31 - i];
|
hasher.in[index++] <== bitsPathIndices.out[31 - i];
|
||||||
}
|
}
|
||||||
for(var leaf = 0; leaf < nLeaves; leaf++) {
|
for(var leaf = 0; leaf < nLeaves; leaf++) {
|
||||||
// the range check on hash is optional, it's enforced by the smart contract anyway
|
// the range check on hash is optional, it's enforced by the smart contract anyway
|
||||||
@ -47,16 +51,16 @@ template TreeUpdateArgsHasher(nLeaves) {
|
|||||||
bitsHash[leaf].in <== hashes[leaf];
|
bitsHash[leaf].in <== hashes[leaf];
|
||||||
bitsInstance[leaf].in <== instances[leaf];
|
bitsInstance[leaf].in <== instances[leaf];
|
||||||
bitsBlock[leaf].in <== blocks[leaf];
|
bitsBlock[leaf].in <== blocks[leaf];
|
||||||
hasher.in[header + leaf * bitsPerLeaf + 0] <== 0;
|
hasher.in[index++] <== 0;
|
||||||
hasher.in[header + leaf * bitsPerLeaf + 1] <== 0;
|
hasher.in[index++] <== 0;
|
||||||
for(var i = 0; i < 254; i++) {
|
for(var i = 0; i < 254; i++) {
|
||||||
hasher.in[header + leaf * bitsPerLeaf + i + 2] <== bitsHash[leaf].out[253 - i];
|
hasher.in[index++] <== bitsHash[leaf].out[253 - i];
|
||||||
}
|
}
|
||||||
for(var i = 0; i < 160; i++) {
|
for(var i = 0; i < 160; i++) {
|
||||||
hasher.in[header + leaf * bitsPerLeaf + i + 256] <== bitsInstance[leaf].out[159 - i];
|
hasher.in[index++] <== bitsInstance[leaf].out[159 - i];
|
||||||
}
|
}
|
||||||
for(var i = 0; i < 32; i++) {
|
for(var i = 0; i < 32; i++) {
|
||||||
hasher.in[header + leaf * bitsPerLeaf + i + 416] <== bitsBlock[leaf].out[31 - i];
|
hasher.in[index++] <== bitsBlock[leaf].out[31 - i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
component b2n = Bits2Num(256);
|
component b2n = Bits2Num(256);
|
@ -10,7 +10,11 @@ contract AdminUpgradeableProxy is TransparentUpgradeableProxy {
|
|||||||
/**
|
/**
|
||||||
* @dev Initializes an upgradeable proxy backed by the implementation at `_logic`.
|
* @dev Initializes an upgradeable proxy backed by the implementation at `_logic`.
|
||||||
*/
|
*/
|
||||||
constructor(address _logic, bytes memory _data) public payable TransparentUpgradeableProxy(_logic, msg.sender, _data) {}
|
constructor(
|
||||||
|
address _logic,
|
||||||
|
address _admin,
|
||||||
|
bytes memory _data
|
||||||
|
) public payable TransparentUpgradeableProxy(_logic, _admin, _data) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Override to allow admin access the fallback function.
|
* @dev Override to allow admin access the fallback function.
|
||||||
|
@ -36,6 +36,8 @@ contract TornadoTrees is Initializable {
|
|||||||
|
|
||||||
event DepositData(address instance, bytes32 indexed hash, uint256 block, uint256 index);
|
event DepositData(address instance, bytes32 indexed hash, uint256 block, uint256 index);
|
||||||
event WithdrawalData(address instance, bytes32 indexed hash, uint256 block, uint256 index);
|
event WithdrawalData(address instance, bytes32 indexed hash, uint256 block, uint256 index);
|
||||||
|
event VerifierUpdated(address newVerifier);
|
||||||
|
event ProxyUpdated(address newProxy);
|
||||||
|
|
||||||
struct TreeLeaf {
|
struct TreeLeaf {
|
||||||
bytes32 hash;
|
bytes32 hash;
|
||||||
@ -100,6 +102,7 @@ contract TornadoTrees is Initializable {
|
|||||||
withdrawalsLength = withdrawalsV1Length;
|
withdrawalsLength = withdrawalsV1Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @dev Queue a new deposit data to be inserted into a merkle tree
|
||||||
function registerDeposit(address _instance, bytes32 _commitment) public onlyTornadoProxy {
|
function registerDeposit(address _instance, bytes32 _commitment) public onlyTornadoProxy {
|
||||||
uint256 _depositsLength = depositsLength;
|
uint256 _depositsLength = depositsLength;
|
||||||
deposits[_depositsLength] = keccak256(abi.encode(_instance, _commitment, blockNumber()));
|
deposits[_depositsLength] = keccak256(abi.encode(_instance, _commitment, blockNumber()));
|
||||||
@ -107,6 +110,7 @@ contract TornadoTrees is Initializable {
|
|||||||
depositsLength = _depositsLength + 1;
|
depositsLength = _depositsLength + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @dev Queue a new withdrawal data to be inserted into a merkle tree
|
||||||
function registerWithdrawal(address _instance, bytes32 _nullifierHash) public onlyTornadoProxy {
|
function registerWithdrawal(address _instance, bytes32 _nullifierHash) public onlyTornadoProxy {
|
||||||
uint256 _withdrawalsLength = withdrawalsLength;
|
uint256 _withdrawalsLength = withdrawalsLength;
|
||||||
withdrawals[_withdrawalsLength] = keccak256(abi.encode(_instance, _nullifierHash, blockNumber()));
|
withdrawals[_withdrawalsLength] = keccak256(abi.encode(_instance, _nullifierHash, blockNumber()));
|
||||||
@ -114,6 +118,13 @@ contract TornadoTrees is Initializable {
|
|||||||
withdrawalsLength = _withdrawalsLength + 1;
|
withdrawalsLength = _withdrawalsLength + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @dev Insert a full batch of queued deposits into a merkle tree
|
||||||
|
/// @param _proof A snark proof that elements were inserted correctly
|
||||||
|
/// @param _argsHash A hash of snark inputs
|
||||||
|
/// @param _currentRoot Current merkle tree root
|
||||||
|
/// @param _newRoot Updated merkle tree root
|
||||||
|
/// @param _pathIndices Merkle path to inserted batch
|
||||||
|
/// @param _events A batch of inserted events (leaves)
|
||||||
function updateDepositTree(
|
function updateDepositTree(
|
||||||
bytes calldata _proof,
|
bytes calldata _proof,
|
||||||
bytes32 _argsHash,
|
bytes32 _argsHash,
|
||||||
@ -123,7 +134,6 @@ contract TornadoTrees is Initializable {
|
|||||||
TreeLeaf[CHUNK_SIZE] calldata _events
|
TreeLeaf[CHUNK_SIZE] calldata _events
|
||||||
) public {
|
) public {
|
||||||
uint256 offset = lastProcessedDepositLeaf;
|
uint256 offset = lastProcessedDepositLeaf;
|
||||||
require(_newRoot != previousDepositRoot, "Outdated deposit root");
|
|
||||||
require(_currentRoot == depositRoot, "Proposed deposit root is invalid");
|
require(_currentRoot == depositRoot, "Proposed deposit root is invalid");
|
||||||
require(_pathIndices == offset >> CHUNK_TREE_HEIGHT, "Incorrect deposit insert index");
|
require(_pathIndices == offset >> CHUNK_TREE_HEIGHT, "Incorrect deposit insert index");
|
||||||
|
|
||||||
@ -139,9 +149,10 @@ contract TornadoTrees is Initializable {
|
|||||||
bytes32 deposit = offset + i >= depositsV1Length ? deposits[offset + i] : tornadoTreesV1.deposits(offset + i);
|
bytes32 deposit = offset + i >= depositsV1Length ? deposits[offset + i] : tornadoTreesV1.deposits(offset + i);
|
||||||
require(leafHash == deposit, "Incorrect deposit");
|
require(leafHash == deposit, "Incorrect deposit");
|
||||||
assembly {
|
assembly {
|
||||||
mstore(add(add(data, mul(ITEM_SIZE, i)), 0x7c), blockNumber)
|
let itemOffset := add(data, mul(ITEM_SIZE, i))
|
||||||
mstore(add(add(data, mul(ITEM_SIZE, i)), 0x78), instance)
|
mstore(add(itemOffset, 0x7c), blockNumber)
|
||||||
mstore(add(add(data, mul(ITEM_SIZE, i)), 0x64), hash)
|
mstore(add(itemOffset, 0x78), instance)
|
||||||
|
mstore(add(itemOffset, 0x64), hash)
|
||||||
}
|
}
|
||||||
if (offset + i >= depositsV1Length) {
|
if (offset + i >= depositsV1Length) {
|
||||||
delete deposits[offset + i];
|
delete deposits[offset + i];
|
||||||
@ -159,6 +170,13 @@ contract TornadoTrees is Initializable {
|
|||||||
lastProcessedDepositLeaf = offset + CHUNK_SIZE;
|
lastProcessedDepositLeaf = offset + CHUNK_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @dev Insert a full batch of queued withdrawals into a merkle tree
|
||||||
|
/// @param _proof A snark proof that elements were inserted correctly
|
||||||
|
/// @param _argsHash A hash of snark inputs
|
||||||
|
/// @param _currentRoot Current merkle tree root
|
||||||
|
/// @param _newRoot Updated merkle tree root
|
||||||
|
/// @param _pathIndices Merkle path to inserted batch
|
||||||
|
/// @param _events A batch of inserted events (leaves)
|
||||||
function updateWithdrawalTree(
|
function updateWithdrawalTree(
|
||||||
bytes calldata _proof,
|
bytes calldata _proof,
|
||||||
bytes32 _argsHash,
|
bytes32 _argsHash,
|
||||||
@ -168,7 +186,6 @@ contract TornadoTrees is Initializable {
|
|||||||
TreeLeaf[CHUNK_SIZE] calldata _events
|
TreeLeaf[CHUNK_SIZE] calldata _events
|
||||||
) public {
|
) public {
|
||||||
uint256 offset = lastProcessedWithdrawalLeaf;
|
uint256 offset = lastProcessedWithdrawalLeaf;
|
||||||
require(_newRoot != previousWithdrawalRoot, "Outdated withdrawal root");
|
|
||||||
require(_currentRoot == withdrawalRoot, "Proposed withdrawal root is invalid");
|
require(_currentRoot == withdrawalRoot, "Proposed withdrawal root is invalid");
|
||||||
require(_pathIndices == offset >> CHUNK_TREE_HEIGHT, "Incorrect withdrawal insert index");
|
require(_pathIndices == offset >> CHUNK_TREE_HEIGHT, "Incorrect withdrawal insert index");
|
||||||
|
|
||||||
@ -184,9 +201,10 @@ contract TornadoTrees is Initializable {
|
|||||||
bytes32 withdrawal = offset + i >= withdrawalsV1Length ? withdrawals[offset + i] : tornadoTreesV1.withdrawals(offset + i);
|
bytes32 withdrawal = offset + i >= withdrawalsV1Length ? withdrawals[offset + i] : tornadoTreesV1.withdrawals(offset + i);
|
||||||
require(leafHash == withdrawal, "Incorrect withdrawal");
|
require(leafHash == withdrawal, "Incorrect withdrawal");
|
||||||
assembly {
|
assembly {
|
||||||
mstore(add(add(data, mul(ITEM_SIZE, i)), 0x7c), blockNumber)
|
let itemOffset := add(data, mul(ITEM_SIZE, i))
|
||||||
mstore(add(add(data, mul(ITEM_SIZE, i)), 0x78), instance)
|
mstore(add(itemOffset, 0x7c), blockNumber)
|
||||||
mstore(add(add(data, mul(ITEM_SIZE, i)), 0x64), hash)
|
mstore(add(itemOffset, 0x78), instance)
|
||||||
|
mstore(add(itemOffset, 0x64), hash)
|
||||||
}
|
}
|
||||||
if (offset + i >= withdrawalsV1Length) {
|
if (offset + i >= withdrawalsV1Length) {
|
||||||
delete withdrawals[offset + i];
|
delete withdrawals[offset + i];
|
||||||
@ -217,10 +235,7 @@ contract TornadoTrees is Initializable {
|
|||||||
string memory _type,
|
string memory _type,
|
||||||
uint256 _from, // most likely array length after the proposal has passed
|
uint256 _from, // most likely array length after the proposal has passed
|
||||||
uint256 _step // optimal step size to find first match, approximately equals dispersion
|
uint256 _step // optimal step size to find first match, approximately equals dispersion
|
||||||
) internal view returns (uint256) {
|
) internal view virtual returns (uint256) {
|
||||||
if (_from == 0 && _step == 0) {
|
|
||||||
return 0; // for tests
|
|
||||||
}
|
|
||||||
// Find the segment with correct array length
|
// Find the segment with correct array length
|
||||||
bool direction = elementExists(_tornadoTreesV1, _type, _from);
|
bool direction = elementExists(_tornadoTreesV1, _type, _from);
|
||||||
do {
|
do {
|
||||||
@ -251,28 +266,14 @@ contract TornadoTrees is Initializable {
|
|||||||
(success, ) = address(_tornadoTreesV1).staticcall{ gas: 2500 }(abi.encodeWithSignature(_type, index));
|
(success, ) = address(_tornadoTreesV1).staticcall{ gas: 2500 }(abi.encodeWithSignature(_type, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRegisteredDeposits() external view returns (bytes32[] memory _deposits) {
|
|
||||||
uint256 count = depositsLength - lastProcessedDepositLeaf;
|
|
||||||
_deposits = new bytes32[](count);
|
|
||||||
for (uint256 i = 0; i < count; i++) {
|
|
||||||
_deposits[i] = deposits[lastProcessedDepositLeaf + i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRegisteredWithdrawals() external view returns (bytes32[] memory _withdrawals) {
|
|
||||||
uint256 count = withdrawalsLength - lastProcessedWithdrawalLeaf;
|
|
||||||
_withdrawals = new bytes32[](count);
|
|
||||||
for (uint256 i = 0; i < count; i++) {
|
|
||||||
_withdrawals[i] = withdrawals[lastProcessedWithdrawalLeaf + i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setTornadoProxyContract(address _tornadoProxy) external onlyGovernance {
|
function setTornadoProxyContract(address _tornadoProxy) external onlyGovernance {
|
||||||
tornadoProxy = _tornadoProxy;
|
tornadoProxy = _tornadoProxy;
|
||||||
|
emit ProxyUpdated(_tornadoProxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setVerifierContract(IBatchTreeUpdateVerifier _treeUpdateVerifier) external onlyGovernance {
|
function setVerifierContract(IBatchTreeUpdateVerifier _treeUpdateVerifier) external onlyGovernance {
|
||||||
treeUpdateVerifier = _treeUpdateVerifier;
|
treeUpdateVerifier = _treeUpdateVerifier;
|
||||||
|
emit VerifierUpdated(address(_treeUpdateVerifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
function blockNumber() public view virtual returns (uint256) {
|
function blockNumber() public view virtual returns (uint256) {
|
||||||
|
@ -97,4 +97,32 @@ contract TornadoTreesMock is TornadoTrees {
|
|||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getRegisteredDeposits() external view returns (bytes32[] memory _deposits) {
|
||||||
|
uint256 count = depositsLength - lastProcessedDepositLeaf;
|
||||||
|
_deposits = new bytes32[](count);
|
||||||
|
for (uint256 i = 0; i < count; i++) {
|
||||||
|
_deposits[i] = deposits[lastProcessedDepositLeaf + i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRegisteredWithdrawals() external view returns (bytes32[] memory _withdrawals) {
|
||||||
|
uint256 count = withdrawalsLength - lastProcessedWithdrawalLeaf;
|
||||||
|
_withdrawals = new bytes32[](count);
|
||||||
|
for (uint256 i = 0; i < count; i++) {
|
||||||
|
_withdrawals[i] = withdrawals[lastProcessedWithdrawalLeaf + i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findArrayLength(
|
||||||
|
ITornadoTreesV1 _tornadoTreesV1,
|
||||||
|
string memory _type,
|
||||||
|
uint256 _from, // most likely array length after the proposal has passed
|
||||||
|
uint256 _step // optimal step size to find first match, approximately equals dispersion
|
||||||
|
) internal view override returns (uint256) {
|
||||||
|
if (_from == 0 && _step == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return super.findArrayLength(_tornadoTreesV1, _type, _from, _step);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ RUN source $HOME/.cargo/env && cargo install zkutil
|
|||||||
RUN npm install -g circom snarkjs
|
RUN npm install -g circom snarkjs
|
||||||
|
|
||||||
WORKDIR /root/test
|
WORKDIR /root/test
|
||||||
RUN npm init -y && npm install circomlib
|
RUN npm init -y && npm install @tornado/circomlib
|
||||||
RUN apt-get update && apt-get install -y ne
|
RUN apt-get update && apt-get install -y ne
|
||||||
RUN mkdir circuits
|
RUN mkdir circuits
|
||||||
COPY sha/circuit.circom sha/input.js test.sh ./circuits/
|
COPY sha/circuit.circom sha/input.js test.sh ./circuits/
|
||||||
|
12
package.json
12
package.json
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "tornado-trees",
|
"name": "@tornado/trees",
|
||||||
"version": "0.0.10",
|
"version": "0.0.11",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"repository": "https://github.com/tornadocash/tornado-trees.git",
|
"repository": "https://git.tornado.ws/tornado-packages/tornado-trees.git",
|
||||||
"author": "Tornadocash team <hello@tornado.cash>",
|
"author": "Tornadocash team <hello@tornado.cash>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"files": [
|
"files": [
|
||||||
@ -42,13 +42,13 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@openzeppelin/contracts": "^3.4.0",
|
"@openzeppelin/contracts": "^3.4.0",
|
||||||
"@openzeppelin/upgrades-core": "^1.5.1",
|
"@openzeppelin/upgrades-core": "^1.5.1",
|
||||||
"circom": "^0.5.38",
|
"@tornado/circomlib": "^0.0.21",
|
||||||
|
"@tornado/fixed-merkle-tree": "^0.5.0",
|
||||||
|
"circom": "0.5.42",
|
||||||
"circom_runtime": "^0.1.12",
|
"circom_runtime": "^0.1.12",
|
||||||
"circomlib": "git+https://github.com/tornadocash/circomlib.git#d20d53411d1bef61f38c99a8b36d5d0cc4836aa1",
|
|
||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
"ffiasm": "^0.1.1",
|
"ffiasm": "^0.1.1",
|
||||||
"ffjavascript": "^0.2.35",
|
"ffjavascript": "^0.2.35",
|
||||||
"fixed-merkle-tree": "^0.5.0",
|
|
||||||
"jssha": "^3.2.0",
|
"jssha": "^3.2.0",
|
||||||
"snarkjs": "^0.3.57",
|
"snarkjs": "^0.3.57",
|
||||||
"tmp-promise": "^3.0.2"
|
"tmp-promise": "^3.0.2"
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
// Runtime Environment's members available in the global scope.
|
// Runtime Environment's members available in the global scope.
|
||||||
const hre = require('hardhat')
|
const hre = require('hardhat')
|
||||||
const { toFixedHex, poseidonHash2 } = require('../src/utils')
|
const { toFixedHex, poseidonHash2 } = require('../src/utils')
|
||||||
const MerkleTree = require('fixed-merkle-tree')
|
const MerkleTree = require('@tornado/fixed-merkle-tree')
|
||||||
const abi = new hre.ethers.utils.AbiCoder()
|
const abi = new hre.ethers.utils.AbiCoder()
|
||||||
const instances = [
|
const instances = [
|
||||||
'0x1111000000000000000000000000000000001111',
|
'0x1111000000000000000000000000000000001111',
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
// Runtime Environment's members available in the global scope.
|
// Runtime Environment's members available in the global scope.
|
||||||
const hre = require('hardhat')
|
const hre = require('hardhat')
|
||||||
const { toFixedHex, poseidonHash2 } = require('../src/utils')
|
const { toFixedHex, poseidonHash2 } = require('../src/utils')
|
||||||
const MerkleTree = require('fixed-merkle-tree')
|
const MerkleTree = require('@tornado/fixed-merkle-tree')
|
||||||
const abi = new hre.ethers.utils.AbiCoder()
|
const abi = new hre.ethers.utils.AbiCoder()
|
||||||
const instances = [
|
const instances = [
|
||||||
'0x1111000000000000000000000000000000001111',
|
'0x1111000000000000000000000000000000001111',
|
||||||
|
17
src/index.js
17
src/index.js
@ -42,7 +42,14 @@ function prove(input, keyBasePath) {
|
|||||||
fs.writeFileSync(`${dir}/input.json`, JSON.stringify(input, null, 2))
|
fs.writeFileSync(`${dir}/input.json`, JSON.stringify(input, null, 2))
|
||||||
out = await exec(`${keyBasePath} ${dir}/input.json ${dir}/witness.json`)
|
out = await exec(`${keyBasePath} ${dir}/input.json ${dir}/witness.json`)
|
||||||
} else {
|
} else {
|
||||||
await wtns.calculate(utils.unstringifyBigInts(input), `${keyBasePath}.wasm`, `${dir}/witness.wtns`)
|
await wtns.debug(
|
||||||
|
utils.unstringifyBigInts(input),
|
||||||
|
`${keyBasePath}.wasm`,
|
||||||
|
`${dir}/witness.wtns`,
|
||||||
|
`${keyBasePath}.sym`,
|
||||||
|
{},
|
||||||
|
console,
|
||||||
|
)
|
||||||
const witness = utils.stringifyBigInts(await wtns.exportJson(`${dir}/witness.wtns`))
|
const witness = utils.stringifyBigInts(await wtns.exportJson(`${dir}/witness.wtns`))
|
||||||
fs.writeFileSync(`${dir}/witness.json`, JSON.stringify(witness, null, 2))
|
fs.writeFileSync(`${dir}/witness.json`, JSON.stringify(witness, null, 2))
|
||||||
}
|
}
|
||||||
@ -57,6 +64,14 @@ function prove(input, keyBasePath) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates inputs for a snark and tornado trees smart contract.
|
||||||
|
* This function updates MerkleTree argument
|
||||||
|
*
|
||||||
|
* @param tree Merkle tree with current smart contract state. This object is mutated during function execution.
|
||||||
|
* @param events New batch of events to insert.
|
||||||
|
* @returns {{args: [string, string, string, string, *], input: {pathElements: *, instances: *, blocks: *, newRoot: *, hashes: *, oldRoot: *, pathIndices: string}}}
|
||||||
|
*/
|
||||||
function batchTreeUpdate(tree, events) {
|
function batchTreeUpdate(tree, events) {
|
||||||
const batchHeight = Math.log2(events.length)
|
const batchHeight = Math.log2(events.length)
|
||||||
if (!Number.isInteger(batchHeight)) {
|
if (!Number.isInteger(batchHeight)) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const crypto = require('crypto')
|
const crypto = require('crypto')
|
||||||
const ethers = require('ethers')
|
const ethers = require('ethers')
|
||||||
const BigNumber = ethers.BigNumber
|
const BigNumber = ethers.BigNumber
|
||||||
const { poseidon } = require('circomlib')
|
const { poseidon } = require('@tornado/circomlib')
|
||||||
|
|
||||||
const poseidonHash = (items) => BigNumber.from(poseidon(items).toString())
|
const poseidonHash = (items) => BigNumber.from(poseidon(items).toString())
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
const { expect } = require('chai')
|
const { expect } = require('chai')
|
||||||
const MerkleTree = require('fixed-merkle-tree')
|
const MerkleTree = require('@tornado/fixed-merkle-tree')
|
||||||
const { poseidonHash2, randomBN } = require('../src/utils')
|
const { poseidonHash2, randomBN } = require('../src/utils')
|
||||||
const { batchTreeUpdate, prove } = require('../src/index')
|
const { batchTreeUpdate, prove } = require('../src/index')
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* global ethers */
|
/* global ethers */
|
||||||
const { expect } = require('chai')
|
const { expect } = require('chai')
|
||||||
const { toFixedHex, poseidonHash2, randomBN } = require('../src/utils')
|
const { toFixedHex, poseidonHash2, randomBN } = require('../src/utils')
|
||||||
const MerkleTree = require('fixed-merkle-tree')
|
const MerkleTree = require('@tornado/fixed-merkle-tree')
|
||||||
const controller = require('../src/index')
|
const controller = require('../src/index')
|
||||||
|
|
||||||
async function register(note, tornadoTrees, from) {
|
async function register(note, tornadoTrees, from) {
|
||||||
|
125
yarn.lock
125
yarn.lock
@ -736,6 +736,37 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
defer-to-connect "^1.0.1"
|
defer-to-connect "^1.0.1"
|
||||||
|
|
||||||
|
"@tornado/circomlib@0.0.21", "@tornado/circomlib@^0.0.21":
|
||||||
|
version "0.0.21"
|
||||||
|
resolved "https://git.tornado.ws/api/packages/tornado-packages/npm/%40tornado%2Fcircomlib/-/0.0.21/circomlib-0.0.21.tgz#fb7a502aa32bcb2b23205a05877d1cd030c41b19"
|
||||||
|
integrity sha512-CFaqfgoWZBdD9xZurVOEalWKEVn/NzsT63W/VLGFRbmAUTYJ1vING9LjC0ZXBvec8vzyYquIkvNRdx6axFdJ5g==
|
||||||
|
dependencies:
|
||||||
|
"@tornado/snarkjs" "0.1.20"
|
||||||
|
blake-hash "^1.1.0"
|
||||||
|
blake2b "^2.1.3"
|
||||||
|
typedarray-to-buffer "^3.1.5"
|
||||||
|
web3 "^1.2.11"
|
||||||
|
|
||||||
|
"@tornado/fixed-merkle-tree@^0.5.0":
|
||||||
|
version "0.5.1"
|
||||||
|
resolved "https://git.tornado.ws/api/packages/tornado-packages/npm/%40tornado%2Ffixed-merkle-tree/-/0.5.1/fixed-merkle-tree-0.5.1.tgz#bda51bc964a8ed86ce9735f49d1efe1f32595140"
|
||||||
|
integrity sha512-aMbCrnHLnvGWSr54/oT4IUg7106+F/55APn2uMhEeg0rQk5PXXRgzzqvHgBqyjRpMibKzOT7m7G8SMMVMpXFFg==
|
||||||
|
dependencies:
|
||||||
|
"@tornado/circomlib" "0.0.21"
|
||||||
|
"@tornado/snarkjs" "0.1.20"
|
||||||
|
|
||||||
|
"@tornado/snarkjs@0.1.20":
|
||||||
|
version "0.1.20"
|
||||||
|
resolved "https://git.tornado.ws/api/packages/tornado-packages/npm/%40tornado%2Fsnarkjs/-/0.1.20/snarkjs-0.1.20.tgz#d7610cd3c8dc10598da7dc3e40e5d7470c3aa8c7"
|
||||||
|
integrity sha512-mn+ePoQjqOHyDyK8AMy8SXYqNSxJWVswWVmMYvuc75/9bBtJ7SNtwrTByxmfWjrf4S3BM3IrGfHqBHEXY6gR4Q==
|
||||||
|
dependencies:
|
||||||
|
big-integer "^1.6.43"
|
||||||
|
chai "^4.2.0"
|
||||||
|
escape-string-regexp "^1.0.5"
|
||||||
|
eslint "^5.16.0"
|
||||||
|
keccak "^2.0.0"
|
||||||
|
yargs "^12.0.5"
|
||||||
|
|
||||||
"@types/bn.js@*":
|
"@types/bn.js@*":
|
||||||
version "5.1.0"
|
version "5.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68"
|
resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68"
|
||||||
@ -2225,26 +2256,10 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
|
|||||||
inherits "^2.0.1"
|
inherits "^2.0.1"
|
||||||
safe-buffer "^5.0.1"
|
safe-buffer "^5.0.1"
|
||||||
|
|
||||||
circom@0.5.33:
|
circom@0.5.42:
|
||||||
version "0.5.33"
|
version "0.5.42"
|
||||||
resolved "https://registry.yarnpkg.com/circom/-/circom-0.5.33.tgz#6943d5799adf5388989bfbb3ef8f502fb1b4f662"
|
resolved "https://registry.yarnpkg.com/circom/-/circom-0.5.42.tgz#96a456f9538f4425654df091d15e3158e9da2acc"
|
||||||
integrity sha512-UdL8fr6GckhQ4VoWjIvuYwCHneJe8z/AyJpDxgKLyuaX51ijd4gBP6jlwHDbQJsha2aU2GR9qgDsxd0jfari1Q==
|
integrity sha512-v6+f9g3z2ia17NQvQmyZjvh8cE8O3GtxRE36KfJfx/a+s58Y7aEDWsUG+GFRJhp1ajiQELdj3NehY9vHSf5Rkg==
|
||||||
dependencies:
|
|
||||||
chai "^4.2.0"
|
|
||||||
circom_runtime "0.1.8"
|
|
||||||
fastfile "0.0.18"
|
|
||||||
ffiasm "0.1.1"
|
|
||||||
ffjavascript "0.2.22"
|
|
||||||
ffwasm "0.0.7"
|
|
||||||
fnv-plus "^1.3.1"
|
|
||||||
r1csfile "0.0.16"
|
|
||||||
tmp-promise "^2.0.2"
|
|
||||||
wasmbuilder "0.0.10"
|
|
||||||
|
|
||||||
circom@^0.5.38:
|
|
||||||
version "0.5.38"
|
|
||||||
resolved "https://registry.yarnpkg.com/circom/-/circom-0.5.38.tgz#c099fb196085837575fb266f37b0516b1ec56eb5"
|
|
||||||
integrity sha512-PFlXto8gDysUlwk6z/GYbn1Mv5BtW9BI4769N9gSP0/7KDNSqLNyVmL4DgMLc67/EpG4qJLGch3SdgzQD+/cfw==
|
|
||||||
dependencies:
|
dependencies:
|
||||||
chai "^4.2.0"
|
chai "^4.2.0"
|
||||||
circom_runtime "0.1.12"
|
circom_runtime "0.1.12"
|
||||||
@ -2273,33 +2288,6 @@ circom_runtime@0.1.12, circom_runtime@^0.1.12:
|
|||||||
ffjavascript "0.2.34"
|
ffjavascript "0.2.34"
|
||||||
fnv-plus "^1.3.1"
|
fnv-plus "^1.3.1"
|
||||||
|
|
||||||
circom_runtime@0.1.8:
|
|
||||||
version "0.1.8"
|
|
||||||
resolved "https://registry.yarnpkg.com/circom_runtime/-/circom_runtime-0.1.8.tgz#d967a1618fe5290849f9c0bbffb6b97b95c0f1c8"
|
|
||||||
integrity sha512-5ZmzCyidkNPb1zZsJGRXTuWcJ6kW6+gRBtHgf2tFqTh5dUyWVVPH0Zg7AsU2ijPr1AmYZUlme0yORUZK5HrjOA==
|
|
||||||
dependencies:
|
|
||||||
ffjavascript "0.2.10"
|
|
||||||
fnv-plus "^1.3.1"
|
|
||||||
|
|
||||||
"circomlib@git+https://github.com/tornadocash/circomlib.git#5beb6aee94923052faeecea40135d45b6ce6172c":
|
|
||||||
version "0.0.20"
|
|
||||||
resolved "git+https://github.com/tornadocash/circomlib.git#5beb6aee94923052faeecea40135d45b6ce6172c"
|
|
||||||
dependencies:
|
|
||||||
blake-hash "^1.1.0"
|
|
||||||
blake2b "^2.1.3"
|
|
||||||
snarkjs "git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5"
|
|
||||||
typedarray-to-buffer "^3.1.5"
|
|
||||||
web3 "^1.2.11"
|
|
||||||
|
|
||||||
"circomlib@git+https://github.com/tornadocash/circomlib.git#d20d53411d1bef61f38c99a8b36d5d0cc4836aa1":
|
|
||||||
version "0.4.1"
|
|
||||||
resolved "git+https://github.com/tornadocash/circomlib.git#d20d53411d1bef61f38c99a8b36d5d0cc4836aa1"
|
|
||||||
dependencies:
|
|
||||||
blake-hash "^1.1.0"
|
|
||||||
blake2b "^2.1.3"
|
|
||||||
circom "0.5.33"
|
|
||||||
ffjavascript "0.1.0"
|
|
||||||
|
|
||||||
class-is@^1.1.0:
|
class-is@^1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825"
|
resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825"
|
||||||
@ -3855,22 +3843,6 @@ ffiasm@0.1.1, ffiasm@^0.1.1:
|
|||||||
ejs "^3.0.1"
|
ejs "^3.0.1"
|
||||||
yargs "^15.3.1"
|
yargs "^15.3.1"
|
||||||
|
|
||||||
ffjavascript@0.1.0:
|
|
||||||
version "0.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/ffjavascript/-/ffjavascript-0.1.0.tgz#456256c259654cc1ce864c6762b0e76ee1714100"
|
|
||||||
integrity sha512-dmKlUasSfvUcxBm8nCSKl2x7EFJsXA7OVP8XLFA03T2+6mAc3IiVLC2ambEVOcMOhyhl0vJfVZjM9f9d38D1rw==
|
|
||||||
dependencies:
|
|
||||||
big-integer "^1.6.48"
|
|
||||||
|
|
||||||
ffjavascript@0.2.10:
|
|
||||||
version "0.2.10"
|
|
||||||
resolved "https://registry.yarnpkg.com/ffjavascript/-/ffjavascript-0.2.10.tgz#b0bf88d69be0b51e0bd28e1966c4a6fb29a86682"
|
|
||||||
integrity sha512-GQI6gHYYG5/iD4Kt3VzezzK7fARJzP0zkc82V/+JAdjfeKBXhDSo5rpKFuK3cDcrdW0Fu2emuYNMEAuFqhEQvQ==
|
|
||||||
dependencies:
|
|
||||||
big-integer "^1.6.48"
|
|
||||||
wasmcurves "0.0.5"
|
|
||||||
worker-threads "^1.0.0"
|
|
||||||
|
|
||||||
ffjavascript@0.2.22:
|
ffjavascript@0.2.22:
|
||||||
version "0.2.22"
|
version "0.2.22"
|
||||||
resolved "https://registry.yarnpkg.com/ffjavascript/-/ffjavascript-0.2.22.tgz#101f33db330b0f6a0c10dec22ebf5725618a8a7d"
|
resolved "https://registry.yarnpkg.com/ffjavascript/-/ffjavascript-0.2.22.tgz#101f33db330b0f6a0c10dec22ebf5725618a8a7d"
|
||||||
@ -4016,14 +3988,6 @@ find-yarn-workspace-root@^1.2.1:
|
|||||||
fs-extra "^4.0.3"
|
fs-extra "^4.0.3"
|
||||||
micromatch "^3.1.4"
|
micromatch "^3.1.4"
|
||||||
|
|
||||||
fixed-merkle-tree@^0.5.0:
|
|
||||||
version "0.5.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/fixed-merkle-tree/-/fixed-merkle-tree-0.5.0.tgz#401cdcf3d670c1e18bc7d3a8e81322eb1b27c1d1"
|
|
||||||
integrity sha512-egOy12EzVATX3Ru2/SLtnWprVpy/sbPCt/MbeG3ANB28jykWLEYj7EjinFnOxtsgR3gTHU6xYXX53yMn/bZqyw==
|
|
||||||
dependencies:
|
|
||||||
circomlib "git+https://github.com/tornadocash/circomlib.git#5beb6aee94923052faeecea40135d45b6ce6172c"
|
|
||||||
snarkjs "git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5"
|
|
||||||
|
|
||||||
flat-cache@^2.0.1:
|
flat-cache@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0"
|
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0"
|
||||||
@ -7458,17 +7422,6 @@ snarkjs@^0.3.57:
|
|||||||
logplease "^1.2.15"
|
logplease "^1.2.15"
|
||||||
r1csfile "0.0.31"
|
r1csfile "0.0.31"
|
||||||
|
|
||||||
"snarkjs@git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5":
|
|
||||||
version "0.1.20"
|
|
||||||
resolved "git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5"
|
|
||||||
dependencies:
|
|
||||||
big-integer "^1.6.43"
|
|
||||||
chai "^4.2.0"
|
|
||||||
escape-string-regexp "^1.0.5"
|
|
||||||
eslint "^5.16.0"
|
|
||||||
keccak "^2.0.0"
|
|
||||||
yargs "^12.0.5"
|
|
||||||
|
|
||||||
solc@0.7.3:
|
solc@0.7.3:
|
||||||
version "0.7.3"
|
version "0.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a"
|
resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a"
|
||||||
@ -8353,14 +8306,6 @@ wasmcurves@0.0.14:
|
|||||||
big-integer "^1.6.42"
|
big-integer "^1.6.42"
|
||||||
blakejs "^1.1.0"
|
blakejs "^1.1.0"
|
||||||
|
|
||||||
wasmcurves@0.0.5:
|
|
||||||
version "0.0.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/wasmcurves/-/wasmcurves-0.0.5.tgz#d0b58e803c0b1c09c966b7dc0fad6dd405d18547"
|
|
||||||
integrity sha512-BmI4GXLjLawGg2YkvHa8zRsnWec+d1uwoxE+Iov8cqOpDL7GA5XO2pk2yuDbXHMzwIug2exnKot3baRZ86R0pA==
|
|
||||||
dependencies:
|
|
||||||
big-integer "^1.6.42"
|
|
||||||
blakejs "^1.1.0"
|
|
||||||
|
|
||||||
web-worker@^1.0.0:
|
web-worker@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.0.0.tgz#c7ced4e1eb6227636ada35056a9e5a477414e4d0"
|
resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.0.0.tgz#c7ced4e1eb6227636ada35056a9e5a477414e4d0"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user