diff --git a/.changeset/witty-buses-worry.md b/.changeset/witty-buses-worry.md new file mode 100644 index 0000000000000..dbdc0e834bf33 --- /dev/null +++ b/.changeset/witty-buses-worry.md @@ -0,0 +1,7 @@ +--- +"@eth-optimism/batch-submitter": minor +"@eth-optimism/core-utils": patch +--- + +- Use raw transaction in batch submitter -- incompatible with L2Geth v0.1.2.1 +- Pass through raw transaction in l2context diff --git a/packages/batch-submitter/src/batch-submitter/state-batch-submitter.ts b/packages/batch-submitter/src/batch-submitter/state-batch-submitter.ts index 77d1aae23d22c..f23480ea19802 100644 --- a/packages/batch-submitter/src/batch-submitter/state-batch-submitter.ts +++ b/packages/batch-submitter/src/batch-submitter/state-batch-submitter.ts @@ -3,7 +3,12 @@ import { Promise as bPromise } from 'bluebird' import { Contract, Signer, providers } from 'ethers' import { TransactionReceipt } from '@ethersproject/abstract-provider' import { getContractFactory } from 'old-contracts' -import { Logger, Bytes32, remove0x } from '@eth-optimism/core-utils' +import { + Logger, + Bytes32, + remove0x, + toRpcHexString, +} from '@eth-optimism/core-utils' /* Internal Imports */ import { L2Block } from '..' diff --git a/packages/batch-submitter/src/batch-submitter/tx-batch-submitter.ts b/packages/batch-submitter/src/batch-submitter/tx-batch-submitter.ts index 3df0b7cbf8a26..98ec83d6a8621 100644 --- a/packages/batch-submitter/src/batch-submitter/tx-batch-submitter.ts +++ b/packages/batch-submitter/src/batch-submitter/tx-batch-submitter.ts @@ -1,20 +1,13 @@ /* External Imports */ import { Promise as bPromise } from 'bluebird' -import { BigNumber, Signer, ethers, Wallet, Contract, providers } from 'ethers' +import { Signer, ethers, Contract, providers } from 'ethers' import { TransactionResponse, TransactionReceipt, } from '@ethersproject/abstract-provider' import { getContractInterface, getContractFactory } from 'old-contracts' import { getContractInterface as getNewContractInterface } from '@eth-optimism/contracts' -import { - Logger, - EIP155TxData, - TxType, - ctcCoder, - EthSignTxData, - txTypePlainText, -} from '@eth-optimism/core-utils' +import { Logger, ctcCoder } from '@eth-optimism/core-utils' /* Internal Imports */ import { @@ -24,13 +17,7 @@ import { AppendSequencerBatchParams, } from '../transaction-chain-contract' -import { - L2Block, - BatchElement, - Batch, - QueueOrigin, - queueOriginPlainText, -} from '..' +import { L2Block, BatchElement, Batch, QueueOrigin } from '..' import { RollupInfo, Range, BatchSubmitter, BLOCK_OFFSET } from '.' export interface AutoFixBatchOptions { @@ -602,41 +589,11 @@ export class TransactionBatchSubmitter extends BatchSubmitter { queueElementBlockNumber: queueElement.blockNumber, } ) - // This implies that we've double played a deposit. - // We can correct this by instead submitting a dummy sequencer tx - const wallet = Wallet.createRandom() - const gasLimit = 8_000_000 - const gasPrice = 0 - const chainId = 10 - const nonce = 0 - const rawTx = await wallet.signTransaction({ - gasLimit, - gasPrice, - chainId, - nonce, - to: '0x1111111111111111111111111111111111111111', - data: '0x1234', - }) - // 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: string = '0x1234' return { stateRoot: queueElement.stateRoot, isSequencerTx: true, - sequencerTxType: TxType.EIP155, - txData: dummyTx, + rawTransaction: dummyTx, timestamp: queueElement.timestamp, blockNumber: queueElement.blockNumber, } @@ -715,17 +672,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 { @@ -742,67 +689,26 @@ export class TransactionBatchSubmitter extends BatchSubmitter { this.log.debug('Fetched L2 block', { block, }) - const txType = block.transactions[0].txType - 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, - } + const batchElement = { + stateRoot: block.stateRoot, + timestamp: block.timestamp, + blockNumber: block.transactions[0].l1BlockNumber, + isSequencerTx: false, + rawTransaction: undefined, } - } - private async _getBlock(blockNumber: number): Promise { - 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] - if (!block.transactions[0].l1BlockNumber) { - this.log.error('Current block missing l1BlockNumber', { - blockNumber, - block, - }) + if (this._isSequencerTx(block)) { + batchElement.isSequencerTx = true + batchElement.rawTransaction = block.transactions[0].rawTransaction } - 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 { + const p = this.l2Provider.getBlockWithTransactions(blockNumber) + return p as Promise } private _isSequencerTx(block: L2Block): boolean { diff --git a/packages/batch-submitter/src/index.ts b/packages/batch-submitter/src/index.ts index 57b48ce734982..e915fe036b086 100644 --- a/packages/batch-submitter/src/index.ts +++ b/packages/batch-submitter/src/index.ts @@ -1,3 +1,4 @@ export * from './batch-submitter' export * from './transaction-chain-contract' export * from './types' +export * from './utils' diff --git a/packages/batch-submitter/src/types.ts b/packages/batch-submitter/src/types.ts index f40bd9a5f09a3..1aea043612751 100644 --- a/packages/batch-submitter/src/types.ts +++ b/packages/batch-submitter/src/types.ts @@ -1,23 +1,12 @@ /* External Imports */ import { BlockWithTransactions, - Provider, TransactionResponse, } from '@ethersproject/abstract-provider' -/* Internal Imports */ -import { EIP155TxData, TxType } from '@eth-optimism/core-utils' - export enum QueueOrigin { - Sequencer = 0, - L1ToL2 = 1, -} - -export const queueOriginPlainText = { - 0: QueueOrigin.Sequencer, - 1: QueueOrigin.L1ToL2, - sequencer: QueueOrigin.Sequencer, - l1ToL2: QueueOrigin.L1ToL2, + Sequencer = 'sequencer', + L1ToL2 = 'l1', } /** @@ -27,8 +16,8 @@ export const queueOriginPlainText = { export interface L2Transaction extends TransactionResponse { l1BlockNumber: number l1TxOrigin: string - txType: number - queueOrigin: number + queueOrigin: string + rawTransaction: string } export interface L2Block extends BlockWithTransactions { @@ -43,8 +32,7 @@ export interface L2Block extends BlockWithTransactions { export interface BatchElement { stateRoot: string isSequencerTx: boolean - sequencerTxType: undefined | TxType - txData: undefined | EIP155TxData + rawTransaction: undefined | string timestamp: number blockNumber: number } diff --git a/packages/batch-submitter/test/batch-submitter/batch-submitter.spec.ts b/packages/batch-submitter/test/batch-submitter/batch-submitter.spec.ts index 5af11a2f031dd..761307b867595 100644 --- a/packages/batch-submitter/test/batch-submitter/batch-submitter.spec.ts +++ b/packages/batch-submitter/test/batch-submitter/batch-submitter.spec.ts @@ -247,18 +247,9 @@ describe('BatchSubmitter', () => { const nextQueueElement = await getQueueElement( OVM_CanonicalTransactionChain ) - const data = ctcCoder.eip155TxData.encode({ - sig: DUMMY_SIG, - gasLimit: 0, - gasPrice: 0, - nonce: 0, - target: DUMMY_ADDRESS, - data: '0x', - type: TxType.EIP155, - }) l2Provider.setL2BlockData( { - data, + rawTransaction: '0x1234', l1BlockNumber: nextQueueElement.blockNumber - 1, txType: TxType.EIP155, queueOrigin: QueueOrigin.Sequencer, @@ -305,18 +296,9 @@ describe('BatchSubmitter', () => { OVM_CanonicalTransactionChain, 2 ) - const data = ctcCoder.ethSignTxData.encode({ - sig: DUMMY_SIG, - gasLimit: 0, - gasPrice: 0, - nonce: 0, - target: DUMMY_ADDRESS, - data: '0x', - type: TxType.EthSign, - }) l2Provider.setL2BlockData( { - data, + rawTransaction: '0x1234', l1BlockNumber: nextQueueElement.blockNumber - 1, txType: TxType.EthSign, queueOrigin: QueueOrigin.Sequencer, @@ -418,18 +400,9 @@ describe('BatchSubmitter', () => { const nextQueueElement = await getQueueElement( OVM_CanonicalTransactionChain ) - const data = ctcCoder.eip155TxData.encode({ - sig: DUMMY_SIG, - gasLimit: 0, - gasPrice: 0, - nonce: 0, - target: DUMMY_ADDRESS, - data: '0x', - type: TxType.EIP155, - }) l2Provider.setL2BlockData( { - data, + rawTransaction: '0x1234', l1BlockNumber: nextQueueElement.blockNumber - 1, txType: TxType.EIP155, queueOrigin: QueueOrigin.Sequencer, diff --git a/packages/batch-submitter/test/batch-submitter/mockchain-provider.ts b/packages/batch-submitter/test/batch-submitter/mockchain-provider.ts index 62f3de3eb7bd9..e50315c46446f 100644 --- a/packages/batch-submitter/test/batch-submitter/mockchain-provider.ts +++ b/packages/batch-submitter/test/batch-submitter/mockchain-provider.ts @@ -1,5 +1,5 @@ /* External Imports */ -import { providers } from 'ethers' +import { providers, BigNumber } from 'ethers' import { BlockWithTransactions, TransactionResponse, @@ -18,6 +18,7 @@ interface UnformattedL2Transaction extends TransactionResponse { l1MessageSender: string signatureHashType: string queueOrigin: string + rawTransaction: string } interface UnformattedL2Block extends BlockWithTransactions { @@ -60,25 +61,32 @@ export class MockchainProvider extends providers.JsonRpcProvider { } public async send(endpoint: string, params: []): Promise { - if (endpoint === 'eth_chainId') { - return this.chainId() + 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 as any)[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 { @@ -119,13 +127,12 @@ export class MockchainProvider extends providers.JsonRpcProvider { block.transactions[0].l1BlockNumber, 10 ) - const queueOrigin: number = parseInt(block.transactions[0].queueOrigin, 10) + const queueOrigin: string = block.transactions[0].queueOrigin const l1TxOrigin: string = block.transactions[0].l1MessageSender const l2Transaction: L2Transaction = { ...block.transactions[0], // Rename the incorrectly named fields l1TxOrigin, - txType, queueOrigin, l1BlockNumber, } @@ -209,8 +216,9 @@ const BLOCKS = JSON.parse(` "creates":"0xA193E42526F1FEA8C99AF609dcEabf30C1c29fAA", "l1BlockNumber":"1", "l1TxOrigin":"0x3333333333333333333333333333333333333333", + "rawTransaction":"0x420420", "signatureHashType":"0", - "queueOrigin":"0", + "queueOrigin":"sequencer", "chainId":31337 } ] @@ -261,8 +269,9 @@ const BLOCKS = JSON.parse(` "creates":null, "l1BlockNumber":"1", "l1TxOrigin":"0x3333333333333333333333333333333333333333", + "rawTransaction":"0x420420", "signatureHashType":"0", - "queueOrigin":"0", + "queueOrigin":"sequencer", "chainId":31337 } ] @@ -313,8 +322,9 @@ const BLOCKS = JSON.parse(` "creates":null, "l1BlockNumber":"1", "l1TxOrigin":"0x3333333333333333333333333333333333333333", + "rawTransaction":"0x420420", "signatureHashType":"0", - "queueOrigin":"0", + "queueOrigin":"sequencer", "chainId":31337 } ] @@ -365,8 +375,9 @@ const BLOCKS = JSON.parse(` "creates":"0x94BA4d5Ebb0e05A50e977FFbF6e1a1Ee3D89299c", "l1BlockNumber":"1", "l1TxOrigin":"0x3333333333333333333333333333333333333333", + "rawTransaction":"0x420420", "signatureHashType":"0", - "queueOrigin":"0", + "queueOrigin":"sequencer", "chainId":31337 } ] @@ -417,8 +428,9 @@ const BLOCKS = JSON.parse(` "creates":null, "l1BlockNumber":"1", "l1TxOrigin":"0x3333333333333333333333333333333333333333", + "rawTransaction":"0x420420", "signatureHashType":"0", - "queueOrigin":"0", + "queueOrigin":"sequencer", "chainId":31337 } ] @@ -469,8 +481,9 @@ const BLOCKS = JSON.parse(` "creates":null, "l1BlockNumber":"1", "l1TxOrigin":"0x3333333333333333333333333333333333333333", + "rawTransaction":"0x420420", "signatureHashType":"0", - "queueOrigin":"0", + "queueOrigin":"sequencer", "chainId":31337 } ] @@ -521,8 +534,9 @@ const BLOCKS = JSON.parse(` "creates":"0x956dA338C1518a7FB213042b70c60c021aeBd554", "l1BlockNumber":"1", "l1TxOrigin":"0x3333333333333333333333333333333333333333", + "rawTransaction":"0x420420", "signatureHashType":"0", - "queueOrigin":"0", + "queueOrigin":"sequencer", "chainId":31337 } ] @@ -573,8 +587,9 @@ const BLOCKS = JSON.parse(` "creates":null, "l1BlockNumber":"1", "l1TxOrigin":"0x3333333333333333333333333333333333333333", + "rawTransaction":"0x420420", "signatureHashType":"0", - "queueOrigin":"0", + "queueOrigin":"sequencer", "chainId":31337 } ] @@ -625,8 +640,9 @@ const BLOCKS = JSON.parse(` "creates":null, "l1BlockNumber":"1", "l1TxOrigin":"0x3333333333333333333333333333333333333333", + "rawTransaction":"0x420420", "signatureHashType":"0", - "queueOrigin":"0", + "queueOrigin":"sequencer", "chainId":31337 } ] @@ -677,8 +693,9 @@ const BLOCKS = JSON.parse(` "creates":"0x6454C9d69a4721feBA60e26A367bD4D56196Ee7c", "l1BlockNumber":"1", "l1TxOrigin":"0x3333333333333333333333333333333333333333", + "rawTransaction":"0x420420", "signatureHashType":"0", - "queueOrigin":"0", + "queueOrigin":"sequencer", "chainId":31337 } ] @@ -729,8 +746,9 @@ const BLOCKS = JSON.parse(` "creates":null, "l1BlockNumber":"1", "l1TxOrigin":"0x3333333333333333333333333333333333333333", + "rawTransaction":"0x420420", "signatureHashType":"0", - "queueOrigin":"0", + "queueOrigin":"sequencer", "chainId":31337 } ] @@ -781,8 +799,9 @@ const BLOCKS = JSON.parse(` "creates":null, "l1BlockNumber":"1", "l1TxOrigin":"0x3333333333333333333333333333333333333333", + "rawTransaction":"0x420420", "signatureHashType":"0", - "queueOrigin":"0", + "queueOrigin":"sequencer", "chainId":31337 } ] @@ -833,8 +852,9 @@ const BLOCKS = JSON.parse(` "creates":null, "l1BlockNumber":"1", "l1TxOrigin":"0x3333333333333333333333333333333333333333", + "rawTransaction":"0x420420", "signatureHashType":"0", - "queueOrigin":"0", + "queueOrigin":"sequencer", "chainId":31337 } ] @@ -885,8 +905,9 @@ const BLOCKS = JSON.parse(` "creates":null, "l1BlockNumber":"1", "l1TxOrigin":"0x3333333333333333333333333333333333333333", + "rawTransaction":"0x420420", "signatureHashType":"0", - "queueOrigin":"0", + "queueOrigin":"sequencer", "chainId":31337 } ] @@ -937,8 +958,9 @@ const BLOCKS = JSON.parse(` "creates":null, "l1BlockNumber":"1", "l1TxOrigin":"0x3333333333333333333333333333333333333333", + "rawTransaction":"0x420420", "signatureHashType":"0", - "queueOrigin":"0", + "queueOrigin":"sequencer", "chainId":31337 } ] diff --git a/packages/core-utils/src/l2context.ts b/packages/core-utils/src/l2context.ts index 06f7853e368ea..0fe7f771b7ebb 100644 --- a/packages/core-utils/src/l2context.ts +++ b/packages/core-utils/src/l2context.ts @@ -33,6 +33,7 @@ export const injectL2Context = (l1Provider: providers.JsonRpcProvider) => { b.transactions[i].l1TxOrigin = block.transactions[i].l1TxOrigin b.transactions[i].txType = block.transactions[i].txType b.transactions[i].queueOrigin = block.transactions[i].queueOrigin + b.transactions[i].rawTransaction = block.transactions[i].rawTransaction } return b }