mirror of
https://github.com/tornadocash/tornado-core.git
synced 2024-11-22 09:47:13 +01:00
typed withdraw inputs
This commit is contained in:
parent
e9c2055bb4
commit
74913e67b2
31
cli.js
31
cli.js
@ -113,11 +113,19 @@ async function withdrawErc20(note, receiver, relayer) {
|
|||||||
console.log('Generating SNARK proof')
|
console.log('Generating SNARK proof')
|
||||||
console.time('Proof time')
|
console.time('Proof time')
|
||||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||||
const { proof, publicSignals } = websnarkUtils.toSolidityInput(proofData)
|
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||||
console.timeEnd('Proof time')
|
console.timeEnd('Proof time')
|
||||||
|
|
||||||
console.log('Submitting withdraw transaction')
|
console.log('Submitting withdraw transaction')
|
||||||
await erc20mixer.methods.withdraw(proof, publicSignals).send({ from: (await web3.eth.getAccounts())[0], gas: 1e6 })
|
const args = [
|
||||||
|
toHex(input.root),
|
||||||
|
toHex(input.nullifierHash),
|
||||||
|
toHex(input.receiver, 20),
|
||||||
|
toHex(input.relayer, 20),
|
||||||
|
toHex(input.fee),
|
||||||
|
toHex(input.refund)
|
||||||
|
]
|
||||||
|
await erc20mixer.methods.withdraw(proof, ...args).send({ from: (await web3.eth.getAccounts())[0], gas: 1e6 })
|
||||||
console.log('Done')
|
console.log('Done')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,6 +146,13 @@ async function getBalanceErc20(receiver, relayer) {
|
|||||||
console.log('Relayer token Balance is ', web3.utils.fromWei(tokenBalanceRelayer.toString()))
|
console.log('Relayer token Balance is ', web3.utils.fromWei(tokenBalanceRelayer.toString()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toHex(number, length = 32) {
|
||||||
|
let str = bigInt(number).toString(16)
|
||||||
|
while (str.length < length * 2) str = '0' + str
|
||||||
|
str = '0x' + str
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
async function withdraw(note, receiver) {
|
async function withdraw(note, receiver) {
|
||||||
// Decode hex string and restore the deposit object
|
// Decode hex string and restore the deposit object
|
||||||
let buf = Buffer.from(note.slice(2), 'hex')
|
let buf = Buffer.from(note.slice(2), 'hex')
|
||||||
@ -188,11 +203,19 @@ async function withdraw(note, receiver) {
|
|||||||
console.log('Generating SNARK proof')
|
console.log('Generating SNARK proof')
|
||||||
console.time('Proof time')
|
console.time('Proof time')
|
||||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||||
const { proof, publicSignals } = websnarkUtils.toSolidityInput(proofData)
|
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||||
console.timeEnd('Proof time')
|
console.timeEnd('Proof time')
|
||||||
|
|
||||||
console.log('Submitting withdraw transaction')
|
console.log('Submitting withdraw transaction')
|
||||||
await mixer.methods.withdraw(proof, publicSignals).send({ from: (await web3.eth.getAccounts())[0], gas: 1e6 })
|
const args = [
|
||||||
|
toHex(input.root),
|
||||||
|
toHex(input.nullifierHash),
|
||||||
|
toHex(input.receiver, 20),
|
||||||
|
toHex(input.relayer, 20),
|
||||||
|
toHex(input.fee),
|
||||||
|
toHex(input.refund)
|
||||||
|
]
|
||||||
|
await mixer.methods.withdraw(proof, ...args).send({ from: (await web3.eth.getAccounts())[0], gas: 1e6 })
|
||||||
console.log('Done')
|
console.log('Done')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ pragma solidity ^0.5.8;
|
|||||||
import "./MerkleTreeWithHistory.sol";
|
import "./MerkleTreeWithHistory.sol";
|
||||||
|
|
||||||
contract IVerifier {
|
contract IVerifier {
|
||||||
function verifyProof(uint256[8] memory _proof, uint256[6] memory _input) public returns(bool);
|
function verifyProof(bytes memory _proof, uint256[6] memory _input) public returns(bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
contract Mixer is MerkleTreeWithHistory {
|
contract Mixer is MerkleTreeWithHistory {
|
||||||
@ -64,6 +64,7 @@ contract Mixer is MerkleTreeWithHistory {
|
|||||||
function deposit(uint256 _commitment) public payable {
|
function deposit(uint256 _commitment) public payable {
|
||||||
require(!isDepositsDisabled, "deposits are disabled");
|
require(!isDepositsDisabled, "deposits are disabled");
|
||||||
require(!commitments[_commitment], "The commitment has been submitted");
|
require(!commitments[_commitment], "The commitment has been submitted");
|
||||||
|
|
||||||
uint32 insertedIndex = _insert(_commitment);
|
uint32 insertedIndex = _insert(_commitment);
|
||||||
commitments[_commitment] = true;
|
commitments[_commitment] = true;
|
||||||
_processDeposit();
|
_processDeposit();
|
||||||
@ -82,21 +83,15 @@ contract Mixer is MerkleTreeWithHistory {
|
|||||||
- the receiver of funds
|
- the receiver of funds
|
||||||
- optional fee that goes to the transaction sender (usually a relay)
|
- optional fee that goes to the transaction sender (usually a relay)
|
||||||
*/
|
*/
|
||||||
function withdraw(uint256[8] memory _proof, uint256[6] memory _input) public payable {
|
function withdraw(bytes memory _proof, uint256 _root, uint256 _nullifierHash, address payable _receiver, address payable _relayer, uint256 _fee, uint256 _refund) public payable {
|
||||||
uint256 root = _input[0];
|
require(_fee <= denomination, "Fee exceeds transfer value");
|
||||||
uint256 nullifierHash = _input[1];
|
require(!nullifierHashes[_nullifierHash], "The note has been already spent");
|
||||||
address payable receiver = address(_input[2]);
|
require(isKnownRoot(_root), "Cannot find your merkle root"); // Make sure to use a recent one
|
||||||
address payable relayer = address(_input[3]);
|
require(verifier.verifyProof(_proof, [_root, _nullifierHash, uint256(_receiver), uint256(_relayer), _fee, _refund]), "Invalid withdraw proof");
|
||||||
uint256 fee = _input[4];
|
|
||||||
uint256 refund = _input[5];
|
|
||||||
require(fee <= denomination, "Fee exceeds transfer value");
|
|
||||||
require(!nullifierHashes[nullifierHash], "The note has been already spent");
|
|
||||||
|
|
||||||
require(isKnownRoot(root), "Cannot find your merkle root"); // Make sure to use a recent one
|
nullifierHashes[_nullifierHash] = true;
|
||||||
require(verifier.verifyProof(_proof, _input), "Invalid withdraw proof");
|
_processWithdraw(_receiver, _relayer, _fee, _refund);
|
||||||
nullifierHashes[nullifierHash] = true;
|
emit Withdrawal(_receiver, _nullifierHash, _relayer, _fee);
|
||||||
_processWithdraw(receiver, relayer, fee, refund);
|
|
||||||
emit Withdrawal(receiver, nullifierHash, relayer, fee);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @dev this function is defined in a child contract */
|
/** @dev this function is defined in a child contract */
|
||||||
|
@ -36,14 +36,14 @@
|
|||||||
"dotenv": "^8.0.0",
|
"dotenv": "^8.0.0",
|
||||||
"eslint": "^6.2.2",
|
"eslint": "^6.2.2",
|
||||||
"ganache-cli": "^6.4.5",
|
"ganache-cli": "^6.4.5",
|
||||||
"snarkjs": "git+https://github.com/peppersec/snarkjs.git#0e2f8ab28092ee6d922dc4d3ac7afc8ef5a25154",
|
"snarkjs": "git+https://github.com/peppersec/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5",
|
||||||
"truffle": "^5.0.27",
|
"truffle": "^5.0.27",
|
||||||
"truffle-artifactor": "^4.0.23",
|
"truffle-artifactor": "^4.0.23",
|
||||||
"truffle-contract": "^4.0.24",
|
"truffle-contract": "^4.0.24",
|
||||||
"truffle-hdwallet-provider": "^1.0.14",
|
"truffle-hdwallet-provider": "^1.0.14",
|
||||||
"web3": "^1.0.0-beta.55",
|
"web3": "^1.0.0-beta.55",
|
||||||
"web3-utils": "^1.0.0-beta.55",
|
"web3-utils": "^1.0.0-beta.55",
|
||||||
"websnark": "git+https://github.com/peppersec/websnark.git#966eafc47df639195c98374d3c366c32acd6f231"
|
"websnark": "git+https://github.com/peppersec/websnark.git#c254b5962287b788081be1047fa0041c2885b39f"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"truffle-flattener": "^1.4.0"
|
"truffle-flattener": "^1.4.0"
|
||||||
|
@ -43,6 +43,13 @@ function getRandomReceiver() {
|
|||||||
return receiver
|
return receiver
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toFixedHex(number, length = 32) {
|
||||||
|
let str = bigInt(number).toString(16)
|
||||||
|
while (str.length < length * 2) str = '0' + str
|
||||||
|
str = '0x' + str
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
contract('ERC20Mixer', accounts => {
|
contract('ERC20Mixer', accounts => {
|
||||||
let mixer
|
let mixer
|
||||||
let token
|
let token
|
||||||
@ -147,7 +154,7 @@ contract('ERC20Mixer', accounts => {
|
|||||||
|
|
||||||
|
|
||||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||||
const { proof, publicSignals } = websnarkUtils.toSolidityInput(proofData)
|
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||||
|
|
||||||
const balanceMixerBefore = await token.balanceOf(mixer.address)
|
const balanceMixerBefore = await token.balanceOf(mixer.address)
|
||||||
const balanceRelayerBefore = await token.balanceOf(relayer)
|
const balanceRelayerBefore = await token.balanceOf(relayer)
|
||||||
@ -161,7 +168,15 @@ contract('ERC20Mixer', accounts => {
|
|||||||
// Uncomment to measure gas usage
|
// Uncomment to measure gas usage
|
||||||
// gas = await mixer.withdraw.estimateGas(proof, publicSignals, { from: relayer, gasPrice: '0' })
|
// gas = await mixer.withdraw.estimateGas(proof, publicSignals, { from: relayer, gasPrice: '0' })
|
||||||
// console.log('withdraw gas:', gas)
|
// console.log('withdraw gas:', gas)
|
||||||
const { logs } = await mixer.withdraw(proof, publicSignals, { value: refund, from: relayer, gasPrice: '0' })
|
const args = [
|
||||||
|
toFixedHex(input.root),
|
||||||
|
toFixedHex(input.nullifierHash),
|
||||||
|
toFixedHex(input.receiver, 20),
|
||||||
|
toFixedHex(input.relayer, 20),
|
||||||
|
toFixedHex(input.fee),
|
||||||
|
toFixedHex(input.refund)
|
||||||
|
]
|
||||||
|
const { logs } = await mixer.withdraw(proof, ...args, { value: refund, from: relayer, gasPrice: '0' })
|
||||||
|
|
||||||
const balanceMixerAfter = await token.balanceOf(mixer.address)
|
const balanceMixerAfter = await token.balanceOf(mixer.address)
|
||||||
const balanceRelayerAfter = await token.balanceOf(relayer)
|
const balanceRelayerAfter = await token.balanceOf(relayer)
|
||||||
@ -215,13 +230,21 @@ contract('ERC20Mixer', accounts => {
|
|||||||
|
|
||||||
|
|
||||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||||
const { proof, publicSignals } = websnarkUtils.toSolidityInput(proofData)
|
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||||
|
|
||||||
let { reason } = await mixer.withdraw(proof, publicSignals, { value: 1, from: relayer, gasPrice: '0' }).should.be.rejected
|
const args = [
|
||||||
|
toFixedHex(input.root),
|
||||||
|
toFixedHex(input.nullifierHash),
|
||||||
|
toFixedHex(input.receiver, 20),
|
||||||
|
toFixedHex(input.relayer, 20),
|
||||||
|
toFixedHex(input.fee),
|
||||||
|
toFixedHex(input.refund)
|
||||||
|
]
|
||||||
|
let { reason } = await mixer.withdraw(proof, ...args, { value: 1, from: relayer, gasPrice: '0' }).should.be.rejected
|
||||||
reason.should.be.equal('Incorrect refund amount received by the contract')
|
reason.should.be.equal('Incorrect refund amount received by the contract')
|
||||||
|
|
||||||
|
|
||||||
;({ reason } = await mixer.withdraw(proof, publicSignals, { value: toBN(refund).mul(toBN(2)), from: relayer, gasPrice: '0' }).should.be.rejected)
|
;({ reason } = await mixer.withdraw(proof, ...args, { value: toBN(refund).mul(toBN(2)), from: relayer, gasPrice: '0' }).should.be.rejected)
|
||||||
reason.should.be.equal('Incorrect refund amount received by the contract')
|
reason.should.be.equal('Incorrect refund amount received by the contract')
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -274,7 +297,7 @@ contract('ERC20Mixer', accounts => {
|
|||||||
|
|
||||||
|
|
||||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||||
const { proof, publicSignals } = websnarkUtils.toSolidityInput(proofData)
|
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||||
|
|
||||||
const balanceMixerBefore = await usdtToken.balanceOf(mixer.address)
|
const balanceMixerBefore = await usdtToken.balanceOf(mixer.address)
|
||||||
const balanceRelayerBefore = await usdtToken.balanceOf(relayer)
|
const balanceRelayerBefore = await usdtToken.balanceOf(relayer)
|
||||||
@ -287,7 +310,15 @@ contract('ERC20Mixer', accounts => {
|
|||||||
// Uncomment to measure gas usage
|
// Uncomment to measure gas usage
|
||||||
// gas = await mixer.withdraw.estimateGas(proof, publicSignals, { from: relayer, gasPrice: '0' })
|
// gas = await mixer.withdraw.estimateGas(proof, publicSignals, { from: relayer, gasPrice: '0' })
|
||||||
// console.log('withdraw gas:', gas)
|
// console.log('withdraw gas:', gas)
|
||||||
const { logs } = await mixer.withdraw(proof, publicSignals, { value: refund, from: relayer, gasPrice: '0' })
|
const args = [
|
||||||
|
toFixedHex(input.root),
|
||||||
|
toFixedHex(input.nullifierHash),
|
||||||
|
toFixedHex(input.receiver, 20),
|
||||||
|
toFixedHex(input.relayer, 20),
|
||||||
|
toFixedHex(input.fee),
|
||||||
|
toFixedHex(input.refund)
|
||||||
|
]
|
||||||
|
const { logs } = await mixer.withdraw(proof, ...args, { value: refund, from: relayer, gasPrice: '0' })
|
||||||
|
|
||||||
const balanceMixerAfter = await usdtToken.balanceOf(mixer.address)
|
const balanceMixerAfter = await usdtToken.balanceOf(mixer.address)
|
||||||
const balanceRelayerAfter = await usdtToken.balanceOf(relayer)
|
const balanceRelayerAfter = await usdtToken.balanceOf(relayer)
|
||||||
@ -355,7 +386,7 @@ contract('ERC20Mixer', accounts => {
|
|||||||
|
|
||||||
|
|
||||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||||
const { proof, publicSignals } = websnarkUtils.toSolidityInput(proofData)
|
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||||
|
|
||||||
const balanceMixerBefore = await token.balanceOf(mixer.address)
|
const balanceMixerBefore = await token.balanceOf(mixer.address)
|
||||||
const balanceRelayerBefore = await token.balanceOf(relayer)
|
const balanceRelayerBefore = await token.balanceOf(relayer)
|
||||||
@ -368,7 +399,15 @@ contract('ERC20Mixer', accounts => {
|
|||||||
// Uncomment to measure gas usage
|
// Uncomment to measure gas usage
|
||||||
// gas = await mixer.withdraw.estimateGas(proof, publicSignals, { from: relayer, gasPrice: '0' })
|
// gas = await mixer.withdraw.estimateGas(proof, publicSignals, { from: relayer, gasPrice: '0' })
|
||||||
// console.log('withdraw gas:', gas)
|
// console.log('withdraw gas:', gas)
|
||||||
const { logs } = await mixer.withdraw(proof, publicSignals, { value: refund, from: relayer, gasPrice: '0' })
|
const args = [
|
||||||
|
toFixedHex(input.root),
|
||||||
|
toFixedHex(input.nullifierHash),
|
||||||
|
toFixedHex(input.receiver, 20),
|
||||||
|
toFixedHex(input.relayer, 20),
|
||||||
|
toFixedHex(input.fee),
|
||||||
|
toFixedHex(input.refund)
|
||||||
|
]
|
||||||
|
const { logs } = await mixer.withdraw(proof, ...args, { value: refund, from: relayer, gasPrice: '0' })
|
||||||
console.log('withdraw done')
|
console.log('withdraw done')
|
||||||
|
|
||||||
const balanceMixerAfter = await token.balanceOf(mixer.address)
|
const balanceMixerAfter = await token.balanceOf(mixer.address)
|
||||||
|
@ -57,6 +57,13 @@ function snarkVerify(proof) {
|
|||||||
return snarkjs['groth'].isValid(verification_key, proof, proof.publicSignals)
|
return snarkjs['groth'].isValid(verification_key, proof, proof.publicSignals)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toFixedHex(number, length = 32) {
|
||||||
|
let str = bigInt(number).toString(16)
|
||||||
|
while (str.length < length * 2) str = '0' + str
|
||||||
|
str = '0x' + str
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
contract('ETHMixer', accounts => {
|
contract('ETHMixer', accounts => {
|
||||||
let mixer
|
let mixer
|
||||||
const sender = accounts[0]
|
const sender = accounts[0]
|
||||||
@ -215,7 +222,7 @@ contract('ETHMixer', accounts => {
|
|||||||
|
|
||||||
|
|
||||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||||
const { proof, publicSignals } = websnarkUtils.toSolidityInput(proofData)
|
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||||
|
|
||||||
const balanceMixerBefore = await web3.eth.getBalance(mixer.address)
|
const balanceMixerBefore = await web3.eth.getBalance(mixer.address)
|
||||||
const balanceRelayerBefore = await web3.eth.getBalance(relayer)
|
const balanceRelayerBefore = await web3.eth.getBalance(relayer)
|
||||||
@ -227,7 +234,15 @@ contract('ETHMixer', accounts => {
|
|||||||
// Uncomment to measure gas usage
|
// Uncomment to measure gas usage
|
||||||
// gas = await mixer.withdraw.estimateGas(proof, publicSignals, { from: relayer, gasPrice: '0' })
|
// gas = await mixer.withdraw.estimateGas(proof, publicSignals, { from: relayer, gasPrice: '0' })
|
||||||
// console.log('withdraw gas:', gas)
|
// console.log('withdraw gas:', gas)
|
||||||
const { logs } = await mixer.withdraw(proof, publicSignals, { from: relayer, gasPrice: '0' })
|
const args = [
|
||||||
|
toFixedHex(input.root),
|
||||||
|
toFixedHex(input.nullifierHash),
|
||||||
|
toFixedHex(input.receiver, 20),
|
||||||
|
toFixedHex(input.relayer, 20),
|
||||||
|
toFixedHex(input.fee),
|
||||||
|
toFixedHex(input.refund)
|
||||||
|
]
|
||||||
|
const { logs } = await mixer.withdraw(proof, ...args, { from: relayer, gasPrice: '0' })
|
||||||
|
|
||||||
const balanceMixerAfter = await web3.eth.getBalance(mixer.address)
|
const balanceMixerAfter = await web3.eth.getBalance(mixer.address)
|
||||||
const balanceRelayerAfter = await web3.eth.getBalance(relayer)
|
const balanceRelayerAfter = await web3.eth.getBalance(relayer)
|
||||||
@ -268,9 +283,17 @@ contract('ETHMixer', accounts => {
|
|||||||
pathIndices: path_index,
|
pathIndices: path_index,
|
||||||
})
|
})
|
||||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||||
const { proof, publicSignals } = websnarkUtils.toSolidityInput(proofData)
|
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||||
await mixer.withdraw(proof, publicSignals, { from: relayer }).should.be.fulfilled
|
const args = [
|
||||||
const error = await mixer.withdraw(proof, publicSignals, { from: relayer }).should.be.rejected
|
toFixedHex(input.root),
|
||||||
|
toFixedHex(input.nullifierHash),
|
||||||
|
toFixedHex(input.receiver, 20),
|
||||||
|
toFixedHex(input.relayer, 20),
|
||||||
|
toFixedHex(input.fee),
|
||||||
|
toFixedHex(input.refund)
|
||||||
|
]
|
||||||
|
await mixer.withdraw(proof, ...args, { from: relayer }).should.be.fulfilled
|
||||||
|
const error = await mixer.withdraw(proof, ...args, { from: relayer }).should.be.rejected
|
||||||
error.reason.should.be.equal('The note has been already spent')
|
error.reason.should.be.equal('The note has been already spent')
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -294,9 +317,16 @@ contract('ETHMixer', accounts => {
|
|||||||
pathIndices: path_index,
|
pathIndices: path_index,
|
||||||
})
|
})
|
||||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||||
const { proof, publicSignals } = websnarkUtils.toSolidityInput(proofData)
|
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||||
publicSignals[1] ='0x' + toBN(publicSignals[1]).add(toBN('21888242871839275222246405745257275088548364400416034343698204186575808495617')).toString('hex')
|
const args = [
|
||||||
const error = await mixer.withdraw(proof, publicSignals, { from: relayer }).should.be.rejected
|
toFixedHex(input.root),
|
||||||
|
toFixedHex(toBN(input.nullifierHash).add(toBN('21888242871839275222246405745257275088548364400416034343698204186575808495617'))),
|
||||||
|
toFixedHex(input.receiver, 20),
|
||||||
|
toFixedHex(input.relayer, 20),
|
||||||
|
toFixedHex(input.fee),
|
||||||
|
toFixedHex(input.refund)
|
||||||
|
]
|
||||||
|
const error = await mixer.withdraw(proof, ...args, { from: relayer }).should.be.rejected
|
||||||
error.reason.should.be.equal('verifier-gte-snark-scalar-field')
|
error.reason.should.be.equal('verifier-gte-snark-scalar-field')
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -321,8 +351,16 @@ contract('ETHMixer', accounts => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||||
const { proof, publicSignals } = websnarkUtils.toSolidityInput(proofData)
|
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||||
const error = await mixer.withdraw(proof, publicSignals, { from: relayer }).should.be.rejected
|
const args = [
|
||||||
|
toFixedHex(input.root),
|
||||||
|
toFixedHex(input.nullifierHash),
|
||||||
|
toFixedHex(input.receiver, 20),
|
||||||
|
toFixedHex(input.relayer, 20),
|
||||||
|
toFixedHex(input.fee),
|
||||||
|
toFixedHex(input.refund)
|
||||||
|
]
|
||||||
|
const error = await mixer.withdraw(proof, ...args, { from: relayer }).should.be.rejected
|
||||||
error.reason.should.be.equal('Fee exceeds transfer value')
|
error.reason.should.be.equal('Fee exceeds transfer value')
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -346,12 +384,18 @@ contract('ETHMixer', accounts => {
|
|||||||
pathIndices: path_index,
|
pathIndices: path_index,
|
||||||
})
|
})
|
||||||
|
|
||||||
const dummyRoot = randomHex(32)
|
|
||||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||||
const { proof, publicSignals } = websnarkUtils.toSolidityInput(proofData)
|
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||||
publicSignals[0] = dummyRoot
|
|
||||||
|
|
||||||
const error = await mixer.withdraw(proof, publicSignals, { from: relayer }).should.be.rejected
|
const args = [
|
||||||
|
toFixedHex(randomHex(32)),
|
||||||
|
toFixedHex(input.nullifierHash),
|
||||||
|
toFixedHex(input.receiver, 20),
|
||||||
|
toFixedHex(input.relayer, 20),
|
||||||
|
toFixedHex(input.fee),
|
||||||
|
toFixedHex(input.refund)
|
||||||
|
]
|
||||||
|
const error = await mixer.withdraw(proof, ...args, { from: relayer }).should.be.rejected
|
||||||
error.reason.should.be.equal('Cannot find your merkle root')
|
error.reason.should.be.equal('Cannot find your merkle root')
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -375,36 +419,60 @@ contract('ETHMixer', accounts => {
|
|||||||
pathIndices: path_index,
|
pathIndices: path_index,
|
||||||
})
|
})
|
||||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||||
let { proof, publicSignals } = websnarkUtils.toSolidityInput(proofData)
|
let { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||||
const originalPublicSignals = publicSignals.slice()
|
const args = [
|
||||||
|
toFixedHex(input.root),
|
||||||
|
toFixedHex(input.nullifierHash),
|
||||||
|
toFixedHex(input.receiver, 20),
|
||||||
|
toFixedHex(input.relayer, 20),
|
||||||
|
toFixedHex(input.fee),
|
||||||
|
toFixedHex(input.refund)
|
||||||
|
]
|
||||||
|
let incorrectArgs
|
||||||
const originalProof = proof.slice()
|
const originalProof = proof.slice()
|
||||||
|
|
||||||
// receiver
|
// receiver
|
||||||
publicSignals[2] = '0x0000000000000000000000007a1f9131357404ef86d7c38dbffed2da70321337'
|
incorrectArgs = [
|
||||||
|
toFixedHex(input.root),
|
||||||
let error = await mixer.withdraw(proof, publicSignals, { from: relayer }).should.be.rejected
|
toFixedHex(input.nullifierHash),
|
||||||
|
toFixedHex('0x0000000000000000000000007a1f9131357404ef86d7c38dbffed2da70321337', 20),
|
||||||
|
toFixedHex(input.relayer, 20),
|
||||||
|
toFixedHex(input.fee),
|
||||||
|
toFixedHex(input.refund)
|
||||||
|
]
|
||||||
|
let error = await mixer.withdraw(proof, ...incorrectArgs, { from: relayer }).should.be.rejected
|
||||||
error.reason.should.be.equal('Invalid withdraw proof')
|
error.reason.should.be.equal('Invalid withdraw proof')
|
||||||
|
|
||||||
// fee
|
// fee
|
||||||
publicSignals = originalPublicSignals.slice()
|
incorrectArgs = [
|
||||||
publicSignals[3] = '0x000000000000000000000000000000000000000000000000015345785d8a0000'
|
toFixedHex(input.root),
|
||||||
|
toFixedHex(input.nullifierHash),
|
||||||
error = await mixer.withdraw(proof, publicSignals, { from: relayer }).should.be.rejected
|
toFixedHex(input.receiver, 20),
|
||||||
|
toFixedHex(input.relayer, 20),
|
||||||
|
toFixedHex('0x000000000000000000000000000000000000000000000000015345785d8a0000'),
|
||||||
|
toFixedHex(input.refund)
|
||||||
|
]
|
||||||
|
error = await mixer.withdraw(proof, ...incorrectArgs, { from: relayer }).should.be.rejected
|
||||||
error.reason.should.be.equal('Invalid withdraw proof')
|
error.reason.should.be.equal('Invalid withdraw proof')
|
||||||
|
|
||||||
// nullifier
|
// nullifier
|
||||||
publicSignals = originalPublicSignals.slice()
|
incorrectArgs = [
|
||||||
publicSignals[1] = '0x00abdfc78211f8807b9c6504a6e537e71b8788b2f529a95f1399ce124a8642ad'
|
toFixedHex(input.root),
|
||||||
|
toFixedHex('0x00abdfc78211f8807b9c6504a6e537e71b8788b2f529a95f1399ce124a8642ad'),
|
||||||
error = await mixer.withdraw(proof, publicSignals, { from: relayer }).should.be.rejected
|
toFixedHex(input.receiver, 20),
|
||||||
|
toFixedHex(input.relayer, 20),
|
||||||
|
toFixedHex(input.fee),
|
||||||
|
toFixedHex(input.refund)
|
||||||
|
]
|
||||||
|
error = await mixer.withdraw(proof, ...incorrectArgs, { from: relayer }).should.be.rejected
|
||||||
error.reason.should.be.equal('Invalid withdraw proof')
|
error.reason.should.be.equal('Invalid withdraw proof')
|
||||||
|
|
||||||
// proof itself
|
// proof itself
|
||||||
proof[0] = '0x261d81d8203437f29b38a88c4263476d858e6d9645cf21740461684412b31337'
|
proof = '0xbeef' + proof.substr(6)
|
||||||
await mixer.withdraw(proof, originalPublicSignals, { from: relayer }).should.be.rejected
|
await mixer.withdraw(proof, ...args, { from: relayer }).should.be.rejected
|
||||||
|
|
||||||
// should work with original values
|
// should work with original values
|
||||||
await mixer.withdraw(originalProof, originalPublicSignals, { from: relayer }).should.be.fulfilled
|
await mixer.withdraw(originalProof, ...args, { from: relayer }).should.be.fulfilled
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should reject with non zero refund', async () => {
|
it('should reject with non zero refund', async () => {
|
||||||
@ -428,9 +496,17 @@ contract('ETHMixer', accounts => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
|
||||||
const { proof, publicSignals } = websnarkUtils.toSolidityInput(proofData)
|
const { proof } = websnarkUtils.toSolidityInput(proofData)
|
||||||
|
|
||||||
const error = await mixer.withdraw(proof, publicSignals, { from: relayer }).should.be.rejected
|
const args = [
|
||||||
|
toFixedHex(input.root),
|
||||||
|
toFixedHex(input.nullifierHash),
|
||||||
|
toFixedHex(input.receiver, 20),
|
||||||
|
toFixedHex(input.relayer, 20),
|
||||||
|
toFixedHex(input.fee),
|
||||||
|
toFixedHex(input.refund)
|
||||||
|
]
|
||||||
|
const error = await mixer.withdraw(proof, ...args, { from: relayer }).should.be.rejected
|
||||||
error.reason.should.be.equal('Refund value is supposed to be zero for ETH mixer')
|
error.reason.should.be.equal('Refund value is supposed to be zero for ETH mixer')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user