Commit bb0285bc authored by Matthew Slipper's avatar Matthew Slipper Committed by GitHub

Merge branch 'develop' into feat/caching-itests

parents 71d64834 f4903adb
---
'@eth-optimism/core-utils': patch
---
Cleans up the internal file and folder structure for the typings exported by core-utils
---
'@eth-optimism/batch-submitter-service': minor
---
Add multi-tx support, clear pending txs on startup
......@@ -29,6 +29,7 @@ jobs:
rpc-proxy : ${{ steps.packages.outputs.rpc-proxy }}
op-exporter : ${{ steps.packages.outputs.op-exporter }}
l2geth-exporter : ${{ steps.packages.outputs.l2geth-exporter }}
batch-submitter-service : ${{ steps.packages.outputs.batch-submitter-service }}
steps:
- name: Check out source code
......@@ -506,3 +507,29 @@ jobs:
file: ./ops/docker/Dockerfile.rpc-proxy
push: true
tags: ethereumoptimism/rpc-proxy:${{ needs.canary-publish.outputs.rpc-proxy }}
batch-submitter-service:
name: Publish batch-submitter-service Version ${{ needs.canary-publish.outputs.canary-docker-tag }}
needs: canary-publish
if: needs.canary-publish.outputs.batch-submitter-service != ''
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: ./ops/docker/Dockerfile.batch-submitter-service
push: true
tags: ethereumoptimism/batch-submitter-service:${{ needs.canary-publish.outputs.batch-submitter-service }}
......@@ -25,6 +25,7 @@ jobs:
hardhat-node: ${{ steps.packages.outputs.hardhat-node }}
op-exporter : ${{ steps.packages.outputs.op-exporter }}
l2geth-exporter : ${{ steps.packages.outputs.l2geth-exporter }}
batch-submitter-service : ${{ steps.packages.outputs.batch-submitter-service }}
steps:
- name: Checkout Repo
......@@ -502,3 +503,29 @@ jobs:
push: true
tags: ethereumoptimism/replica-healthcheck:${{ needs.builder.outputs.replica-healthcheck }},ethereumoptimism/replica-healthcheck:latest
build-args: BUILDER_TAG=${{ needs.builder.outputs.builder }}
batch-submitter-service:
name: Publish batch-submitter-service Version ${{ needs.release.outputs.batch-submitter-service }}
needs: release
if: needs.release.outputs.batch-submitter-service != ''
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: ./ops/docker/Dockerfile.batch-submitter-service
push: true
tags: ethereumoptimism/batch-submitter-service:${{ needs.release.outputs.batch-submitter-service }},ethereumoptimism/batch-submitter-service:latest
export * from './types'
export * from './sequencer-batch'
......@@ -2,8 +2,7 @@ export * from './coders'
export * from './common'
export * from './watcher'
export * from './l2context'
export * from './batches'
export * from './bcfg'
export * from './types'
export * from './fees'
export * from './provider'
export * from './alias'
......
// Use this file for simple types that aren't necessarily associated with a specific project or
// package. Often used for alias types like Address = string.
export interface Signature {
r: string
s: string
......
// Optimism PBC 2021
// Types explicitly related to dealing with Geth.
// Represents the ethereum state
/**
* Represents the Ethereum state, in the format that Geth expects it.
*/
export interface State {
[address: string]: {
nonce: number
......@@ -14,7 +16,9 @@ export interface State {
}
}
// Represents a genesis file that geth can consume
/**
* Represents Geth's genesis file format.
*/
export interface Genesis {
config: {
chainId: number
......
export * from './geth'
export * from './bcfg'
export * from './rollup'
export * from './basic'
......@@ -4,6 +4,9 @@ import {
TransactionResponse,
} from '@ethersproject/abstract-provider'
/**
* Structure of the response returned by L2Geth nodes when querying the `rollup_getInfo` endpoint.
*/
export interface RollupInfo {
mode: 'sequencer' | 'verifier'
syncing: boolean
......@@ -17,14 +20,18 @@ export interface RollupInfo {
}
}
/**
* Enum used for the two transaction types (queue and direct to Sequencer).
*/
export enum QueueOrigin {
Sequencer = 'sequencer',
L1ToL2 = 'l1',
}
/**
* Transaction & Blocks. These are the true data-types we expect
* from running a batch submitter.
* JSON transaction representation when returned by L2Geth nodes. This is simply an extension to
* the standard transaction response type. You do NOT need to use this type unless you care about
* having typed access to L2-specific fields.
*/
export interface L2Transaction extends TransactionResponse {
l1BlockNumber: number
......@@ -33,21 +40,32 @@ export interface L2Transaction extends TransactionResponse {
rawTransaction: string
}
/**
* JSON block representation when returned by L2Geth nodes. Just a normal block but with
* L2Transaction objects instead of the standard transaction response object.
*/
export interface L2Block extends BlockWithTransactions {
stateRoot: string
transactions: [L2Transaction]
}
/**
* BatchElement & Batch. These are the data-types of the compressed / batched
* block data we submit to L1.
* Generic batch element, either a state root batch element or a transaction batch element.
*/
export interface BatchElement {
// Only exists on state root batch elements.
stateRoot: string
// Only exists on transaction batch elements.
isSequencerTx: boolean
rawTransaction: undefined | string
// Batch element context, exists on all batch elements.
timestamp: number
blockNumber: number
}
/**
* List of batch elements.
*/
export type Batch = BatchElement[]
......@@ -421,9 +421,27 @@ export class CrossChainProvider implements ICrossChainProvider {
}
public async estimateL2MessageGasLimit(
message: MessageLike
message: MessageLike,
opts?: {
bufferPercent?: number
}
): Promise<BigNumber> {
throw new Error('Not implemented')
const resolved = await this.toCrossChainMessage(message)
// L2 message gas estimation is only used for L1 => L2 messages.
if (resolved.direction === MessageDirection.L2_TO_L1) {
throw new Error(`cannot estimate gas limit for L2 => L1 message`)
}
const estimate = await this.l2Provider.estimateGas({
from: resolved.sender,
to: resolved.target,
data: resolved.message,
})
// Return the estimate plus a buffer of 20% just in case.
const bufferPercent = opts?.bufferPercent || 20
return estimate.mul(100 + bufferPercent).div(100)
}
public async estimateMessageWaitTimeSeconds(
......
......@@ -201,9 +201,16 @@ export interface ICrossChainProvider {
* L1 => L2 messages. You would supply this gas limit when sending the message to L2.
*
* @param message Message get a gas estimate for.
* @param opts Options object.
* @param opts.bufferPercent Percentage of gas to add to the estimate. Defaults to 20.
* @returns Estimates L2 gas limit.
*/
estimateL2MessageGasLimit(message: MessageLike): Promise<BigNumber>
estimateL2MessageGasLimit(
message: MessageLike,
opts?: {
bufferPercent?: number
}
): Promise<BigNumber>
/**
* Returns the estimated amount of time before the message can be executed. When this is a
......
import { Provider } from '@ethersproject/abstract-provider'
import { expectApprox } from '@eth-optimism/core-utils'
import { Contract } from 'ethers'
import { ethers } from 'hardhat'
......@@ -1091,7 +1092,93 @@ describe('CrossChainProvider', () => {
})
describe('estimateL2MessageGasLimit', () => {
it('should perform a gas estimation of the L2 action')
let provider: CrossChainProvider
beforeEach(async () => {
provider = new CrossChainProvider({
l1Provider: ethers.provider,
l2Provider: ethers.provider,
l1ChainId: 31337,
})
})
describe('when the message is an L1 to L2 message', () => {
it('should return an accurate gas estimate plus a ~20% buffer', async () => {
const message = {
direction: MessageDirection.L1_TO_L2,
target: '0x' + '11'.repeat(20),
sender: '0x' + '22'.repeat(20),
message: '0x' + '33'.repeat(64),
messageNonce: 1234,
logIndex: 0,
blockNumber: 1234,
transactionHash: '0x' + '44'.repeat(32),
}
const estimate = await ethers.provider.estimateGas({
to: message.target,
from: message.sender,
data: message.message,
})
// Approximately 20% greater than the estimate, +/- 1%.
expectApprox(
await provider.estimateL2MessageGasLimit(message),
estimate.mul(120).div(100),
{
percentUpperDeviation: 1,
percentLowerDeviation: 1,
}
)
})
it('should return an accurate gas estimate when a custom buffer is provided', async () => {
const message = {
direction: MessageDirection.L1_TO_L2,
target: '0x' + '11'.repeat(20),
sender: '0x' + '22'.repeat(20),
message: '0x' + '33'.repeat(64),
messageNonce: 1234,
logIndex: 0,
blockNumber: 1234,
transactionHash: '0x' + '44'.repeat(32),
}
const estimate = await ethers.provider.estimateGas({
to: message.target,
from: message.sender,
data: message.message,
})
// Approximately 30% greater than the estimate, +/- 1%.
expectApprox(
await provider.estimateL2MessageGasLimit(message, {
bufferPercent: 30,
}),
estimate.mul(130).div(100),
{
percentUpperDeviation: 1,
percentLowerDeviation: 1,
}
)
})
})
describe('when the message is an L2 to L1 message', () => {
it('should throw an error', async () => {
const message = {
direction: MessageDirection.L2_TO_L1,
target: '0x' + '11'.repeat(20),
sender: '0x' + '22'.repeat(20),
message: '0x' + '33'.repeat(64),
messageNonce: 1234,
logIndex: 0,
blockNumber: 1234,
transactionHash: '0x' + '44'.repeat(32),
}
await expect(provider.estimateL2MessageGasLimit(message)).to.be.rejected
})
})
})
describe('estimateMessageWaitTimeBlocks', () => {
......
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