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: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"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 { JsonRpcProvider } from '@ethersproject/providers'
import { OptimismProvider } from '@eth-optimism/provider'
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: JsonRpcProvider,
readonly l2Provider: OptimismProvider,
readonly minTxSize: number,
readonly maxTxSize: number,
readonly maxBatchSize: number,
Expand Down
13 changes: 6 additions & 7 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, toRpcHexString } from '@eth-optimism/core-utils'
import { Logger, Bytes32 } from '@eth-optimism/core-utils'
import { OptimismProvider } from '@eth-optimism/provider'

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

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

for (let i = startBlock; i < endBlock; i++) {
const block = (await this.l2Provider.send('eth_getBlockByNumber', [
toRpcHexString(i),
true,
])) as L2Block
const block = (await this.l2Provider.getBlockWithTransactions(
i
)) as L2Block
if (block.transactions[0].from === this.fraudSubmissionAddress) {
batch.push(
'0xbad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1'
Expand Down
122 changes: 87 additions & 35 deletions src/batch-submitter/tx-batch-submitter.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
/* External Imports */
import { Promise as bPromise } from 'bluebird'
import { Signer, ethers, Wallet, Contract } from 'ethers'
import { TransactionReceipt } from '@ethersproject/abstract-provider'
import { JsonRpcProvider } from '@ethersproject/providers'
import { BigNumber, Signer, ethers, Wallet, Contract } from 'ethers'
import {
TransactionResponse,
TransactionReceipt,
} from '@ethersproject/abstract-provider'
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 @@ -24,7 +29,6 @@ import {
} from '../transaction-chain-contract'

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

constructor(
signer: Signer,
l2Provider: JsonRpcProvider,
l2Provider: OptimismProvider,
minTxSize: number,
maxTxSize: number,
maxBatchSize: number,
Expand Down Expand Up @@ -343,7 +347,6 @@ 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 @@ -580,12 +583,24 @@ export class TransactionBatchSubmitter extends BatchSubmitter {
})
// tx: [0nonce, 1gasprice, 2startgas, 3to, 4value, 5data, 6v, 7r, 8s]
const tx = ethers.utils.RLP.decode(rawTx)
const dummyTx = '0x1234'
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,
}
return {
stateRoot: queueElement.stateRoot,
isSequencerTx: true,
sequencerTxType: TxType.EIP155,
rawTransaction: dummyTx,
txData: dummyTx,
timestamp: queueElement.timestamp,
blockNumber: queueElement.blockNumber,
}
Expand Down Expand Up @@ -664,7 +679,17 @@ export class TransactionBatchSubmitter extends BatchSubmitter {
if (!block.isSequencerTx) {
continue
}
transactions.push(block.rawTransaction)
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)
}

return {
Expand All @@ -678,40 +703,67 @@ 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)) {
sequencerFields.isSequencerTx = true
sequencerFields.sequencerTxType =
txTypePlainText[block.transactions[0].txType]
sequencerFields.rawTransaction = block.transactions[0].rawTransaction
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,
}
}
}

const batchElement = {
...sequencerFields,
stateRoot: block.stateRoot,
timestamp: formatNumber(block.timestamp),
blockNumber: formatNumber(block.transactions[0].l1BlockNumber),
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
}

return batchElement
return block
}

private async _getBlock(blockNumber: number): Promise<L2Block> {
return (await this.l2Provider.send('eth_getBlockByNumber', [
toRpcHexString(blockNumber),
true,
])) as L2Block
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 _isSequencerTx(block: L2Block): boolean {
return (
queueOriginPlainText[block.transactions[0].queueOrigin] ===
QueueOrigin.Sequencer
)
return block.transactions[0].queueOrigin === QueueOrigin.Sequencer
}
}
4 changes: 3 additions & 1 deletion src/exec/run-batch-submitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ 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 @@ -120,7 +122,7 @@ export const run = async () => {
const l1Provider: Provider = new JsonRpcProvider(
requiredEnvVars.L1_NODE_WEB3_URL
)
const l2Provider: JsonRpcProvider = new JsonRpcProvider(
const l2Provider: OptimismProvider = new OptimismProvider(
requiredEnvVars.L2_NODE_WEB3_URL
)

Expand Down
5 changes: 2 additions & 3 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 { TxType } from '@eth-optimism/core-utils'
import { EIP155TxData, TxType } from '@eth-optimism/core-utils'

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

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

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

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

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

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

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!')
public async send(endpoint: string, params: []): Promise<any> {
if (endpoint === 'eth_chainId') {
return this.chainId()
}
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