add new tests; fix bug
This commit is contained in:
parent
4df9a516db
commit
f5f5a216c1
@ -29,12 +29,12 @@ contract TornadoTrees is EnsResolve {
|
|||||||
mapping(uint256 => bytes32) public deposits;
|
mapping(uint256 => bytes32) public deposits;
|
||||||
uint256 public depositsLength;
|
uint256 public depositsLength;
|
||||||
uint256 public lastProcessedDepositLeaf;
|
uint256 public lastProcessedDepositLeaf;
|
||||||
uint256 public immutable lastV1Deposit;
|
uint256 public immutable depositV1Length;
|
||||||
|
|
||||||
mapping(uint256 => bytes32) public withdrawals;
|
mapping(uint256 => bytes32) public withdrawals;
|
||||||
uint256 public withdrawalsLength;
|
uint256 public withdrawalsLength;
|
||||||
uint256 public lastProcessedWithdrawalLeaf;
|
uint256 public lastProcessedWithdrawalLeaf;
|
||||||
uint256 public immutable lastV1Withdrawal;
|
uint256 public immutable withdrawalsV1Length;
|
||||||
|
|
||||||
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);
|
||||||
@ -79,25 +79,46 @@ contract TornadoTrees is EnsResolve {
|
|||||||
uint256 depositLeaf = _tornadoTreesV1.lastProcessedDepositLeaf();
|
uint256 depositLeaf = _tornadoTreesV1.lastProcessedDepositLeaf();
|
||||||
require(depositLeaf % CHUNK_SIZE == 0, "Incorrect TornadoTrees state");
|
require(depositLeaf % CHUNK_SIZE == 0, "Incorrect TornadoTrees state");
|
||||||
lastProcessedDepositLeaf = depositLeaf;
|
lastProcessedDepositLeaf = depositLeaf;
|
||||||
depositsLength = lastV1Deposit = 1; // todo
|
depositsLength = depositV1Length = 4; // todo
|
||||||
|
|
||||||
|
|
||||||
uint256 withdrawalLeaf = _tornadoTreesV1.lastProcessedWithdrawalLeaf();
|
uint256 withdrawalLeaf = _tornadoTreesV1.lastProcessedWithdrawalLeaf();
|
||||||
require(withdrawalLeaf % CHUNK_SIZE == 0, "Incorrect TornadoTrees state");
|
require(withdrawalLeaf % CHUNK_SIZE == 0, "Incorrect TornadoTrees state");
|
||||||
lastProcessedWithdrawalLeaf = withdrawalLeaf;
|
lastProcessedWithdrawalLeaf = withdrawalLeaf;
|
||||||
withdrawalsLength = lastV1Withdrawal = 1; // todo
|
withdrawalsLength = withdrawalsV1Length = 4; // todo
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo implement binary search
|
||||||
|
function findDepositLength(
|
||||||
|
ITornadoTreesV1 _tornadoTreesV1,
|
||||||
|
uint256 _from,
|
||||||
|
uint256 _to
|
||||||
|
) 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
return _to;
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerDeposit(address _instance, bytes32 _commitment) external onlyTornadoProxy {
|
function registerDeposit(address _instance, bytes32 _commitment) external onlyTornadoProxy {
|
||||||
uint256 _depositsLength = depositsLength;
|
uint256 _depositsLength = depositsLength;
|
||||||
deposits[_depositsLength] = keccak256(abi.encode(_instance, _commitment, blockNumber()));
|
deposits[_depositsLength] = keccak256(abi.encode(_instance, _commitment, blockNumber()));
|
||||||
emit DepositData(_instance, _commitment, blockNumber(), _depositsLength - 1);
|
emit DepositData(_instance, _commitment, blockNumber(), _depositsLength);
|
||||||
|
depositsLength = _depositsLength + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerWithdrawal(address _instance, bytes32 _nullifierHash) external onlyTornadoProxy {
|
function registerWithdrawal(address _instance, bytes32 _nullifierHash) external onlyTornadoProxy {
|
||||||
uint256 _withdrawalsLength = withdrawalsLength;
|
uint256 _withdrawalsLength = withdrawalsLength;
|
||||||
withdrawals[_withdrawalsLength] = keccak256(abi.encode(_instance, _nullifierHash, blockNumber()));
|
withdrawals[_withdrawalsLength] = keccak256(abi.encode(_instance, _nullifierHash, blockNumber()));
|
||||||
emit WithdrawalData(_instance, _nullifierHash, blockNumber(), _withdrawalsLength - 1);
|
emit WithdrawalData(_instance, _nullifierHash, blockNumber(), _withdrawalsLength);
|
||||||
|
withdrawalsLength = _withdrawalsLength + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateDepositTree(
|
function updateDepositTree(
|
||||||
@ -119,18 +140,17 @@ contract TornadoTrees is EnsResolve {
|
|||||||
mstore(add(data, 0x40), _newRoot)
|
mstore(add(data, 0x40), _newRoot)
|
||||||
mstore(add(data, 0x20), _currentRoot)
|
mstore(add(data, 0x20), _currentRoot)
|
||||||
}
|
}
|
||||||
uint256 _lastV1Deposit = lastV1Deposit;
|
|
||||||
for (uint256 i = 0; i < CHUNK_SIZE; i++) {
|
for (uint256 i = 0; i < CHUNK_SIZE; i++) {
|
||||||
(bytes32 hash, address instance, uint32 blockNumber) = (_events[i].hash, _events[i].instance, _events[i].block);
|
(bytes32 hash, address instance, uint32 blockNumber) = (_events[i].hash, _events[i].instance, _events[i].block);
|
||||||
bytes32 leafHash = keccak256(abi.encode(instance, hash, blockNumber));
|
bytes32 leafHash = keccak256(abi.encode(instance, hash, blockNumber));
|
||||||
bytes32 deposit = offset + i > _lastV1Deposit ? deposits[offset + i] : tornadoTreesV1.deposits(offset + i);
|
bytes32 deposit = offset + i >= depositV1Length ? 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)
|
mstore(add(add(data, mul(ITEM_SIZE, i)), 0x7c), blockNumber)
|
||||||
mstore(add(add(data, mul(ITEM_SIZE, i)), 0x78), instance)
|
mstore(add(add(data, mul(ITEM_SIZE, i)), 0x78), instance)
|
||||||
mstore(add(add(data, mul(ITEM_SIZE, i)), 0x64), hash)
|
mstore(add(add(data, mul(ITEM_SIZE, i)), 0x64), hash)
|
||||||
}
|
}
|
||||||
if (offset + i > _lastV1Deposit) {
|
if (offset + i >= depositV1Length) {
|
||||||
delete deposits[offset + i];
|
delete deposits[offset + i];
|
||||||
} else {
|
} else {
|
||||||
emit DepositData(instance, hash, blockNumber, offset + i);
|
emit DepositData(instance, hash, blockNumber, offset + i);
|
||||||
@ -166,11 +186,10 @@ contract TornadoTrees is EnsResolve {
|
|||||||
mstore(add(data, 0x40), _newRoot)
|
mstore(add(data, 0x40), _newRoot)
|
||||||
mstore(add(data, 0x20), _currentRoot)
|
mstore(add(data, 0x20), _currentRoot)
|
||||||
}
|
}
|
||||||
uint256 _lastV1Withdrawal = lastV1Withdrawal;
|
|
||||||
for (uint256 i = 0; i < CHUNK_SIZE; i++) {
|
for (uint256 i = 0; i < CHUNK_SIZE; i++) {
|
||||||
(bytes32 hash, address instance, uint32 blockNumber) = (_events[i].hash, _events[i].instance, _events[i].block);
|
(bytes32 hash, address instance, uint32 blockNumber) = (_events[i].hash, _events[i].instance, _events[i].block);
|
||||||
bytes32 leafHash = keccak256(abi.encode(instance, hash, blockNumber));
|
bytes32 leafHash = keccak256(abi.encode(instance, hash, blockNumber));
|
||||||
bytes32 withdrawal = offset + i > _lastV1Withdrawal ? 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");
|
||||||
require(uint256(hash) < SNARK_FIELD, "Hash out of range");
|
require(uint256(hash) < SNARK_FIELD, "Hash out of range");
|
||||||
assembly {
|
assembly {
|
||||||
@ -178,7 +197,7 @@ contract TornadoTrees is EnsResolve {
|
|||||||
mstore(add(add(data, mul(ITEM_SIZE, i)), 0x78), instance)
|
mstore(add(add(data, mul(ITEM_SIZE, i)), 0x78), instance)
|
||||||
mstore(add(add(data, mul(ITEM_SIZE, i)), 0x64), hash)
|
mstore(add(add(data, mul(ITEM_SIZE, i)), 0x64), hash)
|
||||||
}
|
}
|
||||||
if (offset + i > _lastV1Withdrawal) {
|
if (offset + i >= withdrawalsV1Length) {
|
||||||
delete withdrawals[offset + i];
|
delete withdrawals[offset + i];
|
||||||
} else {
|
} else {
|
||||||
emit WithdrawalData(instance, hash, blockNumber, offset + i);
|
emit WithdrawalData(instance, hash, blockNumber, offset + i);
|
||||||
|
@ -77,7 +77,6 @@ describe('TornadoTrees', function () {
|
|||||||
tornadoTreesV1.address,
|
tornadoTreesV1.address,
|
||||||
verifier.address,
|
verifier.address,
|
||||||
)
|
)
|
||||||
await tornadoTrees.migrate(depositEvents, withdrawalEvents)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('#updateDepositTree', () => {
|
describe('#updateDepositTree', () => {
|
||||||
@ -121,18 +120,34 @@ describe('TornadoTrees', function () {
|
|||||||
|
|
||||||
describe('#getRegisteredDeposits', () => {
|
describe('#getRegisteredDeposits', () => {
|
||||||
it('should work', async () => {
|
it('should work', async () => {
|
||||||
|
for (let i = 0; i < 2 ** CHUNK_TREE_HEIGHT; i++) {
|
||||||
|
notes[i] = {
|
||||||
|
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], tornadoTrees, tornadoProxy)
|
||||||
|
}
|
||||||
|
|
||||||
const abi = new ethers.utils.AbiCoder()
|
const abi = new ethers.utils.AbiCoder()
|
||||||
const count = await tornadoTrees.depositsLength()
|
const count = await tornadoTrees.depositsLength()
|
||||||
const _deposits = await tornadoTrees.getRegisteredDeposits()
|
const _deposits = await tornadoTrees.getRegisteredDeposits()
|
||||||
expect(count).to.be.equal(notes.length)
|
expect(count).to.be.equal(notes.length * 2)
|
||||||
_deposits.forEach((hash, i) => {
|
_deposits.forEach((hash, i) => {
|
||||||
const encodedData = abi.encode(
|
if (i < notes.length) {
|
||||||
['address', 'bytes32', 'uint256'],
|
expect(hash).to.be.equal('0x0000000000000000000000000000000000000000000000000000000000000000')
|
||||||
[notes[i].instance, toFixedHex(notes[i].commitment), notes[i].depositBlock],
|
} else {
|
||||||
)
|
const index = i - notes.length
|
||||||
const leaf = ethers.utils.keccak256(encodedData)
|
const encodedData = abi.encode(
|
||||||
|
['address', 'bytes32', 'uint256'],
|
||||||
|
[notes[index].instance, toFixedHex(notes[index].commitment), notes[index].depositBlock],
|
||||||
|
)
|
||||||
|
const leaf = ethers.utils.keccak256(encodedData)
|
||||||
|
|
||||||
expect(leaf).to.be.equal(hash)
|
expect(leaf).to.be.equal(hash)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
// res.length.should.be.equal(1)
|
// res.length.should.be.equal(1)
|
||||||
// res[0].should.be.true
|
// res[0].should.be.true
|
||||||
@ -149,18 +164,34 @@ describe('TornadoTrees', function () {
|
|||||||
|
|
||||||
describe('#getRegisteredWithdrawals', () => {
|
describe('#getRegisteredWithdrawals', () => {
|
||||||
it('should work', async () => {
|
it('should work', async () => {
|
||||||
|
for (let i = 0; i < 2 ** CHUNK_TREE_HEIGHT; i++) {
|
||||||
|
notes[i] = {
|
||||||
|
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], tornadoTrees, tornadoProxy)
|
||||||
|
}
|
||||||
|
|
||||||
const abi = new ethers.utils.AbiCoder()
|
const abi = new ethers.utils.AbiCoder()
|
||||||
const count = await tornadoTrees.withdrawalsLength()
|
const count = await tornadoTrees.withdrawalsLength()
|
||||||
const _withdrawals = await tornadoTrees.getRegisteredWithdrawals()
|
const _withdrawals = await tornadoTrees.getRegisteredWithdrawals()
|
||||||
expect(count).to.be.equal(notes.length)
|
expect(count).to.be.equal(notes.length * 2)
|
||||||
_withdrawals.forEach((hash, i) => {
|
_withdrawals.forEach((hash, i) => {
|
||||||
const encodedData = abi.encode(
|
if (i < notes.length) {
|
||||||
['address', 'bytes32', 'uint256'],
|
expect(hash).to.be.equal('0x0000000000000000000000000000000000000000000000000000000000000000')
|
||||||
[notes[i].instance, toFixedHex(notes[i].nullifierHash), notes[i].withdrawalBlock],
|
} else {
|
||||||
)
|
const index = i - notes.length
|
||||||
const leaf = ethers.utils.keccak256(encodedData)
|
const encodedData = abi.encode(
|
||||||
|
['address', 'bytes32', 'uint256'],
|
||||||
|
[notes[index].instance, toFixedHex(notes[index].nullifierHash), notes[index].withdrawalBlock],
|
||||||
|
)
|
||||||
|
const leaf = ethers.utils.keccak256(encodedData)
|
||||||
|
|
||||||
expect(leaf).to.be.equal(hash)
|
expect(leaf).to.be.equal(hash)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user