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

Merge the devel branch into the main branch, v3.0.0 #139

Merged
merged 11 commits into from
Jan 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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: 3 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,8 @@ jobs:
file: ./docker/Dockerfile.relayer
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
RELAYER_REF=${{ github.ref_name }}
RELAYER_SHA=${{ github.sha }}
cache-from: type=gha
cache-to: type=gha
4 changes: 4 additions & 0 deletions CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
| RELAYER_REDIS_URL | Url to redis instance | URL |
| RPC_URL | The HTTPS URL(s) used to communicate to the RPC nodes. Several URLs can be specified, delimited by spaces. If the connection to one of these nodes is lost the next URL is used for connection. | URL |
| RELAYER_TX_REDUNDANCY | If set to `true`, instructs relayer to send `eth_sendRawTransaction` requests through all available RPC urls defined in `RPC_URL` variables instead of using first available one. Defaults to `false` | boolean |
| RELAYER_RPC_SYNC_STATE_CHECK_INTERVAL | Interval in milliseconds for checking JSON RPC sync state, by requesting the latest block number. Relayer will switch to the fallback JSON RPC in case sync process is stuck. If this variable is `0` sync state check is disabled. Defaults to `0` | integer |
| INSUFFICIENT_BALANCE_CHECK_TIMEOUT | Interval in milliseconds to check for relayer balance update if transaction send failed with insufficient balance error. Default `60000` | integer |
| SENT_TX_DELAY | Delay in milliseconds for sentTxWorker to verify submitted transactions | integer |
| PERMIT_DEADLINE_THRESHOLD_INITIAL | Minimum time threshold in seconds for permit signature deadline to be valid (before initial transaction submission) | integer |
| PERMIT_DEADLINE_THRESHOLD_RESEND | Minimum time threshold in seconds for permit signature deadline to be valid (for re-send attempts) | integer |
| RELAYER_REQUIRE_TRACE_ID | If set to `true`, then requests to relayer (except `/info`, `/version`, `/params/hash/tree`, `/params/hash/tx`) without `zkbob-support-id` header will be rejected. | boolean |
| RELAYER_REQUIRE_HTTPS | If set to `true`, then RPC URL(s) must be in HTTPS format. HTTP RPC URL(s) should be used in test environment only. | boolean |
21 changes: 14 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,10 @@ sequenceDiagram
## API

For a detailed description of each method's payload you can refer to [`zp-relayer/validation/validation.ts`](zp-relayer/validation/validation.ts) file with JSON validation schemas.

- `/sendTransaction` - submit a transaction to relayer (deprecated).
Note, that requests to all endpoints (except `/`, `/info`, `/params/hash/tree`, `/params/hash/tx`) also require a special `zkbob-support-id` header if `RELAYER_REQUIRE_TRACE_ID` env is set to `true`. This header should be automatically set by the client application.

- `/sendTransactions` - submit batch of transaction to relayer.

- `/transactions?limit=${limit}&offset=${offset}&optimistic=${true|false}` - list of transaction memo blocks (deprecated).

- `/transactions/v2?limit=${limit}&offset=${offset}` - list of encoded transactions data in the following format `"${stateBit}${txHash}${outCommit}${memo}"`. `stateBit` is `1` if transaction is in confirmed state and `0` otherwise.

- `/merkle/root/:index?` - get Merkle Tree root at specified index.
Expand Down Expand Up @@ -120,11 +117,11 @@ For a detailed description of each method's payload you can refer to [`zp-relaye
{
deposit: {
singleOperation // Limit for single pool operation
daylyForAddress: { // Daily deposit limits for address
dailyForAddress: { // Daily deposit limits for address
total
available
},
daylyForAll: { // Daily deposit limits for all users
dailyForAll: { // Daily deposit limits for all users
total
available
},
Expand All @@ -134,7 +131,7 @@ For a detailed description of each method's payload you can refer to [`zp-relaye
},
},
withdraw: {
daylyForAll: { // Daily withdraw limit for all users
dailyForAll: { // Daily withdraw limit for all users
total
available
},
Expand All @@ -143,6 +140,16 @@ For a detailed description of each method's payload you can refer to [`zp-relaye
}
```

- `/version` - currently used relayer version

**Response**
```
{
ref // Branch or tag
commitHash // Commit hash
}
```

- `/params/hash/tree` - hash of pool tree proving parameters.

- `/params/hash/tx` - hash of pool transaction proving parameters.
5 changes: 5 additions & 0 deletions docker/Dockerfile.relayer
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ RUN yarn install --frozen-lockfile --production

FROM node:18

ARG RELAYER_REF
ARG RELAYER_SHA
ENV RELAYER_REF=${RELAYER_REF}
ENV RELAYER_SHA=${RELAYER_SHA}

WORKDIR /app

COPY --from=build /app/zp-relayer/build ./zp-relayer
Expand Down
6 changes: 6 additions & 0 deletions zp-relayer/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const relayerAddress = new Web3().eth.accounts.privateKeyToAccount(
).address

const config = {
relayerRef: process.env.RELAYER_REF || null,
relayerSHA: process.env.RELAYER_SHA || null,
port: parseInt(process.env.PORT || '8000'),
relayerAddress,
relayerPrivateKey: process.env.RELAYER_ADDRESS_PRIVATE_KEY as string,
Expand Down Expand Up @@ -37,10 +39,14 @@ const config = {
relayerTxRedundancy: process.env.RELAYER_TX_REDUNDANCY === 'true',
sentTxDelay: parseInt(process.env.SENT_TX_DELAY || '30000'),
rpcRequestTimeout: parseInt(process.env.RPC_REQUEST_TIMEOUT || '1000'),
insufficientBalanceCheckTimeout: parseInt(process.env.INSUFFICIENT_BALANCE_CHECK_TIMEOUT || '60000'),
rpcSyncCheckInterval: parseInt(process.env.RELAYER_RPC_SYNC_STATE_CHECK_INTERVAL || '0'),
permitDeadlineThresholdInitial: parseInt(process.env.PERMIT_DEADLINE_THRESHOLD_INITIAL || '300'),
relayerJsonRpcErrorCodes: (process.env.RELAYER_JSONRPC_ERROR_CODES || '-32603,-32002,-32005')
.split(',')
.map(s => parseInt(s, 10)),
requireTraceId: process.env.RELAYER_REQUIRE_TRACE_ID === 'true',
requireHTTPS: process.env.RELAYER_REQUIRE_HTTPS === 'true',
}

export default config
117 changes: 45 additions & 72 deletions zp-relayer/endpoints.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
import { Request, Response, NextFunction } from 'express'
import { pool } from './pool'
import { logger } from './services/appLogger'
import { Request, Response } from 'express'
import { pool, PoolTx } from './pool'
import { poolTxQueue } from './queue/poolTxQueue'
import config from './config'
import {
checkGetLimits,
checkGetSiblings,
checkGetTransactions,
checkGetTransactionsV2,
checkMerkleRootErrors,
checkSendTransactionErrors,
checkSendTransactionsErrors,
checkTraceId,
validateBatch,
} from './validation/validation'
import { sentTxQueue, SentTxState } from './queue/sentTxQueue'
import type { Queue } from 'bullmq'
import { TRACE_ID } from './utils/constants'

async function sendTransactions(req: Request, res: Response, next: NextFunction) {
const errors = checkSendTransactionsErrors(req.body)
if (errors) {
logger.info('Request errors: %o', errors)
res.status(400).json({ errors })
return
}
async function sendTransactions(req: Request, res: Response) {
validateBatch([
[checkTraceId, req.headers],
[checkSendTransactionsErrors, req.body],
])

const rawTxs = req.body
const txs = rawTxs.map((tx: any) => {
const rawTxs = req.body as PoolTx[]
const traceId = req.headers[TRACE_ID] as string

const txs = rawTxs.map(tx => {
const { proof, memo, txType, depositSignature } = tx
return {
proof,
Expand All @@ -33,59 +33,26 @@ async function sendTransactions(req: Request, res: Response, next: NextFunction)
depositSignature,
}
})
const jobId = await pool.transact(txs)
const jobId = await pool.transact(txs, traceId)
res.json({ jobId })
}

async function sendTransaction(req: Request, res: Response, next: NextFunction) {
const errors = checkSendTransactionErrors(req.body)
if (errors) {
logger.info('Request errors: %o', errors)
res.status(400).json({ errors })
return
}

const { proof, memo, txType, depositSignature } = req.body
const tx = [{ proof, memo, txType, depositSignature }]
const jobId = await pool.transact(tx)
res.json({ jobId })
}

async function merkleRoot(req: Request, res: Response, next: NextFunction) {
const errors = checkMerkleRootErrors(req.params)
if (errors) {
logger.info('Request errors: %o', errors)
res.status(400).json({ errors })
return
}
async function merkleRoot(req: Request, res: Response) {
validateBatch([
[checkTraceId, req.headers],
[checkMerkleRootErrors, req.params],
])

const index = req.params.index
const root = await pool.getContractMerkleRoot(index)
res.json(root)
}

async function getTransactions(req: Request, res: Response, next: NextFunction) {
const errors = checkGetTransactions(req.query)
if (errors) {
logger.info('Request errors: %o', errors)
res.status(400).json({ errors })
return
}

const state = req.query.optimistic ? pool.optimisticState : pool.state
// Types checked in validation stage
// @ts-ignore
const { txs } = await state.getTransactions(req.query.limit, req.query.offset)
res.json(txs)
}

async function getTransactionsV2(req: Request, res: Response, next: NextFunction) {
const errors = checkGetTransactionsV2(req.query)
if (errors) {
logger.info('Request errors: %o', errors)
res.status(400).json({ errors })
return
}
async function getTransactionsV2(req: Request, res: Response) {
validateBatch([
[checkTraceId, req.headers],
[checkGetTransactionsV2, req.query],
])

const toV2Format = (prefix: string) => (tx: string) => {
const outCommit = tx.slice(0, 64)
Expand Down Expand Up @@ -128,6 +95,8 @@ async function getJob(req: Request, res: Response) {
txHash: null | string
}

validateBatch([[checkTraceId, req.headers]])

const jobId = req.params.id

async function getPoolJobState(requestedJobId: string): Promise<GetJobResponse | null> {
Expand Down Expand Up @@ -233,18 +202,18 @@ function relayerInfo(req: Request, res: Response) {
}

function getFee(req: Request, res: Response) {
validateBatch([[checkTraceId, req.headers]])

res.json({
fee: config.relayerFee.toString(10),
})
}

async function getLimits(req: Request, res: Response) {
const errors = checkGetLimits(req.query)
if (errors) {
logger.info('Request errors: %o', errors)
res.status(400).json({ errors })
return
}
validateBatch([
[checkTraceId, req.headers],
[checkGetLimits, req.query],
])

const address = req.query.address as unknown as string
const limits = await pool.getLimitsFor(address)
Expand All @@ -253,12 +222,10 @@ async function getLimits(req: Request, res: Response) {
}

function getSiblings(req: Request, res: Response) {
const errors = checkGetSiblings(req.query)
if (errors) {
logger.info('Request errors: %o', errors)
res.status(400).json({ errors })
return
}
validateBatch([
[checkTraceId, req.headers],
[checkGetSiblings, req.query],
])

const index = req.query.index as unknown as number

Expand All @@ -278,21 +245,27 @@ function getParamsHash(type: 'tree' | 'transfer') {
}
}

function relayerVersion(req: Request, res: Response) {
res.json({
ref: config.relayerRef,
commitHash: config.relayerSHA,
})
}

function root(req: Request, res: Response) {
return res.sendStatus(200)
}

export default {
sendTransaction,
sendTransactions,
merkleRoot,
getTransactions,
getTransactionsV2,
getJob,
relayerInfo,
getFee,
getLimits,
getSiblings,
getParamsHash,
relayerVersion,
root,
}
2 changes: 1 addition & 1 deletion zp-relayer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "zp-relayer",
"version": "2.2.0",
"version": "3.0.0",
"main": "build/index.js",
"types": "build/index.d.ts",
"scripts": {
Expand Down
Loading