mirror of
https://github.com/tornadocash/tornado-nova
synced 2024-02-02 14:53:56 +01:00
refactor
This commit is contained in:
parent
4fded51106
commit
1dd9cf70d9
@ -16,9 +16,9 @@ pragma experimental ABIEncoderV2;
|
||||
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; // todo: maybe remove?
|
||||
|
||||
interface IVerifier {
|
||||
function verifyProof(bytes memory _proof, uint256[9] memory _input) external returns (bool);
|
||||
function verifyProof(bytes memory _proof, uint256[9] memory _input) external view returns (bool);
|
||||
|
||||
function verifyProof(bytes memory _proof, uint256[23] memory _input) external returns (bool);
|
||||
function verifyProof(bytes memory _proof, uint256[23] memory _input) external view returns (bool);
|
||||
}
|
||||
|
||||
contract TornadoPool is ReentrancyGuard {
|
||||
@ -38,15 +38,13 @@ contract TornadoPool is ReentrancyGuard {
|
||||
bytes encryptedOutput2;
|
||||
}
|
||||
|
||||
// todo: event Transaction();
|
||||
event NewCommitment(bytes32 commitment, uint256 index, bytes encryptedOutput);
|
||||
event NewNullifier(bytes32 nullifier);
|
||||
event Withdraw(bytes32 indexed nullifier); // todo emit it on withdraw so we can easily find the withdraw tx for user on UI
|
||||
|
||||
/**
|
||||
@dev The constructor
|
||||
@param _verifier2 the address of SNARK verifier for this contract
|
||||
@param _verifier16 the address of SNARK verifier for this contract
|
||||
@param _verifier2 the address of SNARK verifier for 2 inputs
|
||||
@param _verifier16 the address of SNARK verifier for 16 inputs
|
||||
*/
|
||||
constructor(
|
||||
IVerifier _verifier2,
|
||||
@ -74,59 +72,10 @@ contract TornadoPool is ReentrancyGuard {
|
||||
require(!isSpent(_inputNullifiers[i]), "Input is already spent");
|
||||
}
|
||||
require(uint256(_extDataHash) == uint256(keccak256(abi.encode(_extData))) % FIELD_SIZE, "Incorrect external data hash");
|
||||
if (_inputNullifiers.length == 2) {
|
||||
require(
|
||||
verifier2.verifyProof(
|
||||
_proof,
|
||||
[
|
||||
uint256(_root),
|
||||
uint256(_newRoot),
|
||||
uint256(_inputNullifiers[0]),
|
||||
uint256(_inputNullifiers[1]),
|
||||
uint256(_outputCommitments[0]),
|
||||
uint256(_outputCommitments[1]),
|
||||
_extAmount,
|
||||
_fee,
|
||||
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");
|
||||
}
|
||||
require(
|
||||
verifyProof(_proof, _root, _newRoot, _inputNullifiers, _outputCommitments, _extAmount, _fee, _extDataHash),
|
||||
"Invalid transaction proof"
|
||||
);
|
||||
|
||||
currentRoot = _newRoot;
|
||||
for (uint256 i = 0; i < _inputNullifiers.length; i++) {
|
||||
@ -172,4 +121,65 @@ contract TornadoPool is ReentrancyGuard {
|
||||
function isSpent(bytes32 _nullifierHash) public view returns (bool) {
|
||||
return nullifierHashes[_nullifierHash];
|
||||
}
|
||||
|
||||
function verifyProof(
|
||||
bytes memory _proof,
|
||||
bytes32 _root,
|
||||
bytes32 _newRoot,
|
||||
bytes32[] memory _inputNullifiers,
|
||||
bytes32[2] memory _outputCommitments,
|
||||
uint256 _extAmount,
|
||||
uint256 _fee,
|
||||
bytes32 _extDataHash
|
||||
) public view returns (bool) {
|
||||
if (_inputNullifiers.length == 2) {
|
||||
return
|
||||
verifier2.verifyProof(
|
||||
_proof,
|
||||
[
|
||||
uint256(_root),
|
||||
uint256(_newRoot),
|
||||
uint256(_inputNullifiers[0]),
|
||||
uint256(_inputNullifiers[1]),
|
||||
uint256(_outputCommitments[0]),
|
||||
uint256(_outputCommitments[1]),
|
||||
_extAmount,
|
||||
_fee,
|
||||
uint256(_extDataHash)
|
||||
]
|
||||
);
|
||||
} else if (_inputNullifiers.length == 16) {
|
||||
return
|
||||
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)
|
||||
]
|
||||
);
|
||||
} else {
|
||||
revert("unsupported input count");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
13
src/index.js
13
src/index.js
@ -9,7 +9,6 @@ const { prove } = require('./prover')
|
||||
const MERKLE_TREE_HEIGHT = 5
|
||||
|
||||
async function buildMerkleTree({ tornadoPool }) {
|
||||
console.log('Getting contract state...')
|
||||
const filter = tornadoPool.filters.NewCommitment()
|
||||
const events = await tornadoPool.queryFilter(filter, 0)
|
||||
|
||||
@ -48,8 +47,6 @@ async function getProof({ inputs, outputs, tree, extAmount, fee, recipient, rela
|
||||
const outputIndex = tree.elements().length - 1
|
||||
const outputPath = tree.path(outputIndex).pathElements
|
||||
|
||||
//encrypt(encryptedPublicKey, { data }, 'x25519-xsalsa20-poly1305')
|
||||
|
||||
const extData = {
|
||||
recipient: toFixedHex(recipient, 20),
|
||||
relayer: toFixedHex(relayer, 20),
|
||||
@ -82,9 +79,6 @@ async function getProof({ inputs, outputs, tree, extAmount, fee, recipient, rela
|
||||
outPathElements: outputPath.slice(Math.log2(outputs.length)),
|
||||
}
|
||||
|
||||
//console.log('SNARK input', input)
|
||||
|
||||
console.log('Generating SNARK proof...')
|
||||
const proof = await prove(input, `./artifacts/circuits/transaction${inputs.length}`)
|
||||
|
||||
const args = [
|
||||
@ -119,7 +113,8 @@ async function transaction({ tornadoPool, inputs = [], outputs = [], fee = 0, re
|
||||
let extAmount = BigNumber.from(fee)
|
||||
.add(outputs.reduce((sum, x) => sum.add(x.amount), BigNumber.from(0)))
|
||||
.sub(inputs.reduce((sum, x) => sum.add(x.amount), BigNumber.from(0)))
|
||||
const amount = extAmount > 0 ? extAmount : 0
|
||||
|
||||
const amount = extAmount > 0 ? extAmount : 0 // extAmount will be positive for a deposit, zero for a transact and negative for withdraw
|
||||
if (extAmount < 0) {
|
||||
extAmount = FIELD_SIZE.add(extAmount)
|
||||
}
|
||||
@ -134,12 +129,12 @@ async function transaction({ tornadoPool, inputs = [], outputs = [], fee = 0, re
|
||||
relayer,
|
||||
})
|
||||
|
||||
console.log('Sending transaction...')
|
||||
const receipt = await tornadoPool.transaction(proof, ...args, {
|
||||
value: amount,
|
||||
gasLimit: 1e6,
|
||||
})
|
||||
console.log(`Receipt ${receipt.hash}`)
|
||||
const { gasUsed } = await receipt.wait()
|
||||
// console.log(`Gas Used ${gasUsed}`)
|
||||
}
|
||||
|
||||
module.exports = { transaction }
|
||||
|
@ -4,7 +4,7 @@ const { randomBN, poseidonHash, toBuffer } = require('./utils')
|
||||
const Keypair = require('./keypair')
|
||||
|
||||
class Utxo {
|
||||
/**
|
||||
/** Initialize a new UTXO - unspent transaction output or input. Note, a full TX consists of 2/16 inputs and 2 outputs
|
||||
*
|
||||
* @param {BigNumber | BigInt | number | string} amount UTXO amount
|
||||
* @param {BigNumber | BigInt | number | string} blinding Blinding factor
|
||||
|
@ -68,7 +68,7 @@ describe('TornadoPool', () => {
|
||||
const bobReceiveUtxo = Utxo.decrypt(bobKeypair, events[0].args.encryptedOutput, events[0].args.index)
|
||||
expect(bobReceiveUtxo.amount).to.be.equal(bobSendAmount)
|
||||
|
||||
// Bob withdraws part of his funds from the shielded pool
|
||||
// Bob withdraws a part of his funds from the shielded pool
|
||||
const bobWithdrawAmount = 2e6
|
||||
const bobEthAddress = '0xDeaD00000000000000000000000000000000BEEf'
|
||||
const bobChangeUtxo = new Utxo({ amount: bobSendAmount - bobWithdrawAmount, keypair: bobKeypair })
|
||||
|
Loading…
Reference in New Issue
Block a user