From 656673b69008d00837759d477e4a4e63fac09c1e Mon Sep 17 00:00:00 2001 From: Roman Storm Date: Mon, 9 Dec 2019 23:39:50 -0800 Subject: [PATCH 01/14] add migration script --- contracts/ETHMixer.sol | 30 +++++++++++++++++ migrationDeposits.js | 76 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 migrationDeposits.js diff --git a/contracts/ETHMixer.sol b/contracts/ETHMixer.sol index 2996b5e..d86ba91 100644 --- a/contracts/ETHMixer.sol +++ b/contracts/ETHMixer.sol @@ -38,4 +38,34 @@ contract ETHMixer is Mixer { require(success, "payment to _relayer did not go thru"); } } + /** + @dev Migrate state from old mixer to this one. + @param _commitments deposited commitments from previous contract + @param _nullifierHashes spent nullifiers from previous contract + */ + bool public isMigrated = false; + function migrateState(bytes32[] calldata _commitments, bytes32[] calldata _nullifierHashes) external onlyOperator { + require(!isMigrated, "Migration is disabled"); + for (uint32 i = 0; i < _commitments.length; i++) { + commitments[_commitments[i]] = true; + emit Deposit(_commitments[i], nextIndex + i, block.timestamp); + } + + nextIndex += uint32(_commitments.length); + + for (uint256 i = 0; i < _nullifierHashes.length; i++) { + nullifierHashes[_nullifierHashes[i]] = true; + emit Withdrawal(address(0), _nullifierHashes[i], address(0), 0); + } + } + + function initializeTreeForMigration(bytes32[] calldata _filledSubtrees, bytes32 _root) external { + require(!isMigrated, "already migrated"); + filledSubtrees = _filledSubtrees; + roots[0] = _root; + } + + function finishMigration() external onlyOperator { + isMigrated = true; + } } diff --git a/migrationDeposits.js b/migrationDeposits.js new file mode 100644 index 0000000..dcdde3c --- /dev/null +++ b/migrationDeposits.js @@ -0,0 +1,76 @@ +require('dotenv').config() +const Web3 = require('web3') +const web3 = new Web3('https://mainnet.infura.io', null, { transactionConfirmationBlocks: 1 }) +const web3Kovan = new Web3('https://kovan.infura.io', null, { transactionConfirmationBlocks: 1 }) +const account = web3.eth.accounts.privateKeyToAccount('0x' + process.env.PRIVATE_KEY) +web3.eth.accounts.wallet.add('0x' + process.env.PRIVATE_KEY) +web3.eth.defaultAccount = account.address +const ABI = [{ 'constant':false,'inputs':[{ 'name':'_newAccount','type':'address' }],'name':'changeOperator','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[],'name':'filled_subtrees','outputs':[{ 'name':'','type':'uint256[]' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[{ 'name':'','type':'uint256' }],'name':'nullifierHashes','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'verifier','outputs':[{ 'name':'','type':'address' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'transferValue','outputs':[{ 'name':'','type':'uint256' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'_commitments','type':'uint256[]' },{ 'name':'_nullifierHashes','type':'uint256[]' }],'name':'migrateState','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[],'name':'roots','outputs':[{ 'name':'','type':'uint256[]' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'_verifier','type':'address' },{ 'name':'_transferValue','type':'uint256' },{ 'name':'_merkleTreeHeight','type':'uint8' },{ 'name':'_emptyElement','type':'uint256' },{ 'name':'_operator','type':'address' },{ 'name':'_filled_subtrees','type':'uint256[]' },{ 'name':'_lastRoot','type':'uint256' }],'name':'initialize','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[{ 'name':'','type':'uint256' }],'name':'commitments','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'zeros','outputs':[{ 'name':'','type':'uint256[]' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'levels','outputs':[{ 'name':'','type':'uint256' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'a','type':'uint256[2]' },{ 'name':'b','type':'uint256[2][2]' },{ 'name':'c','type':'uint256[2]' },{ 'name':'input','type':'uint256[4]' }],'name':'withdraw','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[],'name':'operator','outputs':[{ 'name':'','type':'address' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'isDepositsEnabled','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[{ 'name':'nullifier','type':'uint256' }],'name':'isSpent','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[{ 'name':'left','type':'uint256' },{ 'name':'right','type':'uint256' }],'name':'hashLeftRight','outputs':[{ 'name':'mimc_hash','type':'uint256' }],'payable':false,'stateMutability':'pure','type':'function' },{ 'constant':true,'inputs':[],'name':'next_index','outputs':[{ 'name':'','type':'uint32' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'current_root','outputs':[{ 'name':'','type':'uint256' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'tree_levels','type':'uint256' },{ 'name':'zero_value','type':'uint256' },{ 'name':'filled_subtrees','type':'uint256[]' },{ 'name':'lastRoot','type':'uint256' }],'name':'initialize','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[{ 'name':'root','type':'uint256' }],'name':'isKnownRoot','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'commitment','type':'uint256' }],'name':'deposit','outputs':[],'payable':true,'stateMutability':'payable','type':'function' },{ 'constant':true,'inputs':[],'name':'getLastRoot','outputs':[{ 'name':'','type':'uint256' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[],'name':'toggleDeposits','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':false,'inputs':[],'name':'stopMigration','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[],'name':'isMigrating','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'payable':true,'stateMutability':'payable','type':'fallback' },{ 'anonymous':false,'inputs':[{ 'indexed':true,'name':'commitment','type':'uint256' },{ 'indexed':false,'name':'leafIndex','type':'uint256' },{ 'indexed':false,'name':'timestamp','type':'uint256' }],'name':'Deposit','type':'event' },{ 'anonymous':false,'inputs':[{ 'indexed':false,'name':'to','type':'address' },{ 'indexed':false,'name':'nullifierHash','type':'uint256' },{ 'indexed':false,'name':'fee','type':'uint256' }],'name':'Withdraw','type':'event' }] +const ABIv2 = require('./build/contracts/ETHMixer.json').abi +const snarkjs = require('snarkjs') +const bigInt = snarkjs.bigInt + +const { numberToHex, toWei } = require('web3-utils') +const PREVIOUS_MIXER = '0xb541fc07bC7619fD4062A54d96268525cBC6FfEF' + +function toHex(number, length = 32) { + let str = number instanceof Buffer ? number.toString('hex') : bigInt(number).toString(16) + return '0x' + str.padStart(length * 2, '0') +} +const previousMixer = new web3.eth.Contract(ABI, PREVIOUS_MIXER) +previousMixer.deployedBlock = 8720524 + +async function loadDeposits() { + const depositEvents = await previousMixer.getPastEvents('Deposit', { fromBlock: previousMixer.deployedBlock, toBlock: 'latest' }) + + const withdrawEvents = await previousMixer.getPastEvents('Withdraw', { fromBlock: previousMixer.deployedBlock, toBlock: 'latest' }) + + const commitments = depositEvents + .sort((a, b) => a.returnValues.leafIndex.sub(b.returnValues.leafIndex)) + .map(e => toHex(e.returnValues.commitment)) + const nullifiers = withdrawEvents + .map(e => toHex(e.returnValues.nullifierHash)) + const subtrees = (await previousMixer.methods.filled_subtrees().call()).map(x => toHex(x)) + const lastRoot = await previousMixer.methods.getLastRoot().call() + // console.log(JSON.stringify({ subtrees, lastRoot, commitments, nullifiers }, null, 2)) + return { subtrees, lastRoot: toHex(lastRoot), commitments, nullifiers } +} + +async function migrateState({ subtrees, lastRoot, commitments, nullifiers, newMixer }) { + const loadBy = 100 + let commitmentsToLoad + let nullifiersToLoad + await newMixer.methods.initializeTreeForMigration(subtrees, lastRoot).send({ + gas: numberToHex(2500000), + gasPrice: toHex(toWei('10', 'gwei')), + from: account.address + }) + for(let i=0; i < commitments.length / loadBy; i++) { + commitmentsToLoad = commitments.slice(i*loadBy, (i+1)*loadBy) + nullifiersToLoad = nullifiers.slice(i*loadBy, (i+1)*loadBy) + console.log(`Uploading commitments and nullifiers from ${i*loadBy} to ${(i+1)*loadBy}:`) + // console.log('Commitments:\n', commitmentsToLoad) + // console.log('Nullifiers:\n', nullifiersToLoad) + + const tx = await newMixer.methods.migrateState( + commitmentsToLoad, + nullifiersToLoad + ).send({ + gas: numberToHex(6500000), + gasPrice: toHex(toWei('10', 'gwei')), + from: account.address + }) + console.log('Gas used:', tx.gasUsed) + } +} +async function main() { + const { subtrees, lastRoot, commitments, nullifiers } = await loadDeposits() + + const newContractAddress = '0xE89f4Ca5242C28D3D9565cd12499C1A53A9B76AD' + const newMixer = new web3Kovan.eth.Contract(ABIv2, newContractAddress) + web3Kovan.eth.accounts.wallet.add('0x' + process.env.PRIVATE_KEY) + web3Kovan.eth.defaultAccount = account.address + await migrateState({ subtrees, lastRoot, commitments, nullifiers, newMixer }) + +} +main() From 0e9732625ea802e887cf464e63a5d5550dc97089 Mon Sep 17 00:00:00 2001 From: poma Date: Thu, 28 Nov 2019 11:52:17 +0700 Subject: [PATCH 02/14] fix address formatting in tests --- test/ERC20Mixer.test.js | 49 +++++++++++++++-------------------------- test/ETHMixer.test.js | 21 ++++-------------- 2 files changed, 22 insertions(+), 48 deletions(-) diff --git a/test/ERC20Mixer.test.js b/test/ERC20Mixer.test.js index 30a178f..ad7e07b 100644 --- a/test/ERC20Mixer.test.js +++ b/test/ERC20Mixer.test.js @@ -25,6 +25,8 @@ const MerkleTree = require('../lib/MerkleTree') const rbigint = (nbytes) => snarkjs.bigInt.leBuff2int(crypto.randomBytes(nbytes)) const pedersenHash = (data) => circomlib.babyJub.unpackPoint(circomlib.pedersenHash.hash(data))[0] +const toFixedHex = (number, length = 32) => '0x' + bigInt(number).toString(16).padStart(length * 2, '0') +const getRandomRecipient = () => rbigint(20) function generateDeposit() { let deposit = { @@ -36,21 +38,6 @@ function generateDeposit() { return deposit } -function getRandomRecipient() { - let recipient = rbigint(20) - while (toHex(recipient.toString()).length !== 42) { - recipient = rbigint(20) - } - return recipient -} - -function toFixedHex(number, length = 32) { - let str = bigInt(number).toString(16) - while (str.length < length * 2) str = '0' + str - str = '0x' + str - return str -} - contract('ERC20Mixer', accounts => { let mixer let token @@ -161,10 +148,10 @@ contract('ERC20Mixer', accounts => { const balanceMixerBefore = await token.balanceOf(mixer.address) const balanceRelayerBefore = await token.balanceOf(relayer) - const balanceRecieverBefore = await token.balanceOf(toHex(recipient.toString())) + const balanceRecieverBefore = await token.balanceOf(toFixedHex(recipient, 20)) const ethBalanceOperatorBefore = await web3.eth.getBalance(operator) - const ethBalanceRecieverBefore = await web3.eth.getBalance(toHex(recipient.toString())) + const ethBalanceRecieverBefore = await web3.eth.getBalance(toFixedHex(recipient, 20)) const ethBalanceRelayerBefore = await web3.eth.getBalance(relayer) let isSpent = await mixer.isSpent(toFixedHex(input.nullifierHash)) isSpent.should.be.equal(false) @@ -184,8 +171,8 @@ contract('ERC20Mixer', accounts => { const balanceMixerAfter = await token.balanceOf(mixer.address) const balanceRelayerAfter = await token.balanceOf(relayer) const ethBalanceOperatorAfter = await web3.eth.getBalance(operator) - const balanceRecieverAfter = await token.balanceOf(toHex(recipient.toString())) - const ethBalanceRecieverAfter = await web3.eth.getBalance(toHex(recipient.toString())) + const balanceRecieverAfter = await token.balanceOf(toFixedHex(recipient, 20)) + const ethBalanceRecieverAfter = await web3.eth.getBalance(toFixedHex(recipient, 20)) const ethBalanceRelayerAfter = await web3.eth.getBalance(relayer) const feeBN = toBN(fee.toString()) balanceMixerAfter.should.be.eq.BN(toBN(balanceMixerBefore).sub(toBN(tokenDenomination))) @@ -242,10 +229,10 @@ contract('ERC20Mixer', accounts => { const balanceMixerBefore = await token.balanceOf(mixer.address) const balanceRelayerBefore = await token.balanceOf(relayer) - const balanceRecieverBefore = await token.balanceOf(toHex(recipient.toString())) + const balanceRecieverBefore = await token.balanceOf(toFixedHex(recipient, 20)) const ethBalanceOperatorBefore = await web3.eth.getBalance(operator) - const ethBalanceRecieverBefore = await web3.eth.getBalance(toHex(recipient.toString())) + const ethBalanceRecieverBefore = await web3.eth.getBalance(toFixedHex(recipient, 20)) const ethBalanceRelayerBefore = await web3.eth.getBalance(relayer) let isSpent = await mixer.isSpent(toFixedHex(input.nullifierHash)) isSpent.should.be.equal(false) @@ -263,8 +250,8 @@ contract('ERC20Mixer', accounts => { const balanceMixerAfter = await token.balanceOf(mixer.address) const balanceRelayerAfter = await token.balanceOf(relayer) const ethBalanceOperatorAfter = await web3.eth.getBalance(operator) - const balanceRecieverAfter = await token.balanceOf(toHex(recipient.toString())) - const ethBalanceRecieverAfter = await web3.eth.getBalance(toHex(recipient.toString())) + const balanceRecieverAfter = await token.balanceOf(toFixedHex(recipient, 20)) + const ethBalanceRecieverAfter = await web3.eth.getBalance(toFixedHex(recipient, 20)) const ethBalanceRelayerAfter = await web3.eth.getBalance(relayer) const feeBN = toBN(fee.toString()) balanceMixerAfter.should.be.eq.BN(toBN(balanceMixerBefore).sub(toBN(tokenDenomination))) @@ -384,8 +371,8 @@ contract('ERC20Mixer', accounts => { const balanceMixerBefore = await usdtToken.balanceOf(mixer.address) const balanceRelayerBefore = await usdtToken.balanceOf(relayer) const ethBalanceOperatorBefore = await web3.eth.getBalance(operator) - const balanceRecieverBefore = await usdtToken.balanceOf(toHex(recipient.toString())) - const ethBalanceRecieverBefore = await web3.eth.getBalance(toHex(recipient.toString())) + const balanceRecieverBefore = await usdtToken.balanceOf(toFixedHex(recipient, 20)) + const ethBalanceRecieverBefore = await web3.eth.getBalance(toFixedHex(recipient, 20)) let isSpent = await mixer.isSpent(input.nullifierHash.toString(16).padStart(66, '0x00000')) isSpent.should.be.equal(false) @@ -405,8 +392,8 @@ contract('ERC20Mixer', accounts => { const balanceMixerAfter = await usdtToken.balanceOf(mixer.address) const balanceRelayerAfter = await usdtToken.balanceOf(relayer) const ethBalanceOperatorAfter = await web3.eth.getBalance(operator) - const balanceRecieverAfter = await usdtToken.balanceOf(toHex(recipient.toString())) - const ethBalanceRecieverAfter = await web3.eth.getBalance(toHex(recipient.toString())) + const balanceRecieverAfter = await usdtToken.balanceOf(toFixedHex(recipient, 20)) + const ethBalanceRecieverAfter = await web3.eth.getBalance(toFixedHex(recipient, 20)) const feeBN = toBN(fee.toString()) balanceMixerAfter.should.be.eq.BN(toBN(balanceMixerBefore).sub(toBN(tokenDenomination))) balanceRelayerAfter.should.be.eq.BN(toBN(balanceRelayerBefore)) @@ -473,8 +460,8 @@ contract('ERC20Mixer', accounts => { const balanceMixerBefore = await token.balanceOf(mixer.address) const balanceRelayerBefore = await token.balanceOf(relayer) const ethBalanceOperatorBefore = await web3.eth.getBalance(operator) - const balanceRecieverBefore = await token.balanceOf(toHex(recipient.toString())) - const ethBalanceRecieverBefore = await web3.eth.getBalance(toHex(recipient.toString())) + const balanceRecieverBefore = await token.balanceOf(toFixedHex(recipient, 20)) + const ethBalanceRecieverBefore = await web3.eth.getBalance(toFixedHex(recipient, 20)) let isSpent = await mixer.isSpent(input.nullifierHash.toString(16).padStart(66, '0x00000')) isSpent.should.be.equal(false) @@ -495,8 +482,8 @@ contract('ERC20Mixer', accounts => { const balanceMixerAfter = await token.balanceOf(mixer.address) const balanceRelayerAfter = await token.balanceOf(relayer) const ethBalanceOperatorAfter = await web3.eth.getBalance(operator) - const balanceRecieverAfter = await token.balanceOf(toHex(recipient.toString())) - const ethBalanceRecieverAfter = await web3.eth.getBalance(toHex(recipient.toString())) + const balanceRecieverAfter = await token.balanceOf(toFixedHex(recipient, 20)) + const ethBalanceRecieverAfter = await web3.eth.getBalance(toFixedHex(recipient, 20)) const feeBN = toBN(fee.toString()) balanceMixerAfter.should.be.eq.BN(toBN(balanceMixerBefore).sub(toBN(tokenDenomination))) balanceRelayerAfter.should.be.eq.BN(toBN(balanceRelayerBefore)) diff --git a/test/ETHMixer.test.js b/test/ETHMixer.test.js index bf90557..8c9b5cd 100644 --- a/test/ETHMixer.test.js +++ b/test/ETHMixer.test.js @@ -23,6 +23,8 @@ const MerkleTree = require('../lib/MerkleTree') const rbigint = (nbytes) => snarkjs.bigInt.leBuff2int(crypto.randomBytes(nbytes)) const pedersenHash = (data) => circomlib.babyJub.unpackPoint(circomlib.pedersenHash.hash(data))[0] +const toFixedHex = (number, length = 32) => '0x' + bigInt(number).toString(16).padStart(length * 2, '0') +const getRandomRecipient = () => rbigint(20) function generateDeposit() { let deposit = { @@ -43,27 +45,12 @@ function BNArrayToStringArray(array) { return arrayToPrint } -function getRandomRecipient() { - let recipient = rbigint(20) - while (toHex(recipient.toString()).length !== 42) { - recipient = rbigint(20) - } - return recipient -} - function snarkVerify(proof) { proof = unstringifyBigInts2(proof) const verification_key = unstringifyBigInts2(require('../build/circuits/withdraw_verification_key.json')) return snarkjs['groth'].isValid(verification_key, proof, proof.publicSignals) } -function toFixedHex(number, length = 32) { - let str = bigInt(number).toString(16) - while (str.length < length * 2) str = '0' + str - str = '0x' + str - return str -} - contract('ETHMixer', accounts => { let mixer const sender = accounts[0] @@ -212,7 +199,7 @@ contract('ETHMixer', accounts => { const balanceMixerBefore = await web3.eth.getBalance(mixer.address) const balanceRelayerBefore = await web3.eth.getBalance(relayer) const balanceOperatorBefore = await web3.eth.getBalance(operator) - const balanceRecieverBefore = await web3.eth.getBalance(toHex(recipient.toString())) + const balanceRecieverBefore = await web3.eth.getBalance(toFixedHex(recipient, 20)) let isSpent = await mixer.isSpent(toFixedHex(input.nullifierHash)) isSpent.should.be.equal(false) @@ -232,7 +219,7 @@ contract('ETHMixer', accounts => { const balanceMixerAfter = await web3.eth.getBalance(mixer.address) const balanceRelayerAfter = await web3.eth.getBalance(relayer) const balanceOperatorAfter = await web3.eth.getBalance(operator) - const balanceRecieverAfter = await web3.eth.getBalance(toHex(recipient.toString())) + const balanceRecieverAfter = await web3.eth.getBalance(toFixedHex(recipient, 20)) const feeBN = toBN(fee.toString()) balanceMixerAfter.should.be.eq.BN(toBN(balanceMixerBefore).sub(toBN(value))) balanceRelayerAfter.should.be.eq.BN(toBN(balanceRelayerBefore)) From 2a0f0ccfd90b2c94a01b36f75d87849f86c5a298 Mon Sep 17 00:00:00 2001 From: poma Date: Thu, 28 Nov 2019 15:04:09 +0700 Subject: [PATCH 03/14] remove unused import --- test/ERC20Mixer.test.js | 2 +- test/ETHMixer.test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ERC20Mixer.test.js b/test/ERC20Mixer.test.js index ad7e07b..8c8ec24 100644 --- a/test/ERC20Mixer.test.js +++ b/test/ERC20Mixer.test.js @@ -5,7 +5,7 @@ require('chai') .should() const fs = require('fs') -const { toBN, toHex } = require('web3-utils') +const { toBN } = require('web3-utils') const { takeSnapshot, revertSnapshot } = require('../lib/ganacheHelper') const Mixer = artifacts.require('./ERC20Mixer.sol') diff --git a/test/ETHMixer.test.js b/test/ETHMixer.test.js index 8c9b5cd..ea2b53b 100644 --- a/test/ETHMixer.test.js +++ b/test/ETHMixer.test.js @@ -5,7 +5,7 @@ require('chai') .should() const fs = require('fs') -const { toBN, toHex, randomHex } = require('web3-utils') +const { toBN, randomHex } = require('web3-utils') const { takeSnapshot, revertSnapshot } = require('../lib/ganacheHelper') const Mixer = artifacts.require('./ETHMixer.sol') From 6ae2fe612cae3879b6aa5f703a3178433ea9069d Mon Sep 17 00:00:00 2001 From: Roman Semenov Date: Thu, 5 Dec 2019 22:52:01 +0700 Subject: [PATCH 04/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 98d164e..0879f52 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Tornado mixer [![Build Status](https://travis-ci.org/peppersec/tornado-mixer.svg?branch=master)](https://travis-ci.org/peppersec/tornado-mixer) +# Tornado mixer [![Build Status](https://travis-ci.org/tornadocash/tornado-core.svg?branch=master)](https://travis-ci.org/tornadocash/tornado-core) Tornado is a non-custodial Ethereum and ERC20 mixer based on zkSNARKs. It improves transaction privacy by breaking the on-chain link between recipient and destination addresses. It uses a smart contract that accepts ETH deposits that can be withdrawn by a different address. Whenever ETH is withdrawn by the new address, there is no way to link the withdrawal to the deposit, ensuring complete privacy. From 5140e1b38f29b7f5fd79b05bd08880406cb0eff1 Mon Sep 17 00:00:00 2001 From: Roman Storm Date: Tue, 10 Dec 2019 07:48:11 -0800 Subject: [PATCH 05/14] finish migration --- contracts/ETHMixer.sol | 2 +- migrationDeposits.js | 24 ++++++++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/contracts/ETHMixer.sol b/contracts/ETHMixer.sol index d86ba91..bd580f3 100644 --- a/contracts/ETHMixer.sol +++ b/contracts/ETHMixer.sol @@ -65,7 +65,7 @@ contract ETHMixer is Mixer { roots[0] = _root; } - function finishMigration() external onlyOperator { + function finishMigration() external payable onlyOperator { isMigrated = true; } } diff --git a/migrationDeposits.js b/migrationDeposits.js index dcdde3c..ae0976b 100644 --- a/migrationDeposits.js +++ b/migrationDeposits.js @@ -1,7 +1,7 @@ require('dotenv').config() const Web3 = require('web3') -const web3 = new Web3('https://mainnet.infura.io', null, { transactionConfirmationBlocks: 1 }) -const web3Kovan = new Web3('https://kovan.infura.io', null, { transactionConfirmationBlocks: 1 }) +const web3 = new Web3('https://ethereum-rpc.trustwalletapp.com', null, { transactionConfirmationBlocks: 1 }) +const web3Kovan = new Web3('http://kovanrpc.stormdapps.com:8545', null, { transactionConfirmationBlocks: 1 }) const account = web3.eth.accounts.privateKeyToAccount('0x' + process.env.PRIVATE_KEY) web3.eth.accounts.wallet.add('0x' + process.env.PRIVATE_KEY) web3.eth.defaultAccount = account.address @@ -22,9 +22,9 @@ previousMixer.deployedBlock = 8720524 async function loadDeposits() { const depositEvents = await previousMixer.getPastEvents('Deposit', { fromBlock: previousMixer.deployedBlock, toBlock: 'latest' }) - + console.log('deposits length', depositEvents.length) const withdrawEvents = await previousMixer.getPastEvents('Withdraw', { fromBlock: previousMixer.deployedBlock, toBlock: 'latest' }) - + console.log('withdrawEvents length', withdrawEvents.length) const commitments = depositEvents .sort((a, b) => a.returnValues.leafIndex.sub(b.returnValues.leafIndex)) .map(e => toHex(e.returnValues.commitment)) @@ -62,14 +62,26 @@ async function migrateState({ subtrees, lastRoot, commitments, nullifiers, newMi }) console.log('Gas used:', tx.gasUsed) } + const balance = await web3.eth.getBalance(PREVIOUS_MIXER) + console.log('balance to send in wei', balance) + + const finish = await newMixer.methods.finishMigration().send({ + gas: numberToHex(1500000), + gasPrice: toHex(toWei('10', 'gwei')), + from: account.address, + value: balance + }) + console.log('migration completed', finish.transactionHash) + } async function main() { const { subtrees, lastRoot, commitments, nullifiers } = await loadDeposits() - - const newContractAddress = '0xE89f4Ca5242C28D3D9565cd12499C1A53A9B76AD' + const newContractAddress = '0x9715fC42892A8cE94e7ae58E332Cc4cDa102FfDF' const newMixer = new web3Kovan.eth.Contract(ABIv2, newContractAddress) web3Kovan.eth.accounts.wallet.add('0x' + process.env.PRIVATE_KEY) web3Kovan.eth.defaultAccount = account.address + console.log('commitments length ', commitments.length) + console.log('nullifiers length ', nullifiers.length) await migrateState({ subtrees, lastRoot, commitments, nullifiers, newMixer }) } From 1515959a01c47fcc9243e411899c3facb81d7b52 Mon Sep 17 00:00:00 2001 From: poma Date: Wed, 11 Dec 2019 17:15:07 +0700 Subject: [PATCH 06/14] change tree depth to 20 --- .env.example | 2 +- circuits/withdraw.circom | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 20f30fd..41fef19 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ -MERKLE_TREE_HEIGHT=16 +MERKLE_TREE_HEIGHT=20 # in wei ETH_AMOUNT=100000000000000000 TOKEN_AMOUNT=100000000000000000 diff --git a/circuits/withdraw.circom b/circuits/withdraw.circom index d92a324..bed8cd6 100644 --- a/circuits/withdraw.circom +++ b/circuits/withdraw.circom @@ -52,4 +52,4 @@ template Withdraw(levels) { } } -component main = Withdraw(16); +component main = Withdraw(20); From ae44615198362ed8c93744fd6ac6a05f7e219383 Mon Sep 17 00:00:00 2001 From: poma Date: Wed, 11 Dec 2019 17:15:49 +0700 Subject: [PATCH 07/14] make finishMigration payable --- contracts/ETHMixer.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/ETHMixer.sol b/contracts/ETHMixer.sol index bd580f3..f6a8d99 100644 --- a/contracts/ETHMixer.sol +++ b/contracts/ETHMixer.sol @@ -59,7 +59,7 @@ contract ETHMixer is Mixer { } } - function initializeTreeForMigration(bytes32[] calldata _filledSubtrees, bytes32 _root) external { + function initializeTreeForMigration(bytes32[] calldata _filledSubtrees, bytes32 _root) external onlyOperator { require(!isMigrated, "already migrated"); filledSubtrees = _filledSubtrees; roots[0] = _root; From b6b8aa9619ebda9bd3b6a330880603d124217627 Mon Sep 17 00:00:00 2001 From: poma Date: Wed, 11 Dec 2019 19:28:48 +0700 Subject: [PATCH 08/14] fix subtrees --- migrationDeposits.js | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/migrationDeposits.js b/migrationDeposits.js index ae0976b..285e202 100644 --- a/migrationDeposits.js +++ b/migrationDeposits.js @@ -1,7 +1,7 @@ require('dotenv').config() const Web3 = require('web3') -const web3 = new Web3('https://ethereum-rpc.trustwalletapp.com', null, { transactionConfirmationBlocks: 1 }) -const web3Kovan = new Web3('http://kovanrpc.stormdapps.com:8545', null, { transactionConfirmationBlocks: 1 }) +const web3 = new Web3('https://mainnet.infura.io', null, { transactionConfirmationBlocks: 1 }) +const web3Kovan = new Web3('https://kovan.infura.io/v3/c7463beadf2144e68646ff049917b716', null, { transactionConfirmationBlocks: 1 }) const account = web3.eth.accounts.privateKeyToAccount('0x' + process.env.PRIVATE_KEY) web3.eth.accounts.wallet.add('0x' + process.env.PRIVATE_KEY) web3.eth.defaultAccount = account.address @@ -17,8 +17,8 @@ function toHex(number, length = 32) { let str = number instanceof Buffer ? number.toString('hex') : bigInt(number).toString(16) return '0x' + str.padStart(length * 2, '0') } -const previousMixer = new web3.eth.Contract(ABI, PREVIOUS_MIXER) -previousMixer.deployedBlock = 8720524 +const previousMixer = new web3Kovan.eth.Contract(ABI, PREVIOUS_MIXER) +previousMixer.deployedBlock = 14070053 async function loadDeposits() { const depositEvents = await previousMixer.getPastEvents('Deposit', { fromBlock: previousMixer.deployedBlock, toBlock: 'latest' }) @@ -30,10 +30,30 @@ async function loadDeposits() { .map(e => toHex(e.returnValues.commitment)) const nullifiers = withdrawEvents .map(e => toHex(e.returnValues.nullifierHash)) - const subtrees = (await previousMixer.methods.filled_subtrees().call()).map(x => toHex(x)) - const lastRoot = await previousMixer.methods.getLastRoot().call() + + const { root, subtrees } = await getSubtrees({ commitments }) + console.log(root, subtrees) + // console.log(JSON.stringify({ subtrees, lastRoot, commitments, nullifiers }, null, 2)) - return { subtrees, lastRoot: toHex(lastRoot), commitments, nullifiers } + return { subtrees, lastRoot: toHex(root), commitments, nullifiers } +} + +async function getSubtrees({ commitments }) { + const ganache = new Web3('http://localhost:8545', null, { transactionConfirmationBlocks: 1 }) + const newContractAddress = '0x1D340b022c7d83608F247a7f6fb5d96FE3450DA3' + const tempMixer = new ganache.eth.Contract(ABIv2, newContractAddress) + for(let commitment of commitments) { + await tempMixer.methods.deposit(commitment).send({ value: toWei('0.1'), from: (await ganache.eth.getAccounts())[0], gas:5e6 }) + process.stdout.write('.') + } + process.stdout.write('\n') + let subtrees = [] + for (let i = 0; i < process.env.MERKLE_TREE_HEIGHT; i++) { + subtrees.push(await tempMixer.methods.filledSubtrees(i).call()) + } + subtrees = subtrees.map(x => toHex(x)) + const lastRoot = await tempMixer.methods.getLastRoot().call() + return { subtrees, root: toHex(lastRoot) } } async function migrateState({ subtrees, lastRoot, commitments, nullifiers, newMixer }) { From 2c28e1d5aabc5faa3dba14620a74489be29c0e95 Mon Sep 17 00:00:00 2001 From: Alexey Date: Wed, 11 Dec 2019 17:01:34 +0300 Subject: [PATCH 09/14] tidy --- migrationDeposits.js | 52 ++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/migrationDeposits.js b/migrationDeposits.js index 285e202..d9c82c7 100644 --- a/migrationDeposits.js +++ b/migrationDeposits.js @@ -1,24 +1,31 @@ require('dotenv').config() const Web3 = require('web3') -const web3 = new Web3('https://mainnet.infura.io', null, { transactionConfirmationBlocks: 1 }) -const web3Kovan = new Web3('https://kovan.infura.io/v3/c7463beadf2144e68646ff049917b716', null, { transactionConfirmationBlocks: 1 }) -const account = web3.eth.accounts.privateKeyToAccount('0x' + process.env.PRIVATE_KEY) -web3.eth.accounts.wallet.add('0x' + process.env.PRIVATE_KEY) -web3.eth.defaultAccount = account.address + +// 1. edit here +const web3Source = new Web3('https://mainnet.infura.io/v3/c7463beadf2144e68646ff049917b716', null, { transactionConfirmationBlocks: 1 }) +const web3Target = new Web3('https://kovan.infura.io/v3/c7463beadf2144e68646ff049917b716', null, { transactionConfirmationBlocks: 1 }) +const web3Ganache = new Web3('http://localhost:8545', null, { transactionConfirmationBlocks: 1 }) + +const account = web3Source.eth.accounts.privateKeyToAccount('0x' + process.env.PRIVATE_KEY) +web3Source.eth.accounts.wallet.add('0x' + process.env.PRIVATE_KEY) +web3Source.eth.defaultAccount = account.address const ABI = [{ 'constant':false,'inputs':[{ 'name':'_newAccount','type':'address' }],'name':'changeOperator','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[],'name':'filled_subtrees','outputs':[{ 'name':'','type':'uint256[]' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[{ 'name':'','type':'uint256' }],'name':'nullifierHashes','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'verifier','outputs':[{ 'name':'','type':'address' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'transferValue','outputs':[{ 'name':'','type':'uint256' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'_commitments','type':'uint256[]' },{ 'name':'_nullifierHashes','type':'uint256[]' }],'name':'migrateState','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[],'name':'roots','outputs':[{ 'name':'','type':'uint256[]' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'_verifier','type':'address' },{ 'name':'_transferValue','type':'uint256' },{ 'name':'_merkleTreeHeight','type':'uint8' },{ 'name':'_emptyElement','type':'uint256' },{ 'name':'_operator','type':'address' },{ 'name':'_filled_subtrees','type':'uint256[]' },{ 'name':'_lastRoot','type':'uint256' }],'name':'initialize','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[{ 'name':'','type':'uint256' }],'name':'commitments','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'zeros','outputs':[{ 'name':'','type':'uint256[]' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'levels','outputs':[{ 'name':'','type':'uint256' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'a','type':'uint256[2]' },{ 'name':'b','type':'uint256[2][2]' },{ 'name':'c','type':'uint256[2]' },{ 'name':'input','type':'uint256[4]' }],'name':'withdraw','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[],'name':'operator','outputs':[{ 'name':'','type':'address' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'isDepositsEnabled','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[{ 'name':'nullifier','type':'uint256' }],'name':'isSpent','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[{ 'name':'left','type':'uint256' },{ 'name':'right','type':'uint256' }],'name':'hashLeftRight','outputs':[{ 'name':'mimc_hash','type':'uint256' }],'payable':false,'stateMutability':'pure','type':'function' },{ 'constant':true,'inputs':[],'name':'next_index','outputs':[{ 'name':'','type':'uint32' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'current_root','outputs':[{ 'name':'','type':'uint256' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'tree_levels','type':'uint256' },{ 'name':'zero_value','type':'uint256' },{ 'name':'filled_subtrees','type':'uint256[]' },{ 'name':'lastRoot','type':'uint256' }],'name':'initialize','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[{ 'name':'root','type':'uint256' }],'name':'isKnownRoot','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'commitment','type':'uint256' }],'name':'deposit','outputs':[],'payable':true,'stateMutability':'payable','type':'function' },{ 'constant':true,'inputs':[],'name':'getLastRoot','outputs':[{ 'name':'','type':'uint256' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[],'name':'toggleDeposits','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':false,'inputs':[],'name':'stopMigration','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[],'name':'isMigrating','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'payable':true,'stateMutability':'payable','type':'fallback' },{ 'anonymous':false,'inputs':[{ 'indexed':true,'name':'commitment','type':'uint256' },{ 'indexed':false,'name':'leafIndex','type':'uint256' },{ 'indexed':false,'name':'timestamp','type':'uint256' }],'name':'Deposit','type':'event' },{ 'anonymous':false,'inputs':[{ 'indexed':false,'name':'to','type':'address' },{ 'indexed':false,'name':'nullifierHash','type':'uint256' },{ 'indexed':false,'name':'fee','type':'uint256' }],'name':'Withdraw','type':'event' }] const ABIv2 = require('./build/contracts/ETHMixer.json').abi const snarkjs = require('snarkjs') const bigInt = snarkjs.bigInt - const { numberToHex, toWei } = require('web3-utils') + +// 2. edit here const PREVIOUS_MIXER = '0xb541fc07bC7619fD4062A54d96268525cBC6FfEF' +const GANACHE_MIXER = '0x38e6292EAB2fD2a70A81C87a194d921988d859aB' +const NEW_MIXER = '0x0a854Cf44f87FF135e2d49d2b482001853CfD98d' function toHex(number, length = 32) { let str = number instanceof Buffer ? number.toString('hex') : bigInt(number).toString(16) return '0x' + str.padStart(length * 2, '0') } -const previousMixer = new web3Kovan.eth.Contract(ABI, PREVIOUS_MIXER) -previousMixer.deployedBlock = 14070053 +const previousMixer = new web3Source.eth.Contract(ABI, PREVIOUS_MIXER) +previousMixer.deployedBlock = 0 async function loadDeposits() { const depositEvents = await previousMixer.getPastEvents('Deposit', { fromBlock: previousMixer.deployedBlock, toBlock: 'latest' }) @@ -39,11 +46,9 @@ async function loadDeposits() { } async function getSubtrees({ commitments }) { - const ganache = new Web3('http://localhost:8545', null, { transactionConfirmationBlocks: 1 }) - const newContractAddress = '0x1D340b022c7d83608F247a7f6fb5d96FE3450DA3' - const tempMixer = new ganache.eth.Contract(ABIv2, newContractAddress) + const tempMixer = new web3Ganache.eth.Contract(ABIv2, GANACHE_MIXER) for(let commitment of commitments) { - await tempMixer.methods.deposit(commitment).send({ value: toWei('0.1'), from: (await ganache.eth.getAccounts())[0], gas:5e6 }) + await tempMixer.methods.deposit(commitment).send({ value: toWei('0.1'), from: (await web3Ganache.eth.getAccounts())[0], gas:5e6 }) process.stdout.write('.') } process.stdout.write('\n') @@ -82,24 +87,23 @@ async function migrateState({ subtrees, lastRoot, commitments, nullifiers, newMi }) console.log('Gas used:', tx.gasUsed) } - const balance = await web3.eth.getBalance(PREVIOUS_MIXER) + const balance = await web3Source.eth.getBalance(PREVIOUS_MIXER) console.log('balance to send in wei', balance) - const finish = await newMixer.methods.finishMigration().send({ - gas: numberToHex(1500000), - gasPrice: toHex(toWei('10', 'gwei')), - from: account.address, - value: balance - }) - console.log('migration completed', finish.transactionHash) + // const finish = await newMixer.methods.finishMigration().send({ + // gas: numberToHex(1500000), + // gasPrice: toHex(toWei('10', 'gwei')), + // from: account.address, + // value: balance + // }) + // console.log('migration completed', finish.transactionHash) } async function main() { const { subtrees, lastRoot, commitments, nullifiers } = await loadDeposits() - const newContractAddress = '0x9715fC42892A8cE94e7ae58E332Cc4cDa102FfDF' - const newMixer = new web3Kovan.eth.Contract(ABIv2, newContractAddress) - web3Kovan.eth.accounts.wallet.add('0x' + process.env.PRIVATE_KEY) - web3Kovan.eth.defaultAccount = account.address + const newMixer = new web3Target.eth.Contract(ABIv2, NEW_MIXER) + web3Target.eth.accounts.wallet.add('0x' + process.env.PRIVATE_KEY) + web3Target.eth.defaultAccount = account.address console.log('commitments length ', commitments.length) console.log('nullifiers length ', nullifiers.length) await migrateState({ subtrees, lastRoot, commitments, nullifiers, newMixer }) From 917892ef1385845098c3e84583979d91922fd147 Mon Sep 17 00:00:00 2001 From: poma Date: Wed, 11 Dec 2019 23:49:43 +0700 Subject: [PATCH 10/14] wip --- migrationDeposits.js | 65 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/migrationDeposits.js b/migrationDeposits.js index d9c82c7..e278170 100644 --- a/migrationDeposits.js +++ b/migrationDeposits.js @@ -45,8 +45,73 @@ async function loadDeposits() { return { subtrees, lastRoot: toHex(root), commitments, nullifiers } } +function waitForTxReceipt(web3, txHash, attempts = 60, delay = 4000) { + return new Promise((resolve, reject) => { + const checkForTx = async (txHash, retryAttempt = 0) => { + const result = await web3.eth.getTransactionReceipt(txHash) + if (!result || !result.blockNumber) { + if (retryAttempt <= attempts) { + setTimeout(() => checkForTx(txHash, retryAttempt + 1), delay) + } else { + reject(new Error('tx was not mined')) + } + } else { + if (!result.status) { + reject(new Error(`The tx failed! https://kovan.etherscan.io/tx/${txHash}`)) + } else { + console.log(`A new successfuly mined tx https://kovan.etherscan.io/tx/${txHash}`) + resolve(result) + } + } + } + checkForTx(txHash) + }) +} + +async function makeDeposit({ web3, privKey, mixer, nonce, commitment }) { + const data = mixer.methods.deposit(commitment).encodeABI() + const tx = { + from: (await web3Ganache.eth.getAccounts())[0], + value: toWei('0.1'), + gas: 5e6, + gasPrice: toHex(toWei(20, 'gwei')), + to: mixer._address, + netId: config.netId, + data, + nonce: nonce + } + let signedTx = await web3.eth.accounts.signTransaction(tx, privKey) + return web3.eth.sendSignedTransaction(signedTx.rawTransaction) +} + +async function getNonce(address) { + const response = await axios.post(RPC_URL, { + jsonrpc:"2.0", + method:"eth_getTransactionCount", + params:[address, "latest"], + "id":1 + }) + return response.data.result +} + async function getSubtrees({ commitments }) { const tempMixer = new web3Ganache.eth.Contract(ABIv2, GANACHE_MIXER) + + let nonce = await getNonce((await web3Ganache.eth.getAccounts())[0]) + const chunkSize = 30 + let chunks = Math.ceil(commitments.length / chunkSize) + for(let c = 0; c < chunks; c++) { + const promises = [] + for(let i = c * chunkSize; i < Math.min(commitments.length, (c + 1) * chunkSize); i++) { + const n = toHex(nonce) + promises.push(makeDeposit({ web3: web3Ganache, privKey: process.env.PRIVATE_KEY, mixer: tempMixer, nonce: n, commitment: commitments[i] })) + nonce = bigInt(nonce).add(bigInt('1')) + } + let transactions = await Promise.all(promises) + console.log('Waiting for all deposits mined') + await waitForTxReceipt(web3Ganache, transactions.slice(-1).pop().txHash) + } + for(let commitment of commitments) { await tempMixer.methods.deposit(commitment).send({ value: toWei('0.1'), from: (await web3Ganache.eth.getAccounts())[0], gas:5e6 }) process.stdout.write('.') From 265540067a28dd22a84e3e1899673bd7b9e15752 Mon Sep 17 00:00:00 2001 From: Alexey Date: Wed, 11 Dec 2019 20:05:28 +0300 Subject: [PATCH 11/14] WIP --- migrationDeposits.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/migrationDeposits.js b/migrationDeposits.js index d9c82c7..73ebcbf 100644 --- a/migrationDeposits.js +++ b/migrationDeposits.js @@ -6,9 +6,6 @@ const web3Source = new Web3('https://mainnet.infura.io/v3/c7463beadf2144e68646ff const web3Target = new Web3('https://kovan.infura.io/v3/c7463beadf2144e68646ff049917b716', null, { transactionConfirmationBlocks: 1 }) const web3Ganache = new Web3('http://localhost:8545', null, { transactionConfirmationBlocks: 1 }) -const account = web3Source.eth.accounts.privateKeyToAccount('0x' + process.env.PRIVATE_KEY) -web3Source.eth.accounts.wallet.add('0x' + process.env.PRIVATE_KEY) -web3Source.eth.defaultAccount = account.address const ABI = [{ 'constant':false,'inputs':[{ 'name':'_newAccount','type':'address' }],'name':'changeOperator','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[],'name':'filled_subtrees','outputs':[{ 'name':'','type':'uint256[]' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[{ 'name':'','type':'uint256' }],'name':'nullifierHashes','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'verifier','outputs':[{ 'name':'','type':'address' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'transferValue','outputs':[{ 'name':'','type':'uint256' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'_commitments','type':'uint256[]' },{ 'name':'_nullifierHashes','type':'uint256[]' }],'name':'migrateState','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[],'name':'roots','outputs':[{ 'name':'','type':'uint256[]' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'_verifier','type':'address' },{ 'name':'_transferValue','type':'uint256' },{ 'name':'_merkleTreeHeight','type':'uint8' },{ 'name':'_emptyElement','type':'uint256' },{ 'name':'_operator','type':'address' },{ 'name':'_filled_subtrees','type':'uint256[]' },{ 'name':'_lastRoot','type':'uint256' }],'name':'initialize','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[{ 'name':'','type':'uint256' }],'name':'commitments','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'zeros','outputs':[{ 'name':'','type':'uint256[]' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'levels','outputs':[{ 'name':'','type':'uint256' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'a','type':'uint256[2]' },{ 'name':'b','type':'uint256[2][2]' },{ 'name':'c','type':'uint256[2]' },{ 'name':'input','type':'uint256[4]' }],'name':'withdraw','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[],'name':'operator','outputs':[{ 'name':'','type':'address' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'isDepositsEnabled','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[{ 'name':'nullifier','type':'uint256' }],'name':'isSpent','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[{ 'name':'left','type':'uint256' },{ 'name':'right','type':'uint256' }],'name':'hashLeftRight','outputs':[{ 'name':'mimc_hash','type':'uint256' }],'payable':false,'stateMutability':'pure','type':'function' },{ 'constant':true,'inputs':[],'name':'next_index','outputs':[{ 'name':'','type':'uint32' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'current_root','outputs':[{ 'name':'','type':'uint256' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'tree_levels','type':'uint256' },{ 'name':'zero_value','type':'uint256' },{ 'name':'filled_subtrees','type':'uint256[]' },{ 'name':'lastRoot','type':'uint256' }],'name':'initialize','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[{ 'name':'root','type':'uint256' }],'name':'isKnownRoot','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'commitment','type':'uint256' }],'name':'deposit','outputs':[],'payable':true,'stateMutability':'payable','type':'function' },{ 'constant':true,'inputs':[],'name':'getLastRoot','outputs':[{ 'name':'','type':'uint256' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[],'name':'toggleDeposits','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':false,'inputs':[],'name':'stopMigration','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[],'name':'isMigrating','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'payable':true,'stateMutability':'payable','type':'fallback' },{ 'anonymous':false,'inputs':[{ 'indexed':true,'name':'commitment','type':'uint256' },{ 'indexed':false,'name':'leafIndex','type':'uint256' },{ 'indexed':false,'name':'timestamp','type':'uint256' }],'name':'Deposit','type':'event' },{ 'anonymous':false,'inputs':[{ 'indexed':false,'name':'to','type':'address' },{ 'indexed':false,'name':'nullifierHash','type':'uint256' },{ 'indexed':false,'name':'fee','type':'uint256' }],'name':'Withdraw','type':'event' }] const ABIv2 = require('./build/contracts/ETHMixer.json').abi const snarkjs = require('snarkjs') @@ -18,7 +15,7 @@ const { numberToHex, toWei } = require('web3-utils') // 2. edit here const PREVIOUS_MIXER = '0xb541fc07bC7619fD4062A54d96268525cBC6FfEF' const GANACHE_MIXER = '0x38e6292EAB2fD2a70A81C87a194d921988d859aB' -const NEW_MIXER = '0x0a854Cf44f87FF135e2d49d2b482001853CfD98d' +const NEW_MIXER = '0xF7b4Ec760d9B13A3c1a934Eb3486C2eCB1E62784' function toHex(number, length = 32) { let str = number instanceof Buffer ? number.toString('hex') : bigInt(number).toString(16) @@ -68,7 +65,7 @@ async function migrateState({ subtrees, lastRoot, commitments, nullifiers, newMi await newMixer.methods.initializeTreeForMigration(subtrees, lastRoot).send({ gas: numberToHex(2500000), gasPrice: toHex(toWei('10', 'gwei')), - from: account.address + from: web3Target.eth.defaultAccount }) for(let i=0; i < commitments.length / loadBy; i++) { commitmentsToLoad = commitments.slice(i*loadBy, (i+1)*loadBy) @@ -83,7 +80,7 @@ async function migrateState({ subtrees, lastRoot, commitments, nullifiers, newMi ).send({ gas: numberToHex(6500000), gasPrice: toHex(toWei('10', 'gwei')), - from: account.address + from: web3Target.eth.defaultAccount }) console.log('Gas used:', tx.gasUsed) } @@ -102,8 +99,11 @@ async function migrateState({ subtrees, lastRoot, commitments, nullifiers, newMi async function main() { const { subtrees, lastRoot, commitments, nullifiers } = await loadDeposits() const newMixer = new web3Target.eth.Contract(ABIv2, NEW_MIXER) + + const account = web3Target.eth.accounts.privateKeyToAccount('0x' + process.env.PRIVATE_KEY) web3Target.eth.accounts.wallet.add('0x' + process.env.PRIVATE_KEY) web3Target.eth.defaultAccount = account.address + console.log('commitments length ', commitments.length) console.log('nullifiers length ', nullifiers.length) await migrateState({ subtrees, lastRoot, commitments, nullifiers, newMixer }) From 1be468c8635bf79c817aadfc32d211152e3dc287 Mon Sep 17 00:00:00 2001 From: Alexey Date: Wed, 11 Dec 2019 23:04:38 +0300 Subject: [PATCH 12/14] done --- migrationDeposits.js | 98 +++++++++++++++----------------------------- package.json | 2 +- 2 files changed, 34 insertions(+), 66 deletions(-) diff --git a/migrationDeposits.js b/migrationDeposits.js index e278170..4f2d8a3 100644 --- a/migrationDeposits.js +++ b/migrationDeposits.js @@ -2,13 +2,13 @@ require('dotenv').config() const Web3 = require('web3') // 1. edit here -const web3Source = new Web3('https://mainnet.infura.io/v3/c7463beadf2144e68646ff049917b716', null, { transactionConfirmationBlocks: 1 }) -const web3Target = new Web3('https://kovan.infura.io/v3/c7463beadf2144e68646ff049917b716', null, { transactionConfirmationBlocks: 1 }) -const web3Ganache = new Web3('http://localhost:8545', null, { transactionConfirmationBlocks: 1 }) +const SOURCE_RPC = 'https://mainnet.infura.io/v3/c7463beadf2144e68646ff049917b716' +const TARGET_RPC = 'https://kovan.poa.network' +const HELPER_RPC = 'https://kovan.poa.network' +const web3Source = new Web3(SOURCE_RPC, null, { transactionConfirmationBlocks: 1 }) +const web3Target = new Web3(TARGET_RPC, null, { transactionConfirmationBlocks: 1 }) +const web3Helper = new Web3(HELPER_RPC, null, { transactionConfirmationBlocks: 1 }) -const account = web3Source.eth.accounts.privateKeyToAccount('0x' + process.env.PRIVATE_KEY) -web3Source.eth.accounts.wallet.add('0x' + process.env.PRIVATE_KEY) -web3Source.eth.defaultAccount = account.address const ABI = [{ 'constant':false,'inputs':[{ 'name':'_newAccount','type':'address' }],'name':'changeOperator','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[],'name':'filled_subtrees','outputs':[{ 'name':'','type':'uint256[]' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[{ 'name':'','type':'uint256' }],'name':'nullifierHashes','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'verifier','outputs':[{ 'name':'','type':'address' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'transferValue','outputs':[{ 'name':'','type':'uint256' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'_commitments','type':'uint256[]' },{ 'name':'_nullifierHashes','type':'uint256[]' }],'name':'migrateState','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[],'name':'roots','outputs':[{ 'name':'','type':'uint256[]' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'_verifier','type':'address' },{ 'name':'_transferValue','type':'uint256' },{ 'name':'_merkleTreeHeight','type':'uint8' },{ 'name':'_emptyElement','type':'uint256' },{ 'name':'_operator','type':'address' },{ 'name':'_filled_subtrees','type':'uint256[]' },{ 'name':'_lastRoot','type':'uint256' }],'name':'initialize','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[{ 'name':'','type':'uint256' }],'name':'commitments','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'zeros','outputs':[{ 'name':'','type':'uint256[]' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'levels','outputs':[{ 'name':'','type':'uint256' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'a','type':'uint256[2]' },{ 'name':'b','type':'uint256[2][2]' },{ 'name':'c','type':'uint256[2]' },{ 'name':'input','type':'uint256[4]' }],'name':'withdraw','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[],'name':'operator','outputs':[{ 'name':'','type':'address' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'isDepositsEnabled','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[{ 'name':'nullifier','type':'uint256' }],'name':'isSpent','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[{ 'name':'left','type':'uint256' },{ 'name':'right','type':'uint256' }],'name':'hashLeftRight','outputs':[{ 'name':'mimc_hash','type':'uint256' }],'payable':false,'stateMutability':'pure','type':'function' },{ 'constant':true,'inputs':[],'name':'next_index','outputs':[{ 'name':'','type':'uint32' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':true,'inputs':[],'name':'current_root','outputs':[{ 'name':'','type':'uint256' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'tree_levels','type':'uint256' },{ 'name':'zero_value','type':'uint256' },{ 'name':'filled_subtrees','type':'uint256[]' },{ 'name':'lastRoot','type':'uint256' }],'name':'initialize','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[{ 'name':'root','type':'uint256' }],'name':'isKnownRoot','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[{ 'name':'commitment','type':'uint256' }],'name':'deposit','outputs':[],'payable':true,'stateMutability':'payable','type':'function' },{ 'constant':true,'inputs':[],'name':'getLastRoot','outputs':[{ 'name':'','type':'uint256' }],'payable':false,'stateMutability':'view','type':'function' },{ 'constant':false,'inputs':[],'name':'toggleDeposits','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':false,'inputs':[],'name':'stopMigration','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function' },{ 'constant':true,'inputs':[],'name':'isMigrating','outputs':[{ 'name':'','type':'bool' }],'payable':false,'stateMutability':'view','type':'function' },{ 'payable':true,'stateMutability':'payable','type':'fallback' },{ 'anonymous':false,'inputs':[{ 'indexed':true,'name':'commitment','type':'uint256' },{ 'indexed':false,'name':'leafIndex','type':'uint256' },{ 'indexed':false,'name':'timestamp','type':'uint256' }],'name':'Deposit','type':'event' },{ 'anonymous':false,'inputs':[{ 'indexed':false,'name':'to','type':'address' },{ 'indexed':false,'name':'nullifierHash','type':'uint256' },{ 'indexed':false,'name':'fee','type':'uint256' }],'name':'Withdraw','type':'event' }] const ABIv2 = require('./build/contracts/ETHMixer.json').abi const snarkjs = require('snarkjs') @@ -17,8 +17,8 @@ const { numberToHex, toWei } = require('web3-utils') // 2. edit here const PREVIOUS_MIXER = '0xb541fc07bC7619fD4062A54d96268525cBC6FfEF' -const GANACHE_MIXER = '0x38e6292EAB2fD2a70A81C87a194d921988d859aB' -const NEW_MIXER = '0x0a854Cf44f87FF135e2d49d2b482001853CfD98d' +const HELPER_MIXER = '' +const NEW_MIXER = '' function toHex(number, length = 32) { let str = number instanceof Buffer ? number.toString('hex') : bigInt(number).toString(16) @@ -45,78 +45,39 @@ async function loadDeposits() { return { subtrees, lastRoot: toHex(root), commitments, nullifiers } } -function waitForTxReceipt(web3, txHash, attempts = 60, delay = 4000) { - return new Promise((resolve, reject) => { - const checkForTx = async (txHash, retryAttempt = 0) => { - const result = await web3.eth.getTransactionReceipt(txHash) - if (!result || !result.blockNumber) { - if (retryAttempt <= attempts) { - setTimeout(() => checkForTx(txHash, retryAttempt + 1), delay) - } else { - reject(new Error('tx was not mined')) - } - } else { - if (!result.status) { - reject(new Error(`The tx failed! https://kovan.etherscan.io/tx/${txHash}`)) - } else { - console.log(`A new successfuly mined tx https://kovan.etherscan.io/tx/${txHash}`) - resolve(result) - } - } - } - checkForTx(txHash) - }) -} - async function makeDeposit({ web3, privKey, mixer, nonce, commitment }) { const data = mixer.methods.deposit(commitment).encodeABI() const tx = { - from: (await web3Ganache.eth.getAccounts())[0], + from: web3Helper.eth.defaultAccount, value: toWei('0.1'), - gas: 5e6, - gasPrice: toHex(toWei(20, 'gwei')), + gas: 2e6, + gasPrice: toHex(toWei('2', 'gwei')), to: mixer._address, - netId: config.netId, + netId: await web3.eth.net.getId(), data, - nonce: nonce + nonce } let signedTx = await web3.eth.accounts.signTransaction(tx, privKey) return web3.eth.sendSignedTransaction(signedTx.rawTransaction) } -async function getNonce(address) { - const response = await axios.post(RPC_URL, { - jsonrpc:"2.0", - method:"eth_getTransactionCount", - params:[address, "latest"], - "id":1 - }) - return response.data.result -} - async function getSubtrees({ commitments }) { - const tempMixer = new web3Ganache.eth.Contract(ABIv2, GANACHE_MIXER) + const tempMixer = new web3Helper.eth.Contract(ABIv2, HELPER_MIXER) - let nonce = await getNonce((await web3Ganache.eth.getAccounts())[0]) - const chunkSize = 30 + let nonce = await web3Helper.eth.getTransactionCount(web3Helper.eth.defaultAccount) + const chunkSize = 80 let chunks = Math.ceil(commitments.length / chunkSize) for(let c = 0; c < chunks; c++) { - const promises = [] + let lastTransaction for(let i = c * chunkSize; i < Math.min(commitments.length, (c + 1) * chunkSize); i++) { const n = toHex(nonce) - promises.push(makeDeposit({ web3: web3Ganache, privKey: process.env.PRIVATE_KEY, mixer: tempMixer, nonce: n, commitment: commitments[i] })) + lastTransaction = makeDeposit({ web3: web3Helper, privKey: process.env.PRIVATE_KEY, mixer: tempMixer, nonce: n, commitment: commitments[i] }) nonce = bigInt(nonce).add(bigInt('1')) } - let transactions = await Promise.all(promises) - console.log('Waiting for all deposits mined') - await waitForTxReceipt(web3Ganache, transactions.slice(-1).pop().txHash) + console.log(`Waiting for the ${c}th chunk`) + await lastTransaction } - for(let commitment of commitments) { - await tempMixer.methods.deposit(commitment).send({ value: toWei('0.1'), from: (await web3Ganache.eth.getAccounts())[0], gas:5e6 }) - process.stdout.write('.') - } - process.stdout.write('\n') let subtrees = [] for (let i = 0; i < process.env.MERKLE_TREE_HEIGHT; i++) { subtrees.push(await tempMixer.methods.filledSubtrees(i).call()) @@ -133,7 +94,7 @@ async function migrateState({ subtrees, lastRoot, commitments, nullifiers, newMi await newMixer.methods.initializeTreeForMigration(subtrees, lastRoot).send({ gas: numberToHex(2500000), gasPrice: toHex(toWei('10', 'gwei')), - from: account.address + from: web3Target.eth.defaultAccount }) for(let i=0; i < commitments.length / loadBy; i++) { commitmentsToLoad = commitments.slice(i*loadBy, (i+1)*loadBy) @@ -148,27 +109,34 @@ async function migrateState({ subtrees, lastRoot, commitments, nullifiers, newMi ).send({ gas: numberToHex(6500000), gasPrice: toHex(toWei('10', 'gwei')), - from: account.address + from: web3Target.eth.defaultAccount }) console.log('Gas used:', tx.gasUsed) } const balance = await web3Source.eth.getBalance(PREVIOUS_MIXER) console.log('balance to send in wei', balance) + // 3. Decide should we uncomment here // const finish = await newMixer.methods.finishMigration().send({ // gas: numberToHex(1500000), // gasPrice: toHex(toWei('10', 'gwei')), - // from: account.address, + // from: web3Target.eth.defaultAccount, // value: balance // }) // console.log('migration completed', finish.transactionHash) - } async function main() { + const helperAccount = web3Helper.eth.accounts.privateKeyToAccount('0x' + process.env.PRIVATE_KEY) + web3Helper.eth.accounts.wallet.add('0x' + process.env.PRIVATE_KEY) + web3Helper.eth.defaultAccount = helperAccount.address + + const targetAccount = web3Target.eth.accounts.privateKeyToAccount('0x' + process.env.PRIVATE_KEY) + web3Target.eth.accounts.wallet.add('0x' + process.env.PRIVATE_KEY) + web3Target.eth.defaultAccount = targetAccount.address + const { subtrees, lastRoot, commitments, nullifiers } = await loadDeposits() const newMixer = new web3Target.eth.Contract(ABIv2, NEW_MIXER) - web3Target.eth.accounts.wallet.add('0x' + process.env.PRIVATE_KEY) - web3Target.eth.defaultAccount = account.address + console.log('commitments length ', commitments.length) console.log('nullifiers length ', nullifiers.length) await migrateState({ subtrees, lastRoot, commitments, nullifiers, newMixer }) diff --git a/package.json b/package.json index bc7ea0c..6ab1d33 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "migrate:rinkeby": "npx truffle migrate --network rinkeby --reset", "migrate:mainnet": "npx truffle migrate --network mainnet", "eslint": "npx eslint --ignore-path .gitignore .", - "flat": "truffle-flattener contracts/ETHMixer.sol > ETHMixer_flat.sol contracts/ERC20Mixer.sol > ERC20Mixer_flat.sol" + "flat": "npx truffle-flattener contracts/ETHMixer.sol > ETHMixer_flat.sol && npx truffle-flattener contracts/ERC20Mixer.sol > ERC20Mixer_flat.sol" }, "keywords": [], "author": "", From bb3c4aae52d4eb33cb4c7e61a376daf5def9e759 Mon Sep 17 00:00:00 2001 From: Alexey Date: Fri, 13 Dec 2019 23:01:38 +0300 Subject: [PATCH 13/14] fix cli.js --- cli.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cli.js b/cli.js index 63a9235..9b6ed90 100755 --- a/cli.js +++ b/cli.js @@ -56,7 +56,7 @@ async function deposit() { const deposit = createDeposit(rbigint(31), rbigint(31)) console.log('Submitting deposit transaction') - await mixer.methods.deposit(toHex(deposit.commitment)).send({ value: ETH_AMOUNT, from: senderAccount, gas:1e6 }) + await mixer.methods.deposit(toHex(deposit.commitment)).send({ value: ETH_AMOUNT, from: senderAccount, gas:2e6 }) const note = toHex(deposit.preimage, 62) console.log('Your note:', note) @@ -71,14 +71,14 @@ async function depositErc20() { if(ERC20_TOKEN === '') { console.log('Minting some test tokens to deposit') - await erc20.methods.mint(senderAccount, TOKEN_AMOUNT).send({ from: senderAccount, gas: 1e6 }) + await erc20.methods.mint(senderAccount, TOKEN_AMOUNT).send({ from: senderAccount, gas: 2e6 }) } console.log('Approving tokens for deposit') await erc20.methods.approve(erc20mixer._address, TOKEN_AMOUNT).send({ from: senderAccount, gas:1e6 }) console.log('Submitting deposit transaction') - await erc20mixer.methods.deposit(toHex(deposit.commitment)).send({ from: senderAccount, gas:1e6 }) + await erc20mixer.methods.deposit(toHex(deposit.commitment)).send({ from: senderAccount, gas:2e6 }) const note = toHex(deposit.preimage, 62) console.log('Your note:', note) @@ -333,7 +333,7 @@ function printHelp(code = 0) { Check address balance $ ./cli.js balance
- + Perform an automated test $ ./cli.js test $ ./cli.js testRelay From 6cd0ae8d872d327ea7af34decc81e049a5c168f7 Mon Sep 17 00:00:00 2001 From: Alexey Date: Fri, 13 Dec 2019 23:36:32 +0300 Subject: [PATCH 14/14] fix cli --- cli.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli.js b/cli.js index da57a4a..9e575f6 100755 --- a/cli.js +++ b/cli.js @@ -56,7 +56,7 @@ async function deposit() { const deposit = createDeposit(rbigint(31), rbigint(31)) console.log('Submitting deposit transaction') - await mixer.methods.deposit(toHex(deposit.commitment)).send({ value: ETH_AMOUNT, from: senderAccount, gas:2e6 }) + await tornado.methods.deposit(toHex(deposit.commitment)).send({ value: ETH_AMOUNT, from: senderAccount, gas:2e6 }) const note = toHex(deposit.preimage, 62) console.log('Your note:', note) @@ -78,7 +78,7 @@ async function depositErc20() { await erc20.methods.approve(erc20tornado._address, TOKEN_AMOUNT).send({ from: senderAccount, gas:1e6 }) console.log('Submitting deposit transaction') - await erc20mixer.methods.deposit(toHex(deposit.commitment)).send({ from: senderAccount, gas:2e6 }) + await erc20tornado.methods.deposit(toHex(deposit.commitment)).send({ from: senderAccount, gas:2e6 }) const note = toHex(deposit.preimage, 62) console.log('Your note:', note)