new migration

This commit is contained in:
poma 2021-02-05 02:13:34 +03:00
parent b59fbcf169
commit 89abbf77f5
No known key found for this signature in database
GPG Key ID: BA20CB01FE165657
2 changed files with 26 additions and 78 deletions

View File

@ -28,4 +28,3 @@ jobs:
format: markdown format: markdown
to: ${{ secrets.TELEGRAM_CHAT_ID }} to: ${{ secrets.TELEGRAM_CHAT_ID }}
token: ${{ secrets.TELEGRAM_BOT_TOKEN }} token: ${{ secrets.TELEGRAM_BOT_TOKEN }}

View File

@ -17,6 +17,7 @@ contract TornadoTrees is EnsResolve {
bytes32 public previousWithdrawalRoot; bytes32 public previousWithdrawalRoot;
address public tornadoProxy; address public tornadoProxy;
IVerifier public treeUpdateVerifier; IVerifier public treeUpdateVerifier;
ITornadoTreesV1 public immutable tornadoTreesV1;
// make sure CHUNK_TREE_HEIGHT has the same value in BatchTreeUpdate.circom // make sure CHUNK_TREE_HEIGHT has the same value in BatchTreeUpdate.circom
uint256 public constant CHUNK_TREE_HEIGHT = 2; uint256 public constant CHUNK_TREE_HEIGHT = 2;
@ -28,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;
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;
bool public initialized;
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);
@ -61,11 +62,6 @@ contract TornadoTrees is EnsResolve {
_; _;
} }
modifier onlyInitialized() {
require(initialized, "The contract is in the process of the migration");
_;
}
constructor( constructor(
address _governance, address _governance,
address _tornadoProxy, address _tornadoProxy,
@ -75,6 +71,7 @@ contract TornadoTrees is EnsResolve {
governance = _governance; governance = _governance;
tornadoProxy = _tornadoProxy; tornadoProxy = _tornadoProxy;
treeUpdateVerifier = _treeUpdateVerifier; treeUpdateVerifier = _treeUpdateVerifier;
tornadoTreesV1 = _tornadoTreesV1;
depositRoot = _tornadoTreesV1.depositRoot(); depositRoot = _tornadoTreesV1.depositRoot();
withdrawalRoot = _tornadoTreesV1.withdrawalRoot(); withdrawalRoot = _tornadoTreesV1.withdrawalRoot();
@ -82,86 +79,26 @@ 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;
lastV1Deposit = 1; // 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;
lastV1Withdrawal = 1; // todo
uint256 i = depositLeaf;
while (true) {
(bool success, bytes memory data) = address(_tornadoTreesV1).staticcall{ gas: 3000 }( // todo define more specise gas value.
abi.encodeWithSignature("deposits(uint256)", i)
);
if (!success) {
break;
}
bytes32 deposit = abi.decode(data, (bytes32));
deposits[i] = deposit;
i++;
}
depositsLength = depositLeaf + i;
i = withdrawalLeaf;
while (true) {
(bool success, bytes memory data) = address(_tornadoTreesV1).staticcall{ gas: 3000 }(
abi.encodeWithSignature("withdrawals(uint256)", i)
);
if (!success) {
break;
}
bytes32 withdrawal = abi.decode(data, (bytes32));
withdrawals[i] = withdrawal;
i++;
}
withdrawalsLength = withdrawalLeaf + i;
} }
function registerDeposit(address _instance, bytes32 _commitment) external onlyTornadoProxy onlyInitialized { 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 - 1);
} }
function registerWithdrawal(address _instance, bytes32 _nullifierHash) external onlyTornadoProxy onlyInitialized { 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 - 1);
} }
function migrate(TreeLeaf[] calldata _depositEvents, TreeLeaf[] calldata _withdrawalEvents) external {
require(!initialized, "Already migrated");
uint256 _lastProcessedDepositLeaf = lastProcessedDepositLeaf;
uint256 _depositLength = depositsLength;
for (uint256 i = 0; i < _depositLength - _lastProcessedDepositLeaf; i++) {
bytes32 leafHash = keccak256(abi.encode(_depositEvents[i].instance, _depositEvents[i].hash, _depositEvents[i].block));
require(leafHash == deposits[_lastProcessedDepositLeaf + i], "Incorrect deposit");
emit DepositData(
_depositEvents[i].instance,
_depositEvents[i].hash,
_depositEvents[i].block,
_lastProcessedDepositLeaf + i
);
}
uint256 _withdrawalLength = withdrawalsLength;
uint256 _lastProcessedWithdrawalLeaf = lastProcessedWithdrawalLeaf;
for (uint256 i = 0; i < _withdrawalLength - _lastProcessedWithdrawalLeaf; i++) {
bytes32 leafHash = keccak256(
abi.encode(_withdrawalEvents[i].instance, _withdrawalEvents[i].hash, _withdrawalEvents[i].block)
);
require(leafHash == withdrawals[_lastProcessedWithdrawalLeaf + i], "Incorrect deposit");
emit DepositData(
_withdrawalEvents[i].instance,
_withdrawalEvents[i].hash,
_withdrawalEvents[i].block,
_lastProcessedWithdrawalLeaf + i
);
}
initialized = true;
}
function updateDepositTree( function updateDepositTree(
bytes calldata _proof, bytes calldata _proof,
bytes32 _argsHash, bytes32 _argsHash,
@ -169,7 +106,7 @@ contract TornadoTrees is EnsResolve {
bytes32 _newRoot, bytes32 _newRoot,
uint32 _pathIndices, uint32 _pathIndices,
TreeLeaf[CHUNK_SIZE] calldata _events TreeLeaf[CHUNK_SIZE] calldata _events
) public onlyInitialized { ) public {
uint256 offset = lastProcessedDepositLeaf; uint256 offset = lastProcessedDepositLeaf;
require(_newRoot != previousDepositRoot, "Outdated deposit root"); require(_newRoot != previousDepositRoot, "Outdated deposit root");
require(_currentRoot == depositRoot, "Proposed deposit root is invalid"); require(_currentRoot == depositRoot, "Proposed deposit root is invalid");
@ -181,16 +118,22 @@ 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));
require(leafHash == deposits[offset + i], "Incorrect deposit"); bytes32 deposit = offset + i > _lastV1Deposit ? deposits[offset + i] : tornadoTreesV1.deposits(offset + i);
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)
} }
delete deposits[offset + i]; if (offset + i > _lastV1Deposit) {
delete deposits[offset + i];
} else {
emit DepositData(instance, hash, blockNumber, offset + i);
}
} }
uint256 argsHash = uint256(sha256(data)) % SNARK_FIELD; uint256 argsHash = uint256(sha256(data)) % SNARK_FIELD;
@ -209,7 +152,7 @@ contract TornadoTrees is EnsResolve {
bytes32 _newRoot, bytes32 _newRoot,
uint256 _pathIndices, uint256 _pathIndices,
TreeLeaf[CHUNK_SIZE] calldata _events TreeLeaf[CHUNK_SIZE] calldata _events
) public onlyInitialized { ) public {
uint256 offset = lastProcessedWithdrawalLeaf; uint256 offset = lastProcessedWithdrawalLeaf;
require(_newRoot != previousWithdrawalRoot, "Outdated withdrawal root"); require(_newRoot != previousWithdrawalRoot, "Outdated withdrawal root");
require(_currentRoot == withdrawalRoot, "Proposed withdrawal root is invalid"); require(_currentRoot == withdrawalRoot, "Proposed withdrawal root is invalid");
@ -222,17 +165,23 @@ 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));
require(leafHash == withdrawals[offset + i], "Incorrect withdrawal"); bytes32 withdrawal = offset + i > _lastV1Withdrawal ? withdrawals[offset + i] : tornadoTreesV1.withdrawals(offset + i);
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 {
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)
} }
delete withdrawals[offset + i]; if (offset + i > _lastV1Withdrawal) {
delete withdrawals[offset + i];
} else {
emit WithdrawalData(instance, hash, blockNumber, offset + i);
}
} }
uint256 argsHash = uint256(sha256(data)) % SNARK_FIELD; uint256 argsHash = uint256(sha256(data)) % SNARK_FIELD;