Skip to content
This repository was archived by the owner on Apr 11, 2021. It is now read-only.
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
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
"dependencies": {
"@eth-optimism/contracts": "^0.0.2-alpha.7",
"@eth-optimism/core-utils": "^0.1.10",
"@eth-optimism/provider": "^0.0.1-alpha.13",
"@eth-optimism/ynatm": "^0.2.2",
"@ethersproject/abstract-provider": "^5.0.5",
"@ethersproject/providers": "^5.0.14",
Expand Down
4 changes: 2 additions & 2 deletions src/batch-submitter/batch-submitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Contract, Signer, utils } from 'ethers'
import { TransactionReceipt } from '@ethersproject/abstract-provider'
import * as ynatm from '@eth-optimism/ynatm'
import { Address, Bytes32, Logger } from '@eth-optimism/core-utils'
import { OptimismProvider } from '@eth-optimism/provider'
import { JsonRpcProvider } from '@ethersproject/providers'
import { getContractFactory } from '@eth-optimism/contracts'

export interface RollupInfo {
Expand Down Expand Up @@ -38,7 +38,7 @@ export abstract class BatchSubmitter {

constructor(
readonly signer: Signer,
readonly l2Provider: OptimismProvider,
readonly l2Provider: JsonRpcProvider,
readonly minTxSize: number,
readonly maxTxSize: number,
readonly maxBatchSize: number,
Expand Down
13 changes: 7 additions & 6 deletions src/batch-submitter/state-batch-submitter.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/* External Imports */
import { Contract, Signer } from 'ethers'
import { TransactionReceipt } from '@ethersproject/abstract-provider'
import { JsonRpcProvider } from '@ethersproject/providers'
import { getContractFactory } from '@eth-optimism/contracts'
import { Logger, Bytes32 } from '@eth-optimism/core-utils'
import { OptimismProvider } from '@eth-optimism/provider'
import { Logger, Bytes32, toRpcHexString } from '@eth-optimism/core-utils'

/* Internal Imports */
import { L2Block } from '..'
Expand All @@ -21,7 +21,7 @@ export class StateBatchSubmitter extends BatchSubmitter {

constructor(
signer: Signer,
l2Provider: OptimismProvider,
l2Provider: JsonRpcProvider,
minTxSize: number,
maxTxSize: number,
maxBatchSize: number,
Expand Down Expand Up @@ -173,9 +173,10 @@ export class StateBatchSubmitter extends BatchSubmitter {
const batch: Bytes32[] = []

for (let i = startBlock; i < endBlock; i++) {
const block = (await this.l2Provider.getBlockWithTransactions(
i
)) as L2Block
const block = (await this.l2Provider.send('eth_getBlockByNumber', [
toRpcHexString(i),
true,
])) as L2Block
if (block.transactions[0].from === this.fraudSubmissionAddress) {
batch.push(
'0xbad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1'
Expand Down
122 changes: 35 additions & 87 deletions src/batch-submitter/tx-batch-submitter.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
/* External Imports */
import { Promise as bPromise } from 'bluebird'
import { BigNumber, Signer, ethers, Wallet, Contract } from 'ethers'
import {
TransactionResponse,
TransactionReceipt,
} from '@ethersproject/abstract-provider'
import { Signer, ethers, Wallet, Contract } from 'ethers'
import { TransactionReceipt } from '@ethersproject/abstract-provider'
import { JsonRpcProvider } from '@ethersproject/providers'
import {
getContractInterface,
getContractFactory,
} from '@eth-optimism/contracts'
import { getContractInterface as getNewContractInterface } from 'new-contracts'
import { OptimismProvider } from '@eth-optimism/provider'
import {
Logger,
EIP155TxData,
TxType,
ctcCoder,
EthSignTxData,
txTypePlainText,
toRpcHexString,
} from '@eth-optimism/core-utils'

/* Internal Imports */
Expand All @@ -29,6 +24,7 @@ import {
} from '../transaction-chain-contract'

import {
formatNumber,
L2Block,
BatchElement,
Batch,
Expand All @@ -52,7 +48,7 @@ export class TransactionBatchSubmitter extends BatchSubmitter {

constructor(
signer: Signer,
l2Provider: OptimismProvider,
l2Provider: JsonRpcProvider,
minTxSize: number,
maxTxSize: number,
maxBatchSize: number,
Expand Down Expand Up @@ -347,6 +343,7 @@ export class TransactionBatchSubmitter extends BatchSubmitter {
): Promise<boolean> {
const logEqualityError = (name, index, expected, got) => {
this.log.error('Observed mismatched values', {
name,
index,
expected,
got,
Expand Down Expand Up @@ -583,24 +580,12 @@ export class TransactionBatchSubmitter extends BatchSubmitter {
})
// tx: [0nonce, 1gasprice, 2startgas, 3to, 4value, 5data, 6v, 7r, 8s]
const tx = ethers.utils.RLP.decode(rawTx)
const dummyTx: EIP155TxData = {
sig: {
v: tx[6],
r: tx[7],
s: tx[8],
},
gasLimit,
gasPrice,
nonce,
target: tx[3],
data: tx[5],
type: TxType.EIP155,
}
const dummyTx = '0x1234'
return {
stateRoot: queueElement.stateRoot,
isSequencerTx: true,
sequencerTxType: TxType.EIP155,
txData: dummyTx,
rawTransaction: dummyTx,
timestamp: queueElement.timestamp,
blockNumber: queueElement.blockNumber,
}
Expand Down Expand Up @@ -679,17 +664,7 @@ export class TransactionBatchSubmitter extends BatchSubmitter {
if (!block.isSequencerTx) {
continue
}
let encoding: string
if (block.sequencerTxType === TxType.EIP155) {
encoding = ctcCoder.eip155TxData.encode(block.txData as EIP155TxData)
} else if (block.sequencerTxType === TxType.EthSign) {
encoding = ctcCoder.ethSignTxData.encode(block.txData as EthSignTxData)
} else {
throw new Error(
`Trying to build batch with unknown type ${block.sequencerTxType}`
)
}
transactions.push(encoding)
transactions.push(block.rawTransaction)
}

return {
Expand All @@ -703,67 +678,40 @@ export class TransactionBatchSubmitter extends BatchSubmitter {

private async _getL2BatchElement(blockNumber: number): Promise<BatchElement> {
const block = await this._getBlock(blockNumber)
const txType = block.transactions[0].txType

const sequencerFields = {
isSequencerTx: false,
sequencerTxType: undefined,
rawTransaction: undefined,
}
if (this._isSequencerTx(block)) {
if (txType === TxType.EIP155 || txType === TxType.EthSign) {
return this._getDefaultEcdsaTxBatchElement(block)
} else {
throw new Error('Unsupported Tx Type!')
}
} else {
return {
stateRoot: block.stateRoot,
isSequencerTx: false,
sequencerTxType: undefined,
txData: undefined,
timestamp: block.timestamp,
blockNumber: block.transactions[0].l1BlockNumber,
}
sequencerFields.isSequencerTx = true
sequencerFields.sequencerTxType =
txTypePlainText[block.transactions[0].txType]
sequencerFields.rawTransaction = block.transactions[0].rawTransaction
}
}

private async _getBlock(blockNumber: number): Promise<L2Block> {
const block = (await this.l2Provider.getBlockWithTransactions(
blockNumber
)) as L2Block
// Convert the tx type to a number
block.transactions[0].txType = txTypePlainText[block.transactions[0].txType]
block.transactions[0].queueOrigin =
queueOriginPlainText[block.transactions[0].queueOrigin]
// For now just set the l1BlockNumber based on the current l1 block number
if (!block.transactions[0].l1BlockNumber) {
block.transactions[0].l1BlockNumber = this.lastL1BlockNumber
const batchElement = {
...sequencerFields,
stateRoot: block.stateRoot,
timestamp: formatNumber(block.timestamp),
blockNumber: formatNumber(block.transactions[0].l1BlockNumber),
}
return block

return batchElement
}

private _getDefaultEcdsaTxBatchElement(block: L2Block): BatchElement {
const tx: TransactionResponse = block.transactions[0]
const txData: EIP155TxData = {
sig: {
v: tx.v - this.l2ChainId * 2 - 8 - 27,
r: tx.r,
s: tx.s,
},
gasLimit: BigNumber.from(tx.gasLimit).toNumber(),
gasPrice: BigNumber.from(tx.gasPrice).toNumber(),
nonce: tx.nonce,
target: tx.to ? tx.to : '00'.repeat(20),
data: tx.data,
type: block.transactions[0].txType,
}
return {
stateRoot: block.stateRoot,
isSequencerTx: true,
sequencerTxType: block.transactions[0].txType,
txData,
timestamp: block.timestamp,
blockNumber: block.transactions[0].l1BlockNumber,
}
private async _getBlock(blockNumber: number): Promise<L2Block> {
return (await this.l2Provider.send('eth_getBlockByNumber', [
toRpcHexString(blockNumber),
true,
])) as L2Block
}

private _isSequencerTx(block: L2Block): boolean {
return block.transactions[0].queueOrigin === QueueOrigin.Sequencer
return (
queueOriginPlainText[block.transactions[0].queueOrigin] ===
QueueOrigin.Sequencer
)
}
}
4 changes: 1 addition & 3 deletions src/exec/run-batch-submitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@ import {
JsonRpcProvider,
TransactionReceipt,
} from '@ethersproject/providers'
import { OptimismProvider } from '@eth-optimism/provider'
import { config } from 'dotenv'
config()

/* Internal Imports */
import {
TransactionBatchSubmitter,
AutoFixBatchOptions,
BatchSubmitter,
StateBatchSubmitter,
STATE_BATCH_SUBMITTER_LOG_TAG,
TX_BATCH_SUBMITTER_LOG_TAG,
Expand Down Expand Up @@ -122,7 +120,7 @@ export const run = async () => {
const l1Provider: Provider = new JsonRpcProvider(
requiredEnvVars.L1_NODE_WEB3_URL
)
const l2Provider: OptimismProvider = new OptimismProvider(
const l2Provider: JsonRpcProvider = new JsonRpcProvider(
requiredEnvVars.L2_NODE_WEB3_URL
)

Expand Down
5 changes: 3 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
} from '@ethersproject/abstract-provider'

/* Internal Imports */
import { EIP155TxData, TxType } from '@eth-optimism/core-utils'
import { TxType } from '@eth-optimism/core-utils'

export enum QueueOrigin {
Sequencer = 0,
Expand All @@ -29,6 +29,7 @@ export interface L2Transaction extends TransactionResponse {
l1TxOrigin: string
txType: number
queueOrigin: number
rawTransaction: string
}

export interface L2Block extends BlockWithTransactions {
Expand All @@ -44,7 +45,7 @@ export interface BatchElement {
stateRoot: string
isSequencerTx: boolean
sequencerTxType: undefined | TxType
txData: undefined | EIP155TxData
rawTransaction: undefined | string
timestamp: number
blockNumber: number
}
Expand Down
7 changes: 7 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,10 @@ export const remove0x = (str: string): string => {
return str
}
}

export const formatNumber = (num: any): number => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be num: string?

Is there a function which does this in core-utils? If not I think it's fine to include here but eventually probably a good idea to move it there

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i copied this from ethers formatter, which i think is supposed to keep the input general since it may begin as a number too

https://github.com/ethers-io/ethers.js/blob/6c43e20e7a68f3f5a141c74527ec63d9fe8458be/packages/providers/src.ts/formatter.ts#L165-L170

i'll move it into core-utils in a followup PR :)

if (num === '0x') {
return 0
}
return BigNumber.from(num).toNumber()
}
51 changes: 30 additions & 21 deletions test/batch-submitter/mockchain-provider.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* External Imports */
import { OptimismProvider } from '@eth-optimism/provider'
import { BigNumber } from 'ethers'
import {
BlockWithTransactions,
TransactionResponse,
} from '@ethersproject/abstract-provider'
import { JsonRpcProvider } from '@ethersproject/providers'

/* Internal Imports */
import { L2Transaction, L2Block, RollupInfo } from '../../src'
Expand All @@ -18,14 +19,15 @@ interface UnformattedL2Transaction extends TransactionResponse {
l1MessageSender: string
signatureHashType: string
queueOrigin: string
rawTransaction: string
}

interface UnformattedL2Block extends BlockWithTransactions {
stateRoot: string
transactions: [UnformattedL2Transaction]
}

export class MockchainProvider extends OptimismProvider {
export class MockchainProvider extends JsonRpcProvider {
public mockBlockNumber: number = 1
public numBlocksToReturn: number = 2
public mockBlocks: L2Block[] = []
Expand Down Expand Up @@ -59,26 +61,33 @@ export class MockchainProvider extends OptimismProvider {
return this.mockBlockNumber
}

public async send(endpoint: string, params: []): Promise<any> {
if (endpoint === 'eth_chainId') {
return this.chainId()
public async send(endpoint: string, params: any[]): Promise<any> {
switch (endpoint) {
case 'eth_chainId':
return this.chainId()
case 'rollup_getInfo':
const info: RollupInfo = {
mode: 'sequencer',
syncing: false,
ethContext: {
timestamp: 0,
blockNumber: 0,
},
rollupContext: {
index: 0,
queueIndex: 0,
},
}
return info
case 'eth_getBlockByNumber':
if (params.length === 0) {
throw new Error(`Invalid params for ${endpoint}`)
}
const blockNumber = BigNumber.from(params[0]).toNumber()
return this.mockBlocks[blockNumber]
default:
throw new Error('Unsupported endpoint!')
}
if (endpoint === 'rollup_getInfo') {
const info: RollupInfo = {
mode: 'sequencer',
syncing: false,
ethContext: {
timestamp: 0,
blockNumber: 0,
},
rollupContext: {
index: 0,
queueIndex: 0,
},
}
return info
}
throw new Error('Unsupported endpoint!')
}

public setNumBlocksToReturn(numBlocks: number): void {
Expand Down
Loading