test merge tx

This commit is contained in:
poma 2021-06-15 14:47:54 +03:00
parent 960b6adb30
commit a210e2a2cc
No known key found for this signature in database
GPG Key ID: BA20CB01FE165657
3 changed files with 81 additions and 21 deletions

View File

@ -57,7 +57,7 @@ contract TornadoPool is ReentrancyGuard {
bytes calldata _proof, bytes calldata _proof,
bytes32 _root, bytes32 _root,
bytes32 _newRoot, bytes32 _newRoot,
bytes32[2] calldata _inputNullifiers, bytes32[] calldata _inputNullifiers,
bytes32[2] calldata _outputCommitments, bytes32[2] calldata _outputCommitments,
uint256 _extAmount, uint256 _extAmount,
uint256 _fee, uint256 _fee,
@ -67,24 +67,56 @@ contract TornadoPool is ReentrancyGuard {
external payable nonReentrant external payable nonReentrant
{ {
require(currentRoot == _root, "Invalid merkle root"); require(currentRoot == _root, "Invalid merkle root");
require(!isSpent(_inputNullifiers[0]), "Input 0 is already spent"); for(uint256 i = 0; i < _inputNullifiers.length; i++) {
require(!isSpent(_inputNullifiers[1]), "Input 1 is already spent"); require(!isSpent(_inputNullifiers[i]), "Input is already spent");
}
require(uint256(_extDataHash) == uint256(keccak256(abi.encode(_extData))) % FIELD_SIZE, "Incorrect external data hash"); require(uint256(_extDataHash) == uint256(keccak256(abi.encode(_extData))) % FIELD_SIZE, "Incorrect external data hash");
require(verifier2.verifyProof(_proof, [ if (_inputNullifiers.length == 2) {
uint256(_root), require(verifier2.verifyProof(_proof, [
uint256(_newRoot), uint256(_root),
uint256(_inputNullifiers[0]), uint256(_newRoot),
uint256(_inputNullifiers[1]), uint256(_inputNullifiers[0]),
uint256(_outputCommitments[0]), uint256(_inputNullifiers[1]),
uint256(_outputCommitments[1]), uint256(_outputCommitments[0]),
_extAmount, uint256(_outputCommitments[1]),
_fee, _extAmount,
uint256(_extDataHash) _fee,
]), "Invalid transaction proof"); uint256(_extDataHash)
]), "Invalid transaction proof");
} else if (_inputNullifiers.length == 16) {
require(verifier16.verifyProof(_proof, [
uint256(_root),
uint256(_newRoot),
uint256(_inputNullifiers[0]),
uint256(_inputNullifiers[1]),
uint256(_inputNullifiers[2]),
uint256(_inputNullifiers[3]),
uint256(_inputNullifiers[4]),
uint256(_inputNullifiers[5]),
uint256(_inputNullifiers[6]),
uint256(_inputNullifiers[7]),
uint256(_inputNullifiers[8]),
uint256(_inputNullifiers[9]),
uint256(_inputNullifiers[10]),
uint256(_inputNullifiers[11]),
uint256(_inputNullifiers[12]),
uint256(_inputNullifiers[13]),
uint256(_inputNullifiers[14]),
uint256(_inputNullifiers[15]),
uint256(_outputCommitments[0]),
uint256(_outputCommitments[1]),
_extAmount,
_fee,
uint256(_extDataHash)
]), "Invalid transaction proof");
} else {
revert("unsupported input count");
}
currentRoot = _newRoot; currentRoot = _newRoot;
nullifierHashes[_inputNullifiers[0]] = true; for(uint256 i = 0; i < _inputNullifiers.length; i++) {
nullifierHashes[_inputNullifiers[1]] = true; nullifierHashes[_inputNullifiers[i]] = true;
}
int256 extAmount = calculateExternalAmount(_extAmount); int256 extAmount = calculateExternalAmount(_extAmount);
if (extAmount > 0) { if (extAmount > 0) {
@ -101,9 +133,9 @@ contract TornadoPool is ReentrancyGuard {
// todo enforce currentCommitmentIndex value in snark // todo enforce currentCommitmentIndex value in snark
emit NewCommitment(_outputCommitments[0], currentCommitmentIndex++, _extData.encryptedOutput1); emit NewCommitment(_outputCommitments[0], currentCommitmentIndex++, _extData.encryptedOutput1);
emit NewCommitment(_outputCommitments[1], currentCommitmentIndex++, _extData.encryptedOutput2); emit NewCommitment(_outputCommitments[1], currentCommitmentIndex++, _extData.encryptedOutput2);
emit NewNullifier(_inputNullifiers[0]); for(uint256 i = 0; i < _inputNullifiers.length; i++) {
emit NewNullifier(_inputNullifiers[1]); emit NewNullifier(_inputNullifiers[i]);
// emit Transaction(); }
} }
function calculateExternalAmount(uint256 _extAmount) public pure returns(int256) { function calculateExternalAmount(uint256 _extAmount) public pure returns(int256) {

View File

@ -126,6 +126,30 @@ async function deposit({ tornadoPool }) {
return outputs[0] return outputs[0]
} }
async function merge({ tornadoPool }) {
const amount = 1e6
const inputs = new Array(16).fill(0).map(_ => new Utxo())
const outputs = [new Utxo({ amount }), new Utxo()]
const { proof, args } = await getProof({
inputs,
outputs,
tree: await buildMerkleTree({ tornadoPool }),
extAmount: amount,
fee: 0,
recipient: 0,
relayer: 0,
})
console.log('Sending merge transaction...', proof, args)
const receipt = await tornadoPool.transaction(proof, ...args, {
value: amount,
gasLimit: 1e6,
})
console.log(`Receipt ${receipt.hash}`)
return outputs[0]
}
async function transact({ tornadoPool, utxo }) { async function transact({ tornadoPool, utxo }) {
const inputs = [utxo, new Utxo()] const inputs = [utxo, new Utxo()]
const outputs = [ const outputs = [
@ -168,4 +192,4 @@ async function withdraw({ tornadoPool, utxo, recipient }) {
console.log(`Receipt ${receipt.hash}`) console.log(`Receipt ${receipt.hash}`)
} }
module.exports = { deposit, withdraw, transact } module.exports = { deposit, withdraw, transact, merge }

View File

@ -7,7 +7,7 @@ const { poseidonHash2, toFixedHex, takeSnapshot, revertSnapshot } = require('../
const MERKLE_TREE_HEIGHT = 5 const MERKLE_TREE_HEIGHT = 5
const MerkleTree = require('fixed-merkle-tree') const MerkleTree = require('fixed-merkle-tree')
const { deposit, transact, withdraw } = require('../src/index') const { deposit, transact, withdraw, merge } = require('../src/index')
describe('TornadoPool', () => { describe('TornadoPool', () => {
let snapshotId, tornadoPool let snapshotId, tornadoPool
@ -42,6 +42,10 @@ describe('TornadoPool', () => {
expect(bal).to.be.gt(0) expect(bal).to.be.gt(0)
}) })
it('should work with 16 inputs', async function () {
const utxo1 = await merge({tornadoPool})
})
afterEach(async () => { afterEach(async () => {
await revertSnapshot(snapshotId) await revertSnapshot(snapshotId)
snapshotId = await takeSnapshot() snapshotId = await takeSnapshot()