From 660a1fa97053d020dbf4ee19344b39dd16296a63 Mon Sep 17 00:00:00 2001 From: Annie Ke Date: Fri, 9 Apr 2021 09:06:38 -0700 Subject: [PATCH] Adding logs to batch submitters (#73) * Add logs to tx batch submitter * improve state batch submitter logs and fix bug * remove utils --- src/batch-submitter/batch-submitter.ts | 6 +- src/batch-submitter/state-batch-submitter.ts | 45 +++++++++++-- src/batch-submitter/tx-batch-submitter.ts | 69 +++++++++++++++++++- src/exec/run-batch-submitter.ts | 5 +- src/index.ts | 1 - src/transaction-chain-contract.ts | 2 +- src/utils.ts | 23 ------- 7 files changed, 119 insertions(+), 32 deletions(-) delete mode 100644 src/utils.ts diff --git a/src/batch-submitter/batch-submitter.ts b/src/batch-submitter/batch-submitter.ts index 39e010f..0c7955f 100644 --- a/src/batch-submitter/batch-submitter.ts +++ b/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/src/batch-submitter/state-batch-submitter.ts b/src/batch-submitter/state-batch-submitter.ts index e3273c0..3fbdc18 100644 --- a/src/batch-submitter/state-batch-submitter.ts +++ b/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/src/batch-submitter/tx-batch-submitter.ts b/src/batch-submitter/tx-batch-submitter.ts index 8193cb8..2cd3293 100644 --- a/src/batch-submitter/tx-batch-submitter.ts +++ b/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 @@ -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/src/exec/run-batch-submitter.ts b/src/exec/run-batch-submitter.ts index 1c6b091..40c7171 100644 --- a/src/exec/run-batch-submitter.ts +++ b/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/src/index.ts b/src/index.ts index ebeeed3..57b48ce 100644 --- a/src/index.ts +++ b/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/src/transaction-chain-contract.ts b/src/transaction-chain-contract.ts index 78b3202..1eae53d 100644 --- a/src/transaction-chain-contract.ts +++ b/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/src/utils.ts b/src/utils.ts deleted file mode 100644 index c7f4c8a..0000000 --- a/src/utils.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* External Imports */ -import { BigNumber } from 'ethers' - -export const getLen = (pos: { start; end }) => (pos.end - pos.start) * 2 - -export const encodeHex = (val: any, len: number) => - remove0x(BigNumber.from(val).toHexString()).padStart(len, '0') - -export const toVerifiedBytes = (val: string, len: number) => { - val = remove0x(val) - if (val.length !== len) { - throw new Error('Invalid length!') - } - return val -} - -export const remove0x = (str: string): string => { - if (str.startsWith('0x')) { - return str.slice(2) - } else { - return str - } -}