Commit 77108d37 authored by Annie Ke's avatar Annie Ke Committed by GitHub

feat[integration-tests]: add verifier sync test (#913)

* feat[ops]: add verifier config

* add verifier sync test

* add changeset
parent 3f1e7e62
---
'@eth-optimism/integration-tests': patch
---
Add verifier sync test and extra docker-compose functions
......@@ -13,6 +13,7 @@
"build:contracts": "hardhat compile",
"build:contracts:ovm": "hardhat compile --network optimism",
"test:integration": "hardhat --network optimism test",
"test:sync": "hardhat --network optimism test sync-tests/*.spec.ts --no-compile",
"clean": "rimraf cache artifacts artifacts-ovm cache-ovm"
},
"devDependencies": {
......
import chai, { expect } from 'chai'
import { Wallet, BigNumber, providers } from 'ethers'
import { injectL2Context } from '@eth-optimism/core-utils'
import { sleep, l2Provider, verifierProvider } from '../test/shared/utils'
import { OptimismEnv } from '../test/shared/env'
import { DockerComposeNetwork } from '../test/shared/docker-compose'
describe('Syncing a verifier', () => {
let env: OptimismEnv
let wallet: Wallet
let verifier: DockerComposeNetwork
let provider: providers.JsonRpcProvider
const sequencerProvider = injectL2Context(l2Provider)
/* Helper functions */
const waitForBatchSubmission = async (
totalElementsBefore: BigNumber
): Promise<BigNumber> => {
// Wait for batch submission to happen by watching the CTC
let totalElementsAfter = (await env.ctc.getTotalElements()) as BigNumber
while (totalElementsBefore.eq(totalElementsAfter)) {
await sleep(500)
totalElementsAfter = (await env.ctc.getTotalElements()) as BigNumber
}
return totalElementsAfter
}
const startVerifier = async () => {
// Bring up new verifier
verifier = new DockerComposeNetwork(['verifier'])
await verifier.up({ commandOptions: ['--scale', 'verifier=1'] })
// Wait for verifier to be looping
let logs = await verifier.logs()
while (!logs.out.includes('Starting Sequencer Loop')) {
await sleep(500)
logs = await verifier.logs()
}
provider = injectL2Context(verifierProvider)
}
const syncVerifier = async (sequencerBlockNumber: number) => {
// Wait until verifier has caught up to the sequencer
let latestVerifierBlock = (await provider.getBlock('latest')) as any
while (latestVerifierBlock.number < sequencerBlockNumber) {
await sleep(500)
latestVerifierBlock = (await provider.getBlock('latest')) as any
}
return provider.getBlock(sequencerBlockNumber)
}
before(async () => {
env = await OptimismEnv.new()
wallet = env.l2Wallet
})
describe('Basic transactions', () => {
afterEach(async () => {
await verifier.stop('verifier')
await verifier.rm()
})
it('should sync dummy transaction', async () => {
const totalElementsBefore = (await env.ctc.getTotalElements()) as BigNumber
const tx = {
to: '0x' + '1234'.repeat(10),
gasLimit: 4000000,
gasPrice: 0,
data: '0x',
value: 0,
}
const result = await wallet.sendTransaction(tx)
await result.wait()
const totalElementsAfter = await waitForBatchSubmission(
totalElementsBefore
)
expect(totalElementsAfter.gt(totalElementsAfter))
const latestSequencerBlock = (await sequencerProvider.getBlock(
'latest'
)) as any
await startVerifier()
const matchingVerifierBlock = (await syncVerifier(
latestSequencerBlock.number
)) as any
expect(matchingVerifierBlock.stateRoot).to.eq(
latestSequencerBlock.stateRoot
)
})
})
})
......@@ -2,7 +2,12 @@ import * as compose from 'docker-compose'
import * as shell from 'shelljs'
import * as path from 'path'
type ServiceNames = 'batch_submitter' | 'dtl' | 'l2geth' | 'relayer'
type ServiceNames =
| 'batch_submitter'
| 'dtl'
| 'l2geth'
| 'relayer'
| 'verifier'
const OPS_DIRECTORY = path.join(process.cwd(), '../ops')
const DEFAULT_SERVICES: ServiceNames[] = [
......@@ -15,8 +20,11 @@ const DEFAULT_SERVICES: ServiceNames[] = [
export class DockerComposeNetwork {
constructor(private readonly services: ServiceNames[] = DEFAULT_SERVICES) {}
async up() {
const out = await compose.upMany(this.services, { cwd: OPS_DIRECTORY })
async up(options?: compose.IDockerComposeOptions) {
const out = await compose.upMany(this.services, {
cwd: OPS_DIRECTORY,
...options,
})
const { err, exitCode } = out
......@@ -35,5 +43,19 @@ export class DockerComposeNetwork {
cwd: OPS_DIRECTORY,
})
}
return out
}
async logs() {
return compose.logs(this.services, { cwd: OPS_DIRECTORY })
}
async stop(service: ServiceNames) {
return compose.stopOne(service, { cwd: OPS_DIRECTORY })
}
async rm() {
return compose.rm({ cwd: OPS_DIRECTORY })
}
}
......@@ -21,8 +21,10 @@ export const GWEI = BigNumber.from(1e9)
const env = cleanEnv(process.env, {
L1_URL: str({ default: 'http://localhost:9545' }),
L2_URL: str({ default: 'http://localhost:8545' }),
VERIFIER_URL: str({ default: 'http://localhost:8547' }),
L1_POLLING_INTERVAL: num({ default: 10 }),
L2_POLLING_INTERVAL: num({ default: 10 }),
VERIFIER_POLLING_INTERVAL: num({ default: 10 }),
PRIVATE_KEY: str({
default:
'0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',
......@@ -39,6 +41,9 @@ l1Provider.pollingInterval = env.L1_POLLING_INTERVAL
export const l2Provider = new providers.JsonRpcProvider(env.L2_URL)
l2Provider.pollingInterval = env.L2_POLLING_INTERVAL
export const verifierProvider = new providers.JsonRpcProvider(env.VERIFIER_URL)
verifierProvider.pollingInterval = env.VERIFIER_POLLING_INTERVAL
// The sequencer private key which is funded on L1
export const l1Wallet = new Wallet(env.PRIVATE_KEY, l1Provider)
......
......@@ -3,6 +3,6 @@
"compilerOptions": {
"resolveJsonModule": true
},
"include": ["./test"],
"include": ["./test", "sync-tests/*.ts"],
"files": ["./hardhat.config.ts"]
}
......@@ -28,6 +28,12 @@ docker-compose \
up --build --detach
```
Optionally, run a verifier along the rest of the stack.
```
docker-compose up --scale verifier=1 \
--build --detach
```
A Makefile has been provided for convience. The following targets are available.
- make up
- make down
......
......@@ -129,6 +129,35 @@ services:
URL: http://deployer:8081/addresses.json
SEQUENCER_PRIVATE_KEY: "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"
verifier:
depends_on:
- l1_chain
- deployer
- dtl
image: ethereumoptimism/l2geth
deploy:
replicas: 0
build:
context: ..
dockerfile: ./ops/docker/Dockerfile.geth
# override with the geth script and the env vars required for it
entrypoint: sh ./geth.sh
env_file:
- ./envs/geth.env
environment:
ETH1_HTTP: http://l1_chain:8545
ROLLUP_STATE_DUMP_PATH: http://deployer:8081/state-dump.latest.json
# used for getting the addresses
URL: http://deployer:8081/addresses.json
# connecting to the DTL
ROLLUP_CLIENT_HTTP: http://dtl:7878
ETH1_CTC_DEPLOYMENT_HEIGHT: 8
RETRIES: 60
IS_VERIFIER: "true"
ports:
- ${VERIFIER_HTTP_PORT:-8547}:8545
- ${VERIFIER_WS_PORT:-8548}:8546
integration_tests:
image: ethereumoptimism/integration-tests
deploy:
......
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