Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add HTTPS URL validation #124

Merged
merged 2 commits into from
Jan 2, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion zp-relayer/config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import './env'
import Web3 from 'web3'
import { toBN } from 'web3-utils'
import type { EstimationType, GasPriceKey } from './services/gas-price'
import type { EstimationType, GasPriceKey } from './services/gas-price/types'

const relayerAddress = new Web3().eth.accounts.privateKeyToAccount(
process.env.RELAYER_ADDRESS_PRIVATE_KEY as string
Expand Down Expand Up @@ -41,6 +41,7 @@ const config = {
relayerJsonRpcErrorCodes: (process.env.RELAYER_JSONRPC_ERROR_CODES || '-32603,-32002,-32005')
.split(',')
.map(s => parseInt(s, 10)),
requireHTTPS: process.env.RELAYER_REQUIRE_HTTPS === 'true',
}

export default config
1 change: 1 addition & 0 deletions zp-relayer/services/providers/HttpListProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { logger } from '../appLogger'
import BaseHttpProvider, { ProviderOptions } from './BaseHttpProvider'

export class HttpListProviderError extends Error {
name = 'HttpListProviderError'
errors: Error[]
constructor(message: string, errors: Error[]) {
super(message)
Expand Down
2 changes: 2 additions & 0 deletions zp-relayer/services/web3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import type { HttpProvider } from 'web3-core'
import { RETRY_CONFIG } from '@/utils/constants'
import HttpListProvider from './providers/HttpListProvider'
import RedundantHttpListProvider from './providers/RedundantHttpListProvider'
import { checkHTTPS } from '@/utils/helpers'

const providerOptions = {
requestTimeout: config.rpcRequestTimeout,
retry: RETRY_CONFIG,
}

config.rpcUrls.forEach(checkHTTPS(config.requireHTTPS))
const provider = new HttpListProvider(config.rpcUrls, providerOptions)
const web3 = new Web3(provider as HttpProvider)

Expand Down
31 changes: 24 additions & 7 deletions zp-relayer/utils/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import BN from 'bn.js'
import type BN from 'bn.js'
import { padLeft, toBN } from 'web3-utils'
import { logger } from '@/services/appLogger'
import { SnarkProof } from 'libzkbob-rs-node'
import type { SnarkProof } from 'libzkbob-rs-node'
import { TxType } from 'zp-memo-parser'
import type { Mutex } from 'async-mutex'
import { TxValidationError } from '@/validateTx'

const S_MASK = toBN('0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff')
const S_MAX = toBN('0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0')
Expand Down Expand Up @@ -113,14 +112,19 @@ export function withMutex<R>(mutex: Mutex, f: () => Promise<R>): () => Promise<R
}
}

export async function withErrorLog<R>(f: () => Promise<R>): Promise<R> {
export async function withErrorLog<R>(
f: () => Promise<R>,
WarnErrors: (new (...args: any[]) => Error)[] = []
): Promise<R> {
try {
return await f()
} catch (e) {
if (e instanceof TxValidationError) {
logger.warn('Validation error: %s', (e as Error).message)
const err = e as Error
const isWarn = WarnErrors.some(WarnError => err instanceof WarnError)
if (isWarn) {
logger.warn('%s: %s', err.name, err.message)
} else {
logger.error('Found error: %s', (e as Error).message)
logger.error('Found error: %s', err.message)
}
throw e
}
Expand Down Expand Up @@ -157,3 +161,16 @@ export function withLoop<R>(f: () => Promise<R>, timeout: number, supressedError
}
}
}

export function checkHTTPS(isRequired: boolean) {
return (url: string) => {
console.log(url, isRequired)
if (!/^https.*/.test(url)) {
if (isRequired) {
throw new Error(`http is not allowed: ${url}`)
} else {
logger.warn('HTTP RPC URL is not recommended for production usage')
}
}
}
}
2 changes: 1 addition & 1 deletion zp-relayer/utils/web3.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Web3 from 'web3'
import type Web3 from 'web3'
import { Contract, PastEventOptions } from 'web3-eth-contract'
import { logger } from '@/services/appLogger'

Expand Down
1 change: 1 addition & 0 deletions zp-relayer/validateTx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const tokenContract = new web3.eth.Contract(TokenAbi as AbiItem[], config.tokenA
const ZERO = toBN(0)

export class TxValidationError extends Error {
name = 'TxValidationError'
constructor(message: string) {
super(message)
}
Expand Down
6 changes: 5 additions & 1 deletion zp-relayer/workers/poolTxWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type { Mutex } from 'async-mutex'
import { getChainId } from '@/utils/web3'
import { getTxProofField } from '@/utils/proofInputs'
import type { Redis } from 'ioredis'
import { TxValidationError } from '@/validateTx'

export async function createPoolTxWorker<T extends EstimationType>(
gasPrice: GasPrice<T>,
Expand Down Expand Up @@ -128,7 +129,10 @@ export async function createPoolTxWorker<T extends EstimationType>(

const poolTxWorker = new Worker<TxPayload[], PoolTxResult[]>(
TX_QUEUE_NAME,
job => withErrorLog(withMutex(mutex, () => poolTxWorkerProcessor(job))),
job => withErrorLog(
withMutex(mutex, () => poolTxWorkerProcessor(job)),
[TxValidationError]
),
WORKER_OPTIONS
)

Expand Down