Commit 0df744f6 authored by Mark Tyneway's avatar Mark Tyneway

core-utils,contracts-bedrock,ci: OpNodeProvider + check

Implements a simple `OpNodeProvider` that can be used
to query the op-node. It is used as part of a ci check
against the devnet. It should add some more health related
things, now it just prints of rpc responses. This will
help to debug things.
parent 6c9862a8
---
'@eth-optimism/core-utils': patch
---
Implement basic OpNodeProvider
...@@ -457,9 +457,12 @@ jobs: ...@@ -457,9 +457,12 @@ jobs:
--amount-eth 1 \ --amount-eth 1 \
--private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \ --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
--network devnetL1 --network devnetL1
working_directory: packages/contracts-bedrock/contracts-bedrock working_directory: packages/contracts-bedrock
- run: - run:
command: echo "Deposit complete." name: Check the status
command: |
npx hardhat check-op-node
working_directory: packages/contracts-bedrock
integration-tests: integration-tests:
machine: machine:
......
...@@ -14,6 +14,7 @@ import './tasks/genesis-l2' ...@@ -14,6 +14,7 @@ import './tasks/genesis-l2'
import './tasks/deposits' import './tasks/deposits'
import './tasks/rekey' import './tasks/rekey'
import './tasks/rollup-config' import './tasks/rollup-config'
import './tasks/check-op-node'
subtask(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS).setAction( subtask(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS).setAction(
async (_, __, runSuper) => { async (_, __, runSuper) => {
......
import { task, types } from 'hardhat/config'
import { OpNodeProvider } from '@eth-optimism/core-utils'
// TODO(tynes): add in config validation
task('check-op-node', 'Validate the config of the op-node')
.addParam(
'opNodeUrl',
'URL of the OP Node.',
'http://localhost:7545',
types.string
)
.setAction(async (args) => {
const provider = new OpNodeProvider(args.opNodeUrl)
const syncStatus = await provider.syncStatus()
console.log(JSON.stringify(syncStatus, null, 2))
const config = await provider.rollupConfig()
console.log(JSON.stringify(config, null, 2))
})
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
"@ethersproject/abstract-provider": "^5.6.1", "@ethersproject/abstract-provider": "^5.6.1",
"@ethersproject/providers": "^5.6.8", "@ethersproject/providers": "^5.6.8",
"@ethersproject/transactions": "^5.6.2", "@ethersproject/transactions": "^5.6.2",
"@ethersproject/properties": "^5.6.0",
"@ethersproject/web": "^5.6.1",
"bufio": "^1.0.7", "bufio": "^1.0.7",
"chai": "^4.3.4", "chai": "^4.3.4",
"ethers": "^5.6.8" "ethers": "^5.6.8"
......
...@@ -10,3 +10,4 @@ export * from './op-node' ...@@ -10,3 +10,4 @@ export * from './op-node'
export * from './deposit-transaction' export * from './deposit-transaction'
export * from './encoding' export * from './encoding'
export * from './hashing' export * from './hashing'
export * from './op-provider'
import EventEmitter from 'events'
import { BigNumber } from 'ethers'
import { deepCopy } from '@ethersproject/properties'
import { ConnectionInfo, fetchJson } from '@ethersproject/web'
const getResult = (payload: {
error?: { code?: number; data?: any; message?: string }
result?: any
}): any => {
if (payload.error) {
const error: any = new Error(payload.error.message)
error.code = payload.error.code
error.data = payload.error.data
throw error
}
return payload.result
}
export interface BlockDescriptor {
hash: string
number: BigNumber
parentHash: string
timestamp: BigNumber
}
export interface L2BlockDescriptor extends BlockDescriptor {
l1Origin: {
hash: string
number: BigNumber
}
sequencerNumber: BigNumber
}
export interface SyncStatusResponse {
currentL1: BlockDescriptor
headL1: BlockDescriptor
unsafeL2: L2BlockDescriptor
safeL2: L2BlockDescriptor
finalizedL2: L2BlockDescriptor
}
export class OpNodeProvider extends EventEmitter {
readonly connection: ConnectionInfo
private _nextId: number = 0
constructor(url?: ConnectionInfo | string) {
super()
if (typeof url === 'string') {
this.connection = { url }
} else {
this.connection = url
}
}
async syncStatus(): Promise<SyncStatusResponse> {
const result = await this.send('optimism_syncStatus', [])
return {
currentL1: {
hash: result.current_l1.hash,
number: BigNumber.from(result.current_l1.number),
parentHash: result.current_l1.parentHash,
timestamp: BigNumber.from(result.current_l1.timestamp),
},
headL1: {
hash: result.head_l1.hash,
number: BigNumber.from(result.head_l1.number),
parentHash: result.head_l1.parentHash,
timestamp: BigNumber.from(result.head_l1.timestamp),
},
unsafeL2: {
hash: result.unsafe_l2.hash,
number: BigNumber.from(result.unsafe_l2.number),
parentHash: result.unsafe_l2.parentHash,
timestamp: BigNumber.from(result.unsafe_l2.timestamp),
l1Origin: {
hash: result.unsafe_l2.l1origin.hash,
number: BigNumber.from(result.unsafe_l2.l1origin.number),
},
sequencerNumber: BigNumber.from(result.unsafe_l2.sequenceNumber),
},
safeL2: {
hash: result.safe_l2.hash,
number: BigNumber.from(result.safe_l2.number),
parentHash: result.safe_l2.parentHash,
timestamp: BigNumber.from(result.safe_l2.timestamp),
l1Origin: {
hash: result.safe_l2.l1origin.hash,
number: BigNumber.from(result.safe_l2.l1origin.number),
},
sequencerNumber: BigNumber.from(result.safe_l2.sequenceNumber),
},
finalizedL2: {
hash: result.finalized_l2.hash,
number: BigNumber.from(result.finalized_l2.number),
parentHash: result.finalized_l2.parentHash,
timestamp: BigNumber.from(result.finalized_l2.timestamp),
l1Origin: {
hash: result.finalized_l2.l1origin.hash,
number: BigNumber.from(result.finalized_l2.l1origin.number),
},
sequencerNumber: BigNumber.from(result.finalized_l2.sequenceNumber),
},
}
}
// TODO(tynes): turn the response into a stronger type
async rollupConfig() {
const result = await this.send('optimism_rollupConfig', [])
return result
}
send(method: string, params: Array<any>): Promise<any> {
const request = {
method,
params,
id: this._nextId++,
jsonrpc: '2.0',
}
this.emit('debug', {
action: 'request',
request: deepCopy(request),
provider: this,
})
const result = fetchJson(
this.connection,
JSON.stringify(request),
getResult
).then(
(res) => {
this.emit('debug', {
action: 'response',
request,
response: res,
provider: this,
})
return res
},
(error) => {
this.emit('debug', {
action: 'response',
error,
request,
provider: this,
})
throw error
}
)
return result
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment