diff --git a/packages/batch-submitter/src/batch-submitter/batch-submitter.ts b/packages/batch-submitter/src/batch-submitter/batch-submitter.ts index 2d28837c2076..fd29c064d3eb 100644 --- a/packages/batch-submitter/src/batch-submitter/batch-submitter.ts +++ b/packages/batch-submitter/src/batch-submitter/batch-submitter.ts @@ -69,6 +69,10 @@ export abstract class BatchSubmitter { } await this._updateChainInfo() await this._checkBalance() + this.log.info('Readying to submit next batch...', { + l2ChainId: this.l2ChainId, + batchSubmitterAddress: await this.signer.getAddress(), + }) if (this.syncing === true) { this.log.info( @@ -225,7 +229,7 @@ export abstract class BatchSubmitter { this.log ) - this.log.debug('Transaction receipt:', { receipt }) + this.log.info('Received transaction receipt', { receipt }) this.log.info(successMessage) return receipt } 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 e3273c044c33..3fbdc1829701 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,7 @@ import { Promise as bPromise } from 'bluebird' import { Contract, Signer } from 'ethers' import { TransactionReceipt } from '@ethersproject/abstract-provider' import { getContractFactory } from '@eth-optimism/contracts' -import { Logger, Bytes32 } from '@eth-optimism/core-utils' +import { Logger, Bytes32, remove0x } from '@eth-optimism/core-utils' import { OptimismProvider } from '@eth-optimism/provider' /* Internal Imports */ @@ -82,6 +82,10 @@ export class StateBatchSubmitter extends BatchSubmitter { sccAddress === this.chainContract.address && ctcAddress === this.ctcContract.address ) { + this.log.debug('Chain contract already initialized', { + sccAddress, + ctcAddress, + }) return } @@ -105,12 +109,21 @@ export class StateBatchSubmitter extends BatchSubmitter { } public async _getBatchStartAndEnd(): Promise { + this.log.info('Getting batch start and end for state batch submitter...') // TODO: Remove BLOCK_OFFSET by adding a tx to Geth's genesis const startBlock: number = (await this.chainContract.getTotalElements()).toNumber() + BLOCK_OFFSET + this.log.info('Retrieved start block number from SCC', { + startBlock, + }) + // We will submit state roots for txs which have been in the tx chain for a while. const totalElements: number = (await this.ctcContract.getTotalElements()).toNumber() + BLOCK_OFFSET + this.log.info('Retrieved total elements from CTC', { + totalElements, + }) + const endBlock: number = Math.min( startBlock + this.maxBatchSize, totalElements @@ -142,7 +155,13 @@ export class StateBatchSubmitter extends BatchSubmitter { 'appendStateBatch', [batch, startBlock] ) - if (!this._shouldSubmitBatch(tx.length / 2)) { + const batchSizeInBytes = remove0x(tx).length / 2 + this.log.debug('State batch generated', { + batchSizeInBytes, + tx, + }) + + if (!this._shouldSubmitBatch(batchSizeInBytes)) { return } @@ -156,6 +175,13 @@ export class StateBatchSubmitter extends BatchSubmitter { offsetStartsAtIndex, { nonce, gasPrice } ) + this.log.info('Submitted appendStateBatch transaction', { + nonce, + txHash: contractTx.hash, + contractAddr: this.chainContract.address, + from: contractTx.from, + data: contractTx.data, + }) return this.signer.provider.waitForTransaction( contractTx.hash, this.numConfirmations @@ -180,7 +206,12 @@ export class StateBatchSubmitter extends BatchSubmitter { const block = (await this.l2Provider.getBlockWithTransactions( startBlock + i )) as L2Block - if (block.transactions[0].from === this.fraudSubmissionAddress) { + const blockTx = block.transactions[0] + if (blockTx.from === this.fraudSubmissionAddress) { + this.log.warn('Found transaction from fraud submission address', { + txHash: blockTx.hash, + fraudSubmissionAddress: this.fraudSubmissionAddress, + }) this.fraudSubmissionAddress = 'no fraud' return '0xbad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1bad1' } @@ -193,14 +224,20 @@ export class StateBatchSubmitter extends BatchSubmitter { 'appendStateBatch', [batch, startBlock] ) - while (tx.length > this.maxTxSize) { + while (remove0x(tx).length / 2 > this.maxTxSize) { batch.splice(Math.ceil((batch.length * 2) / 3)) // Delete 1/3rd of all of the batch elements + this.log.debug('Splicing batch...', { + batchSizeInBytes: tx.length / 2, + }) tx = this.chainContract.interface.encodeFunctionData('appendStateBatch', [ batch, startBlock, ]) } + this.log.info('Generated state commitment batch', { + batch, // list of stateRoots + }) return batch } } 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 8193cb8924de..61bdd4d55c2f 100644 --- a/packages/batch-submitter/src/batch-submitter/tx-batch-submitter.ts +++ b/packages/batch-submitter/src/batch-submitter/tx-batch-submitter.ts @@ -114,6 +114,9 @@ export class TransactionBatchSubmitter extends BatchSubmitter { typeof this.chainContract !== 'undefined' && ctcAddress === this.chainContract.address ) { + this.log.debug('Chain contract already initialized', { + ctcAddress, + }) return } @@ -134,6 +137,9 @@ export class TransactionBatchSubmitter extends BatchSubmitter { public async _onSync(): Promise { const pendingQueueElements = await this.chainContract.getNumPendingQueueElements() + this.log.debug('Got number of pending queue elements', { + pendingQueueElements, + }) if (pendingQueueElements !== 0) { this.log.info( @@ -150,6 +156,13 @@ export class TransactionBatchSubmitter extends BatchSubmitter { nonce, gasPrice, }) + this.log.info('Submitted appendQueueBatch transaction', { + nonce, + txHash: tx.hash, + contractAddr: this.chainContract.address, + from: tx.from, + data: tx.data, + }) return this.signer.provider.waitForTransaction( tx.hash, this.numConfirmations @@ -166,6 +179,7 @@ export class TransactionBatchSubmitter extends BatchSubmitter { // TODO: Remove this function and use geth for lastL1BlockNumber! private async _updateLastL1BlockNumber() { + this.log.warn('Calling _updateLastL1BlockNumber...') const pendingQueueElements = await this.chainContract.getNumPendingQueueElements() if (pendingQueueElements !== 0) { @@ -187,17 +201,32 @@ export class TransactionBatchSubmitter extends BatchSubmitter { } } } + + this.log.debug('Set lastL1BlockNumber', { + lastL1BlockNumber: this.lastL1BlockNumber, + }) } public async _getBatchStartAndEnd(): Promise { + this.log.info( + 'Getting batch start and end for transaction batch submitter...' + ) // TODO: Remove BLOCK_OFFSET by adding a tx to Geth's genesis const startBlock = (await this.chainContract.getTotalElements()).toNumber() + BLOCK_OFFSET + this.log.info('Retrieved start block number from CTC', { + startBlock, + }) + const endBlock = Math.min( startBlock + this.maxBatchSize, await this.l2Provider.getBlockNumber() ) + 1 // +1 because the `endBlock` is *exclusive* + this.log.info('Retrieved end block number from L2 sequencer', { + endBlock, + }) + if (startBlock >= endBlock) { if (startBlock > endBlock) { this.log @@ -224,7 +253,7 @@ export class TransactionBatchSubmitter extends BatchSubmitter { ) if (gasPriceInGwei > this.gasThresholdInGwei) { this.log.warn( - 'Gas price is higher than gras price threshold; aborting batch submission', + 'Gas price is higher than gas price threshold; aborting batch submission', { gasPriceInGwei, gasThresholdInGwei: this.gasThresholdInGwei, @@ -238,6 +267,9 @@ export class TransactionBatchSubmitter extends BatchSubmitter { wasBatchTruncated, ] = await this._generateSequencerBatchParams(startBlock, endBlock) const batchSizeInBytes = encodeAppendSequencerBatch(batchParams).length / 2 + this.log.debug('Sequencer batch generated', { + batchSizeInBytes, + }) // Only submit batch if one of the following is true: // 1. it was truncated @@ -256,6 +288,13 @@ export class TransactionBatchSubmitter extends BatchSubmitter { nonce, gasPrice, }) + this.log.info('Submitted appendSequencerBatch transaction', { + nonce, + txHash: tx.hash, + contractAddr: this.chainContract.address, + from: tx.from, + data: tx.data, + }) return this.signer.provider.waitForTransaction( tx.hash, this.numConfirmations @@ -299,6 +338,9 @@ export class TransactionBatchSubmitter extends BatchSubmitter { let wasBatchTruncated = false let encoded = encodeAppendSequencerBatch(sequencerBatchParams) while (encoded.length / 2 > this.maxTxSize) { + this.log.debug('Splicing batch...', { + batchSizeInBytes: encoded.length / 2, + }) batch.splice(Math.ceil((batch.length * 2) / 3)) // Delete 1/3rd of all of the batch elements sequencerBatchParams = await this._getSequencerBatchParams( startBlock, @@ -310,6 +352,12 @@ export class TransactionBatchSubmitter extends BatchSubmitter { // In this case, we want to submit regardless of the batch's size. wasBatchTruncated = true } + + this.log.info('Generated sequencer batch params', { + contexts: sequencerBatchParams.contexts, + transactions: sequencerBatchParams.transactions, + wasBatchTruncated, + }) return [sequencerBatchParams, wasBatchTruncated] } @@ -421,6 +469,7 @@ export class TransactionBatchSubmitter extends BatchSubmitter { // TODO: Remove this super complex logic and rely on Geth to actually supply correct block data. const fixMonotonicity = async (b: Batch): Promise => { + this.log.debug('Fixing monotonicity...') // The earliest allowed timestamp/blockNumber is the last timestamp submitted on chain. const { lastTimestamp, @@ -428,6 +477,10 @@ export class TransactionBatchSubmitter extends BatchSubmitter { } = await this._getLastTimestampAndBlockNumber() let earliestTimestamp = lastTimestamp let earliestBlockNumber = lastBlockNumber + this.log.debug('Determined earliest timestamp and blockNumber', { + earliestTimestamp, + earliestBlockNumber, + }) // The latest allowed timestamp/blockNumber is the next queue element! let nextQueueIndex = await this.chainContract.getNextQueueIndex() @@ -457,6 +510,10 @@ export class TransactionBatchSubmitter extends BatchSubmitter { } // Actually update the latest timestamp and block number await updateLatestTimestampAndBlockNumber() + this.log.debug('Determined latest timestamp and blockNumber', { + latestTimestamp, + latestBlockNumber, + }) // Now go through our batch and fix the timestamps and block numbers // to automatically enforce monotonicity. @@ -573,7 +630,13 @@ export class TransactionBatchSubmitter extends BatchSubmitter { blockNumber > queueElement.blockNumber ) { this.log.warn( - 'Double deposit detected!!! Fixing by skipping the deposit & replacing with a dummy tx.' + 'Double deposit detected. Fixing by skipping the deposit & replacing with a dummy tx.', + { + timestamp, + blockNumber, + queueElementTimestamp: queueElement.timestamp, + queueElementBlockNumber: queueElement.blockNumber, + } ) // This implies that we've double played a deposit. // We can correct this by instead submitting a dummy sequencer tx @@ -712,6 +775,9 @@ export class TransactionBatchSubmitter extends BatchSubmitter { private async _getL2BatchElement(blockNumber: number): Promise { const block = await this._getBlock(blockNumber) + this.log.debug('Fetched L2 block', { + block, + }) const txType = block.transactions[0].txType if (this._isSequencerTx(block)) { @@ -744,6 +810,7 @@ export class TransactionBatchSubmitter extends BatchSubmitter { if (!block.transactions[0].l1BlockNumber) { block.transactions[0].l1BlockNumber = this.lastL1BlockNumber } + return block } diff --git a/packages/batch-submitter/src/exec/run-batch-submitter.ts b/packages/batch-submitter/src/exec/run-batch-submitter.ts index 1c6b09153868..40c717142b3d 100644 --- a/packages/batch-submitter/src/exec/run-batch-submitter.ts +++ b/packages/batch-submitter/src/exec/run-batch-submitter.ts @@ -201,9 +201,12 @@ export const run = async () => { value: 0, nonce: i, }) - log.info('Submitting empty transaction', { + log.info('Submitted empty transaction', { nonce: i, txHash: response.hash, + to: response.to, + from: response.from, + data: response.data, }) await sequencerSigner.provider.waitForTransaction( response.hash, diff --git a/packages/batch-submitter/src/index.ts b/packages/batch-submitter/src/index.ts index ebeeed3d6608..57b48ce73498 100644 --- a/packages/batch-submitter/src/index.ts +++ b/packages/batch-submitter/src/index.ts @@ -1,4 +1,3 @@ export * from './batch-submitter' -export * from './utils' export * from './transaction-chain-contract' export * from './types' diff --git a/packages/batch-submitter/src/transaction-chain-contract.ts b/packages/batch-submitter/src/transaction-chain-contract.ts index 78b3202a838f..1eae53d95726 100644 --- a/packages/batch-submitter/src/transaction-chain-contract.ts +++ b/packages/batch-submitter/src/transaction-chain-contract.ts @@ -5,11 +5,11 @@ import { TransactionRequest, } from '@ethersproject/abstract-provider' import { keccak256 } from 'ethers/lib/utils' -import { remove0x, encodeHex } from './utils' import { AppendSequencerBatchParams, BatchContext, encodeAppendSequencerBatch, + encodeHex, } from '@eth-optimism/core-utils' export { encodeAppendSequencerBatch, BatchContext, AppendSequencerBatchParams } diff --git a/packages/contracts/scripts/build.sh b/packages/contracts/scripts/build.sh index b30a72af4ad3..cda148fc6d93 100755 --- a/packages/contracts/scripts/build.sh +++ b/packages/contracts/scripts/build.sh @@ -1,2 +1,3 @@ -yarn run build:typescript & yarn run build:contracts & yarn run build:contracts:ovm +yarn run build:typescript & yarn run build:contracts +yarn run build:contracts:ovm yarn run build:copy:artifacts & yarn run build:copy:artifacts:ovm & yarn run build:copy:contracts diff --git a/packages/hardhat-ovm/src/index.ts b/packages/hardhat-ovm/src/index.ts index 991da2d56758..f87da86b63de 100644 --- a/packages/hardhat-ovm/src/index.ts +++ b/packages/hardhat-ovm/src/index.ts @@ -75,8 +75,20 @@ const getOvmSolcPath = async (version: string): Promise => { subtask( TASK_COMPILE_SOLIDITY_RUN_SOLC, async (args: { input: any; solcPath: string }, hre, runSuper) => { + const ignoreRxList = hre.network.config.ignoreRxList || []; + const ignore = (filename: string) => ignoreRxList.reduce((ignored: boolean, rx: string | RegExp) => ignored || new RegExp(rx).test(filename), false); if (hre.network.ovm !== true) { - return runSuper(args) + // Separate the EVM and OVM inputs. + for (const file of Object.keys(args.input.sources)) { + // Ignore any contract that has this tag or in ignore list + if (args.input.sources[file].content.includes('// @unsupported: evm') || ignore(file)) { + delete args.input.sources[file]; + } + else { + //console.log(file + ' included'); + } + } + return runSuper(args) } // Just some silly sanity checks, make sure we have a solc version to download. Our format is @@ -101,8 +113,8 @@ subtask( // Separate the EVM and OVM inputs. for (const file of Object.keys(args.input.sources)) { - // Ignore any contract that has this tag. - if (!args.input.sources[file].content.includes('// @unsupported: ovm')) { + // Ignore any contract that has this tag or in ignore list + if (!args.input.sources[file].content.includes('// @unsupported: ovm') && !ignore(file)) { ovmInput.sources[file] = args.input.sources[file] } } @@ -141,8 +153,8 @@ extendEnvironment((hre) => { } // Forcibly update the artifacts object. - hre.config.paths.artifacts = artifactsPath - hre.config.paths.cache = cachePath - ;(hre as any).artifacts = new Artifacts(artifactsPath) + hre.config.paths.artifacts = artifactsPath; + hre.config.paths.cache = cachePath; + (hre as any).artifacts = new Artifacts(artifactsPath); } }) diff --git a/packages/hardhat-ovm/src/type-extensions.ts b/packages/hardhat-ovm/src/type-extensions.ts index c725d503fa91..dd28c766e992 100644 --- a/packages/hardhat-ovm/src/type-extensions.ts +++ b/packages/hardhat-ovm/src/type-extensions.ts @@ -14,24 +14,31 @@ declare module 'hardhat/types/config' { } interface HardhatNetworkUserConfig { - ovm?: boolean + ovm?: boolean; + ignoreRxList?: string[]; } interface HttpNetworkUserConfig { - ovm?: boolean + ovm?: boolean; + ignoreRxList?: string[]; } + interface HardhatNetworkConfig { - ovm: boolean + ovm: boolean; + ignoreRxList: string[]; } interface HttpNetworkConfig { - ovm: boolean + ovm: boolean; + ignoreRxList: string[]; } } + declare module 'hardhat/types/runtime' { interface Network { - ovm: boolean + ovm: boolean; + ignoreRxList: string[]; } }