add isSpendArray view function

This commit is contained in:
Roman Storm 2019-11-27 19:45:52 -08:00
parent f5486f0943
commit a6cda4a501
2 changed files with 61 additions and 1 deletions

View File

@ -95,10 +95,20 @@ contract Mixer is MerkleTreeWithHistory, ReentrancyGuard {
function _processWithdraw(address payable _recipient, address payable _relayer, uint256 _fee, uint256 _refund) internal; function _processWithdraw(address payable _recipient, address payable _relayer, uint256 _fee, uint256 _refund) internal;
/** @dev whether a note is already spent */ /** @dev whether a note is already spent */
function isSpent(bytes32 _nullifierHash) external view returns(bool) { function isSpent(bytes32 _nullifierHash) public view returns(bool) {
return nullifierHashes[_nullifierHash]; return nullifierHashes[_nullifierHash];
} }
/** @dev whether an array of notes is already spent */
function isSpentArray(bytes32[] calldata _nullifierHashes) external view returns(bool[] memory spent) {
spent = new bool[](_nullifierHashes.length);
for(uint i = 0; i < _nullifierHashes.length; i++) {
if (isSpent(_nullifierHashes[i])) {
spent[i] = true;
}
}
}
/** /**
@dev allow operator to update SNARK verification keys. This is needed to update keys after the final trusted setup ceremony is held. @dev allow operator to update SNARK verification keys. This is needed to update keys after the final trusted setup ceremony is held.
After that operator rights are supposed to be transferred to zero address After that operator rights are supposed to be transferred to zero address

View File

@ -542,6 +542,56 @@ contract('ETHMixer', accounts => {
}) })
}) })
describe('#isSpent', () => {
it('should work', async () => {
const deposit1 = generateDeposit()
const deposit2 = generateDeposit()
await tree.insert(deposit1.commitment)
await tree.insert(deposit2.commitment)
await mixer.deposit(toFixedHex(deposit1.commitment), { value, gasPrice: '0' })
await mixer.deposit(toFixedHex(deposit2.commitment), { value, gasPrice: '0' })
const { root, path_elements, path_index } = await tree.path(1)
// Circuit input
const input = stringifyBigInts({
// public
root,
nullifierHash: pedersenHash(deposit2.nullifier.leInt2Buff(31)),
relayer: operator,
recipient,
fee,
refund,
// private
nullifier: deposit2.nullifier,
secret: deposit2.secret,
pathElements: path_elements,
pathIndices: path_index,
})
const proofData = await websnarkUtils.genWitnessAndProve(groth16, input, circuit, proving_key)
const { proof } = websnarkUtils.toSolidityInput(proofData)
const args = [
toFixedHex(input.root),
toFixedHex(input.nullifierHash),
toFixedHex(input.recipient, 20),
toFixedHex(input.relayer, 20),
toFixedHex(input.fee),
toFixedHex(input.refund)
]
await mixer.withdraw(proof, ...args, { from: relayer, gasPrice: '0' })
const nullifierHash1 = toFixedHex(pedersenHash(deposit1.nullifier.leInt2Buff(31)))
const nullifierHash2 = toFixedHex(pedersenHash(deposit2.nullifier.leInt2Buff(31)))
const spentArray = await mixer.isSpentArray([nullifierHash1, nullifierHash2])
spentArray.should.be.deep.equal([false, true])
})
})
afterEach(async () => { afterEach(async () => {
await revertSnapshot(snapshotId.result) await revertSnapshot(snapshotId.result)
// eslint-disable-next-line require-atomic-updates // eslint-disable-next-line require-atomic-updates