2020-09-30 11:35:48 -04:00
|
|
|
const { isAddress, toChecksumAddress } = require('web3-utils')
|
2020-09-27 22:28:34 -04:00
|
|
|
const { getInstance } = require('./utils')
|
|
|
|
|
2020-09-28 10:54:54 -04:00
|
|
|
const Ajv = require('ajv')
|
|
|
|
const ajv = new Ajv({ format: 'fast' })
|
2020-09-27 22:28:34 -04:00
|
|
|
|
2020-09-28 10:54:54 -04:00
|
|
|
ajv.addKeyword('isAddress', {
|
|
|
|
validate: (schema, data) => {
|
|
|
|
try {
|
|
|
|
return isAddress(data)
|
|
|
|
} catch (e) {
|
|
|
|
return false
|
2020-09-27 22:28:34 -04:00
|
|
|
}
|
2020-09-28 10:54:54 -04:00
|
|
|
},
|
2020-09-30 11:35:48 -04:00
|
|
|
errors: true,
|
2020-09-28 10:54:54 -04:00
|
|
|
})
|
|
|
|
|
|
|
|
ajv.addKeyword('isKnownContract', {
|
|
|
|
validate: (schema, data) => {
|
|
|
|
try {
|
|
|
|
return getInstance(data) !== null
|
|
|
|
} catch (e) {
|
|
|
|
return false
|
2020-09-27 22:28:34 -04:00
|
|
|
}
|
2020-09-28 10:54:54 -04:00
|
|
|
},
|
2020-09-30 11:35:48 -04:00
|
|
|
errors: true,
|
2020-09-28 10:54:54 -04:00
|
|
|
})
|
|
|
|
|
2020-09-28 23:17:42 -04:00
|
|
|
ajv.addKeyword('isFeeRecipient', {
|
2020-09-28 10:54:54 -04:00
|
|
|
validate: (schema, data) => {
|
|
|
|
try {
|
2020-09-30 11:35:48 -04:00
|
|
|
return require('../config').rewardAccount === toChecksumAddress(data)
|
2020-09-28 10:54:54 -04:00
|
|
|
} catch (e) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
},
|
2020-09-30 11:35:48 -04:00
|
|
|
errors: true,
|
2020-09-28 10:54:54 -04:00
|
|
|
})
|
|
|
|
|
|
|
|
const addressType = { type: 'string', pattern: '^0x[a-fA-F0-9]{40}$', isAddress: true }
|
|
|
|
const proofType = { type: 'string', pattern: '^0x[a-fA-F0-9]{512}$' }
|
|
|
|
const encryptedAccountType = { type: 'string', pattern: '^0x[a-fA-F0-9]{392}$' }
|
|
|
|
const bytes32Type = { type: 'string', pattern: '^0x[a-fA-F0-9]{64}$' }
|
2020-09-28 23:17:42 -04:00
|
|
|
const instanceType = { ...addressType, isKnownContract: true }
|
|
|
|
const relayerType = { ...addressType, isFeeRecipient: true }
|
2020-09-28 10:54:54 -04:00
|
|
|
|
|
|
|
const tornadoWithdrawSchema = {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
proof: proofType,
|
|
|
|
contract: instanceType,
|
|
|
|
args: {
|
|
|
|
type: 'array',
|
|
|
|
maxItems: 6,
|
|
|
|
minItems: 6,
|
2020-09-30 11:35:48 -04:00
|
|
|
items: [bytes32Type, bytes32Type, addressType, relayerType, bytes32Type, bytes32Type],
|
|
|
|
},
|
2020-09-28 10:54:54 -04:00
|
|
|
},
|
|
|
|
additionalProperties: false,
|
2020-09-30 11:35:48 -04:00
|
|
|
required: ['proof', 'contract', 'args'],
|
2020-09-27 22:28:34 -04:00
|
|
|
}
|
|
|
|
|
2020-09-28 10:54:54 -04:00
|
|
|
const miningRewardSchema = {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
proof: proofType,
|
|
|
|
args: {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
rate: bytes32Type,
|
|
|
|
fee: bytes32Type,
|
|
|
|
instance: instanceType,
|
|
|
|
rewardNullifier: bytes32Type,
|
|
|
|
extDataHash: bytes32Type,
|
|
|
|
depositRoot: bytes32Type,
|
|
|
|
withdrawalRoot: bytes32Type,
|
|
|
|
extData: {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
relayer: relayerType,
|
2020-09-30 11:35:48 -04:00
|
|
|
encryptedAccount: encryptedAccountType,
|
2020-09-28 10:54:54 -04:00
|
|
|
},
|
|
|
|
additionalProperties: false,
|
2020-09-30 11:35:48 -04:00
|
|
|
required: ['relayer', 'encryptedAccount'],
|
2020-09-28 10:54:54 -04:00
|
|
|
},
|
|
|
|
account: {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
inputRoot: bytes32Type,
|
|
|
|
inputNullifierHash: bytes32Type,
|
|
|
|
outputRoot: bytes32Type,
|
|
|
|
outputPathIndices: bytes32Type,
|
2020-09-30 11:35:48 -04:00
|
|
|
outputCommitment: bytes32Type,
|
2020-09-28 10:54:54 -04:00
|
|
|
},
|
|
|
|
additionalProperties: false,
|
2020-09-30 11:35:48 -04:00
|
|
|
required: [
|
|
|
|
'inputRoot',
|
|
|
|
'inputNullifierHash',
|
|
|
|
'outputRoot',
|
|
|
|
'outputPathIndices',
|
|
|
|
'outputCommitment',
|
|
|
|
],
|
|
|
|
},
|
2020-09-28 10:54:54 -04:00
|
|
|
},
|
|
|
|
additionalProperties: false,
|
|
|
|
required: [
|
|
|
|
'rate',
|
|
|
|
'fee',
|
|
|
|
'instance',
|
|
|
|
'rewardNullifier',
|
|
|
|
'extDataHash',
|
|
|
|
'depositRoot',
|
|
|
|
'withdrawalRoot',
|
|
|
|
'extData',
|
2020-09-30 11:35:48 -04:00
|
|
|
'account',
|
|
|
|
],
|
|
|
|
},
|
2020-09-28 10:54:54 -04:00
|
|
|
},
|
|
|
|
additionalProperties: false,
|
2020-09-30 11:35:48 -04:00
|
|
|
required: ['proof', 'args'],
|
2020-09-28 10:54:54 -04:00
|
|
|
}
|
2020-09-27 22:28:34 -04:00
|
|
|
|
2020-09-28 10:54:54 -04:00
|
|
|
const miningWithdrawSchema = {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
proof: proofType,
|
|
|
|
args: {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
amount: bytes32Type,
|
|
|
|
fee: bytes32Type,
|
|
|
|
extDataHash: bytes32Type,
|
|
|
|
extData: {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
recipient: addressType,
|
|
|
|
relayer: relayerType,
|
2020-09-30 11:35:48 -04:00
|
|
|
encryptedAccount: encryptedAccountType,
|
2020-09-28 10:54:54 -04:00
|
|
|
},
|
|
|
|
additionalProperties: false,
|
2020-09-30 11:35:48 -04:00
|
|
|
required: ['relayer', 'encryptedAccount', 'recipient'],
|
2020-09-28 10:54:54 -04:00
|
|
|
},
|
|
|
|
account: {
|
|
|
|
type: 'object',
|
|
|
|
properties: {
|
|
|
|
inputRoot: bytes32Type,
|
|
|
|
inputNullifierHash: bytes32Type,
|
|
|
|
outputRoot: bytes32Type,
|
|
|
|
outputPathIndices: bytes32Type,
|
2020-09-30 11:35:48 -04:00
|
|
|
outputCommitment: bytes32Type,
|
2020-09-28 10:54:54 -04:00
|
|
|
},
|
|
|
|
additionalProperties: false,
|
2020-09-30 11:35:48 -04:00
|
|
|
required: [
|
|
|
|
'inputRoot',
|
|
|
|
'inputNullifierHash',
|
|
|
|
'outputRoot',
|
|
|
|
'outputPathIndices',
|
|
|
|
'outputCommitment',
|
|
|
|
],
|
|
|
|
},
|
2020-09-28 10:54:54 -04:00
|
|
|
},
|
|
|
|
additionalProperties: false,
|
2020-09-30 11:35:48 -04:00
|
|
|
required: ['amount', 'fee', 'extDataHash', 'extData', 'account'],
|
|
|
|
},
|
2020-09-28 10:54:54 -04:00
|
|
|
},
|
|
|
|
additionalProperties: false,
|
2020-09-30 11:35:48 -04:00
|
|
|
required: ['proof', 'args'],
|
2020-09-27 22:28:34 -04:00
|
|
|
}
|
|
|
|
|
2020-09-28 10:54:54 -04:00
|
|
|
const validateTornadoWithdraw = ajv.compile(tornadoWithdrawSchema)
|
|
|
|
const validateMiningReward = ajv.compile(miningRewardSchema)
|
|
|
|
const validateMiningWithdraw = ajv.compile(miningWithdrawSchema)
|
2020-09-27 22:28:34 -04:00
|
|
|
|
2020-09-28 10:54:54 -04:00
|
|
|
function getInputError(validator, data) {
|
|
|
|
validator(data)
|
|
|
|
if (validator.errors) {
|
|
|
|
const error = validator.errors[0]
|
|
|
|
return `${error.dataPath} ${error.message}`
|
|
|
|
}
|
2020-09-27 22:28:34 -04:00
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
2020-09-28 10:54:54 -04:00
|
|
|
function getTornadoWithdrawInputError(data) {
|
|
|
|
return getInputError(validateTornadoWithdraw, data)
|
2020-09-27 22:28:34 -04:00
|
|
|
}
|
|
|
|
|
2020-09-28 10:54:54 -04:00
|
|
|
function getMiningRewardInputError(data) {
|
|
|
|
return getInputError(validateMiningReward, data)
|
2020-09-27 22:28:34 -04:00
|
|
|
}
|
|
|
|
|
2020-09-28 10:54:54 -04:00
|
|
|
function getMiningWithdrawInputError(data) {
|
|
|
|
return getInputError(validateMiningWithdraw, data)
|
2020-09-27 22:28:34 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = {
|
2020-09-28 10:54:54 -04:00
|
|
|
getTornadoWithdrawInputError,
|
|
|
|
getMiningRewardInputError,
|
2020-09-30 11:35:48 -04:00
|
|
|
getMiningWithdrawInputError,
|
2020-09-27 22:28:34 -04:00
|
|
|
}
|