diff --git a/contracts/TornadoTrees.sol b/contracts/TornadoTrees.sol index d1e26aa..b76b256 100644 --- a/contracts/TornadoTrees.sol +++ b/contracts/TornadoTrees.sol @@ -79,42 +79,40 @@ contract TornadoTrees is EnsResolve { uint256 depositLeaf = _tornadoTreesV1.lastProcessedDepositLeaf(); require(depositLeaf % CHUNK_SIZE == 0, "Incorrect TornadoTrees state"); lastProcessedDepositLeaf = depositLeaf; - depositsLength = depositV1Length = 4; // todo + depositsLength = depositV1Length = findArrayLength(_tornadoTreesV1, "deposits(uint256)", 3); // todo uint256 withdrawalLeaf = _tornadoTreesV1.lastProcessedWithdrawalLeaf(); require(withdrawalLeaf % CHUNK_SIZE == 0, "Incorrect TornadoTrees state"); lastProcessedWithdrawalLeaf = withdrawalLeaf; - withdrawalsLength = withdrawalsV1Length = 4; // todo + withdrawalsLength = withdrawalsV1Length = findArrayLength(_tornadoTreesV1, "withdrawals(uint256)", 3); // todo } // todo implement binary search - function findDepositLength( + function findArrayLength( ITornadoTreesV1 _tornadoTreesV1, - uint256 _from, - uint256 _to + string memory _signature, + uint256 _from ) public view returns (uint256) { bool success; bytes memory data; - uint256 previousTo; - (success, data) = address(_tornadoTreesV1).staticcall{ gas: 3000 }(abi.encodeWithSignature("deposits(uint256)", _to)); - while (!success) { - previousTo = _to; - _to = (_from + _to) / 2; - (success, data) = address(_tornadoTreesV1).staticcall{ gas: 3000 }(abi.encodeWithSignature("deposits(uint256)", _to)); + (success, data) = address(_tornadoTreesV1).staticcall{ gas: 3000 }(abi.encodeWithSignature(_signature, _from)); + while (success) { + _from++; + (success, data) = address(_tornadoTreesV1).staticcall{ gas: 3000 }(abi.encodeWithSignature(_signature, _from)); } - return _to; + return _from; } - function registerDeposit(address _instance, bytes32 _commitment) external onlyTornadoProxy { + function registerDeposit(address _instance, bytes32 _commitment) public onlyTornadoProxy { uint256 _depositsLength = depositsLength; deposits[_depositsLength] = keccak256(abi.encode(_instance, _commitment, blockNumber())); emit DepositData(_instance, _commitment, blockNumber(), _depositsLength); depositsLength = _depositsLength + 1; } - function registerWithdrawal(address _instance, bytes32 _nullifierHash) external onlyTornadoProxy { + function registerWithdrawal(address _instance, bytes32 _nullifierHash) public onlyTornadoProxy { uint256 _withdrawalsLength = withdrawalsLength; withdrawals[_withdrawalsLength] = keccak256(abi.encode(_instance, _nullifierHash, blockNumber())); emit WithdrawalData(_instance, _nullifierHash, blockNumber(), _withdrawalsLength); diff --git a/contracts/mocks/TornadoTreesMock.sol b/contracts/mocks/TornadoTreesMock.sol index a185a65..fb3176e 100644 --- a/contracts/mocks/TornadoTreesMock.sol +++ b/contracts/mocks/TornadoTreesMock.sol @@ -37,12 +37,10 @@ contract TornadoTreesMock is TornadoTrees { uint256 _withdrawBlockNumber ) public { setBlockNumber(_depositBlockNumber); - deposits[depositsLength] = keccak256(abi.encode(_instance, _commitment, blockNumber())); - depositsLength++; + registerDeposit(_instance, _commitment); setBlockNumber(_withdrawBlockNumber); - withdrawals[withdrawalsLength] = keccak256(abi.encode(_instance, _nullifier, blockNumber())); - withdrawalsLength++; + registerWithdrawal(_instance, _nullifier); } function updateDepositTreeMock( diff --git a/hardhat.config.js b/hardhat.config.js index 9615c71..ea3d71f 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -24,6 +24,9 @@ const config = { blockGasLimit: 950000000, }, }, + mocha: { + timeout: 600000, + }, } if (process.env.NETWORK) { diff --git a/test/tornadoTrees.test.js b/test/tornadoTrees.test.js index c21d8ae..1b88a25 100644 --- a/test/tornadoTrees.test.js +++ b/test/tornadoTrees.test.js @@ -36,6 +36,7 @@ describe('TornadoTrees', function () { let tornadoTrees let tornadoTreesV1 let notes + let depositDataEventFilter const depositEvents = [] const withdrawalEvents = [] @@ -77,6 +78,7 @@ describe('TornadoTrees', function () { tornadoTreesV1.address, verifier.address, ) + depositDataEventFilter = tornadoTrees.filters.DepositData() }) describe('#updateDepositTree', () => { @@ -119,8 +121,7 @@ describe('TornadoTrees', function () { let updatedRoot = await tornadoTrees.depositRoot() expect(updatedRoot).to.be.equal(tree.root()) - const filter = tornadoTrees.filters.DepositData() - const migratedEvents = await tornadoTrees.queryFilter(filter) + const migratedEvents = await tornadoTrees.queryFilter(depositDataEventFilter) migratedEvents.forEach((e, i) => { expect(e.args.index).to.be.equal(i) }) @@ -128,18 +129,72 @@ describe('TornadoTrees', function () { for (let i = 0; i < notes.length; i++) { await register(notes[i], tornadoTrees, tornadoProxy) } - let registeredEvents = await tornadoTrees.queryFilter(filter) + let registeredEvents = await tornadoTrees.queryFilter(depositDataEventFilter) registeredEvents = registeredEvents.map((e) => ({ hash: toFixedHex(e.args.hash), instance: toFixedHex(e.args.instance, 20), block: toFixedHex(e.args.block, 4), })) - ;({ input, args } = controller.batchTreeUpdate(tree, registeredEvents)) + ;({ input, args } = controller.batchTreeUpdate(tree, registeredEvents.slice(0, 4))) proof = await controller.prove(input, './artifacts/circuits/BatchTreeUpdate') await tornadoTrees.updateDepositTree(proof, ...args) updatedRoot = await tornadoTrees.depositRoot() expect(updatedRoot).to.be.equal(tree.root()) }) + // it('should work for batch+N filled v1 tree', async () => { + // for (let i = 4; i < 6; i++) { + // notes.push({ + // instance: instances[i % instances.length], + // depositBlock: blocks[i % blocks.length], + // withdrawalBlock: 2 + i + i * 4 * 60 * 24, + // commitment: randomBN(), + // nullifierHash: randomBN(), + // }) + // await register(notes[i], tornadoTreesV1, tornadoProxy) + // } + + // const TornadoTrees = await ethers.getContractFactory('TornadoTreesMock') + // const newTornadoTrees = await TornadoTrees.deploy( + // operator.address, + // tornadoProxy.address, + // tornadoTreesV1.address, + // verifier.address, + // ) + + // let { input, args } = controller.batchTreeUpdate(tree, depositEvents) + // let proof = await controller.prove(input, './artifacts/circuits/BatchTreeUpdate') + // await newTornadoTrees.updateDepositTree(proof, ...args) + // let updatedRoot = await newTornadoTrees.depositRoot() + // expect(updatedRoot).to.be.equal(tree.root()) + + // // register 6 new deposits for the new trees + // for (let i = 0; i < notes.length; i++) { + // await register(notes[i], newTornadoTrees, tornadoProxy) + // } + + // // get 2 events from v1 tress + // const events = notes.slice(4).map((note) => ({ + // hash: toFixedHex(note.commitment), + // instance: toFixedHex(note.instance, 20), + // block: toFixedHex(note.depositBlock, 4), + // })) + + // const registeredEvents = await newTornadoTrees.queryFilter(depositDataEventFilter) + // console.log('registeredEvents', JSON.stringify(registeredEvents, null, 2)) + // // events = events.concat( + // // registeredEvents.slice(0, 2).map((e) => ({ + // // hash: toFixedHex(e.args.hash), + // // instance: toFixedHex(e.args.instance, 20), + // // block: toFixedHex(e.args.block, 4), + // // })), + // // ) + // // console.log('events', events) + // // ;({ input, args } = controller.batchTreeUpdate(tree, events)) + // // proof = await controller.prove(input, './artifacts/circuits/BatchTreeUpdate') + // // await newTornadoTrees.updateDepositTree(proof, ...args) + // // updatedRoot = await newTornadoTrees.depositRoot() + // // expect(updatedRoot).to.be.equal(tree.root()) + // }) it('should reject for partially filled tree') it('should reject for outdated deposit root') it('should reject for incorrect insert index')