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

Fixing return payload for reverts #31

Merged
merged 6 commits into from
Mar 10, 2020
Merged
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ export const JSONRPC_ERRORS = {
code: -32603,
message: 'Internal error',
},
REVERT_ERROR: {
code: -32015,
message: 'revert: requested action reverted',
},
}

/**
Expand Down
1 change: 0 additions & 1 deletion packages/ovm/src/app/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ export const getOvmTransactionMetadata = (
/**
* Converts an EVM receipt to an OVM receipt.
*
* @param executionManager The EM contract to use to parse th logs.
* @param internalTxReceipt The EVM tx receipt to convert to an OVM tx receipt
* @returns The converted receipt
*/
Expand Down
5 changes: 5 additions & 0 deletions packages/rollup-full-node/src/app/fullnode-rpc-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import {
FullnodeHandler,
InvalidParametersError,
RevertError,
UnsupportedMethodError,
} from '../types'

Expand Down Expand Up @@ -65,6 +66,10 @@ export class FullnodeRpcServer extends ExpressHttpServer {
result,
})
} catch (err) {
if (err instanceof RevertError) {
log.debug(`Request reverted. Request: ${JSON.stringify(request)}`)
return res.json(buildJsonRpcError('REVERT_ERROR', request.id))
}
if (err instanceof UnsupportedMethodError) {
log.debug(
`Received request with unsupported method: [${JSON.stringify(
Expand Down
30 changes: 19 additions & 11 deletions packages/rollup-full-node/src/app/test-web3-rpc-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,26 @@ export class TestWeb3Handler extends DefaultWeb3Handler {
* Override to add some test RPC methods.
*/
public async handleRequest(method: string, params: any[]): Promise<string> {
if (method === Web3RpcMethods.increaseTimestamp) {
this.assertParameters(params, 1)
this.increaseTimestamp(params[0])
log.debug(`Set increased timestamp by ${params[0]} seconds.`)
return TestWeb3Handler.successString
switch (method) {
case Web3RpcMethods.increaseTimestamp:
this.assertParameters(params, 1)
this.increaseTimestamp(params[0])
log.debug(`Set increased timestamp by ${params[0]} seconds.`)
return TestWeb3Handler.successString
case Web3RpcMethods.getTimestamp:
this.assertParameters(params, 0)
return add0x(this.getTimestamp().toString(16))
case Web3RpcMethods.evmSnapshot:
this.assertParameters(params, 0)
return this.provider.send(Web3RpcMethods.evmSnapshot, [])
case Web3RpcMethods.evmRevert:
this.assertParameters(params, 1)
return this.provider.send(Web3RpcMethods.evmRevert, params)
case Web3RpcMethods.evmMine:
return this.provider.send(Web3RpcMethods.evmMine, params)
default:
return super.handleRequest(method, params)
}
if (method === Web3RpcMethods.getTimestamp) {
this.assertParameters(params, 0)
return add0x(this.getTimestamp().toString(16))
}

return super.handleRequest(method, params)
}

/**
Expand Down
25 changes: 20 additions & 5 deletions packages/rollup-full-node/src/app/web3-rpc-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
} from '@eth-optimism/ovm'

import { Contract, ethers, utils, Wallet } from 'ethers'
import { Web3Provider } from 'ethers/providers'
import { TransactionReceipt, Web3Provider } from 'ethers/providers'
import { createMockProvider, deployContract, getWallets } from 'ethereum-waffle'

import AsyncLock from 'async-lock'
Expand All @@ -26,6 +26,7 @@ import { DEFAULT_ETHNODE_GAS_LIMIT } from '.'
import {
FullnodeHandler,
InvalidParametersError,
RevertError,
UnsupportedMethodError,
Web3Handler,
Web3RpcMethods,
Expand Down Expand Up @@ -63,9 +64,9 @@ export class DefaultWeb3Handler implements Web3Handler, FullnodeHandler {
}

protected constructor(
private readonly provider: Web3Provider,
private readonly wallet: Wallet,
private readonly executionManager: Contract
protected readonly provider: Web3Provider,
protected readonly wallet: Wallet,
protected readonly executionManager: Contract
) {
this.lock = new AsyncLock()
}
Expand Down Expand Up @@ -272,7 +273,10 @@ export class DefaultWeb3Handler implements Web3Handler, FullnodeHandler {
defaultBlock: string
): Promise<string> {
if (defaultBlock !== 'latest') {
throw new Error('No support for historical code lookups!')
log.info(
`No support for historical code lookups! Anything returned from this may be very wrong.`
)
//throw new Error('No support for historical code lookups!')
}
log.debug(
`Getting code for address: [${address}], defaultBlock: [${defaultBlock}]`
Expand Down Expand Up @@ -396,6 +400,17 @@ export class DefaultWeb3Handler implements Web3Handler, FullnodeHandler {
throw Error(msg)
}

const receipt: TransactionReceipt = await this.getTransactionReceipt(
ovmTxHash
)
log.info(
`Transaction receipt for ${rawOvmTx}: ${JSON.stringify(receipt)}`
)
if (!receipt || !receipt.status) {
log.debug(`Transaction reverted: ${rawOvmTx}, ovmTxHash: ${ovmTxHash}`)
throw new RevertError()
}

log.debug(`Completed send raw tx [${rawOvmTx}]. Response: [${ovmTxHash}]`)
// Return the *OVM* tx hash. We can do this because we store a mapping to the ovmTxHashs in the EM contract.
return ovmTxHash
Expand Down
1 change: 1 addition & 0 deletions packages/rollup-full-node/src/exec/fullnode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const runFullnode = async (
const host = '0.0.0.0'
const port = 8545

log.info(`Starting fullnode in ${testFullnode ? 'TEST' : 'LIVE'} mode`)
const fullnodeHandler = testFullnode
? await TestWeb3Handler.create()
: await DefaultWeb3Handler.create()
Expand Down
6 changes: 6 additions & 0 deletions packages/rollup-full-node/src/types/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,9 @@ export class InvalidParametersError extends Error {
)
}
}

export class RevertError extends Error {
constructor(message?: string) {
super(message || 'Revert: The provided transaction reverted.')
}
}
3 changes: 3 additions & 0 deletions packages/rollup-full-node/src/types/web3-rpc-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ export enum Web3RpcMethods {
sendRawTransaction = 'eth_sendRawTransaction',

// Test methods:
evmSnapshot = 'evm_snapshot',
evmRevert = 'evm_revert',
evmMine = 'evm_mine',
increaseTimestamp = 'evm_increaseTime',
getTimestamp = 'evm_getTime',
}
38 changes: 36 additions & 2 deletions packages/rollup-full-node/test/app/fullnode-rpc-server.spec.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
/* External Imports */
import { AxiosHttpClient, getLogger } from '@eth-optimism/core-utils/build/src'
import {
AxiosHttpClient,
getLogger,
JSONRPC_ERRORS,
} from '@eth-optimism/core-utils/build/src'
import { AxiosResponse } from 'axios'

/* Internal Imports */
import { FullnodeRpcServer } from '../../src/app'
import { FullnodeHandler, UnsupportedMethodError } from '../../src/types'
import {
FullnodeHandler,
RevertError,
UnsupportedMethodError,
} from '../../src/types'
import { should } from '../setup'

const log = getLogger('fullnode-rpc-server', true)

const dummyResponse: string = 'Dummy Response =D'

const unsupportedMethod: string = 'unsupported!'
const revertMethod: string = 'revert!'
class DummyFullnodeHandler implements FullnodeHandler {
public async handleRequest(
method: string,
Expand All @@ -20,6 +29,9 @@ class DummyFullnodeHandler implements FullnodeHandler {
if (method === unsupportedMethod) {
throw new UnsupportedMethodError()
}
if (method === revertMethod) {
throw new RevertError()
}
return dummyResponse
}
}
Expand Down Expand Up @@ -114,4 +126,26 @@ describe('FullnodeHandler RPC Server', () => {
r.data['jsonrpc'].should.equal('2.0')
})
})

it('reverts properly', async () => {
const result: AxiosResponse = await request(client, {
id: 1,
jsonrpc: '2.0',
method: revertMethod,
})

result.status.should.equal(200)

result.data.should.haveOwnProperty('id')
result.data.should.haveOwnProperty('jsonrpc')
result.data.should.haveOwnProperty('error')
result.data['error'].should.haveOwnProperty('message')
result.data['error'].should.haveOwnProperty('code')
result.data['error']['message'].should.equal(
JSONRPC_ERRORS.REVERT_ERROR.message
)
result.data['error']['code'].should.equal(JSONRPC_ERRORS.REVERT_ERROR.code)

result.data['jsonrpc'].should.equal('2.0')
})
})