Skip to content
This repository was archived by the owner on Apr 11, 2021. It is now read-only.
Open
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
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@ GAS_RETRY_INCREMENT=5
GAS_THRESHOLD_IN_GWEI=100

SEQUENCER_PRIVATE_KEY=0xd2ab07f7c10ac88d5f86f1b4c1035d5195e81f27dbe62ad65e59cbf88205629b

ITX_ENABLED=false
129 changes: 90 additions & 39 deletions src/batch-submitter/batch-submitter.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
/* External Imports */
import { Contract, Signer, utils } from 'ethers'
import {
TransactionReceipt,
} from '@ethersproject/abstract-provider'
import { TransactionReceipt } from '@ethersproject/abstract-provider'
import * as ynatm from '@eth-optimism/ynatm'
import { Address, Bytes32, Logger } from '@eth-optimism/core-utils'
import { Logger } from '@eth-optimism/core-utils'
import { OptimismProvider } from '@eth-optimism/provider'
import { getContractFactory } from '@eth-optimism/contracts'
import { JsonRpcProvider, TransactionRequest } from '@ethersproject/providers'
import { formatEther } from 'ethers/lib/utils'
import { itxWaitForTx, sendTxWithITX } from '../itx'

export interface RollupInfo {
mode: 'sequencer' | 'verifier'
Expand All @@ -25,9 +26,9 @@ export interface Range {
end: number
}
export interface ResubmissionConfig {
resubmissionTimeout: number,
minGasPriceInGwei: number,
maxGasPriceInGwei: number,
resubmissionTimeout: number
minGasPriceInGwei: number
maxGasPriceInGwei: number
Comment on lines +29 to +31
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Unrelated to the core functionality implemented here, but there seem to be quite a few stylistic changes made here (like the removal of commas above). We don't have a linting / formatting CI step yet (which we ought to soon hopefully). Absent that could you try to strip them from these commits?

gasRetryIncrement: number
}

Expand All @@ -54,6 +55,7 @@ export abstract class BatchSubmitter {
readonly maxGasPriceInGwei: number,
readonly gasRetryIncrement: number,
readonly gasThresholdInGwei: number,
readonly itxEnabled: boolean,
readonly log: Logger
) {}

Expand Down Expand Up @@ -94,7 +96,9 @@ export abstract class BatchSubmitter {

this.log.info(`Balance ${address}: ${ether} ether`)
if (num < this.minBalanceEther) {
this.log.error(`Current balance of ${num} lower than min safe balance of ${this.minBalanceEther}`)
this.log.error(
`Current balance of ${num} lower than min safe balance of ${this.minBalanceEther}`
)
}
}

Expand All @@ -106,7 +110,10 @@ export abstract class BatchSubmitter {
return this.l2Provider.send('eth_chainId', [])
}

protected async _getChainAddresses(): Promise<{ ctcAddress: string; sccAddress: string }> {
protected async _getChainAddresses(): Promise<{
ctcAddress: string
sccAddress: string
}> {
const addressManager = (
await getContractFactory('Lib_AddressManager', this.signer)
).attach(this.addressManagerAddress)
Expand All @@ -122,13 +129,15 @@ export abstract class BatchSubmitter {
}
}

protected _shouldSubmitBatch(
batchSizeInBytes: number
): boolean {
const isTimeoutReached = this.lastBatchSubmissionTimestamp + this.maxBatchSubmissionTime <= Date.now()
protected _shouldSubmitBatch(batchSizeInBytes: number): boolean {
const isTimeoutReached =
this.lastBatchSubmissionTimestamp + this.maxBatchSubmissionTime <=
Date.now()
if (batchSizeInBytes < this.minTxSize) {
if (!isTimeoutReached) {
this.log.info(`Batch is too small & max submission timeout not reached. Skipping batch submission...`)
this.log.info(
`Batch is too small & max submission timeout not reached. Skipping batch submission...`
)
return false
}
this.log.info(`Timeout reached.`)
Expand All @@ -139,22 +148,22 @@ export abstract class BatchSubmitter {
public static async getReceiptWithResubmission(
txFunc: (gasPrice) => Promise<TransactionReceipt>,
resubmissionConfig: ResubmissionConfig,
log: Logger,
log: Logger
): Promise<TransactionReceipt> {
const {
resubmissionTimeout,
minGasPriceInGwei,
maxGasPriceInGwei,
gasRetryIncrement
gasRetryIncrement,
} = resubmissionConfig

const receipt = await ynatm.send({
sendTransactionFunction: txFunc,
minGasPrice: ynatm.toGwei(minGasPriceInGwei),
maxGasPrice: ynatm.toGwei(maxGasPriceInGwei),
gasPriceScalingFunction: ynatm.LINEAR(gasRetryIncrement),
delay: resubmissionTimeout
});
sendTransactionFunction: txFunc,
minGasPrice: ynatm.toGwei(minGasPriceInGwei),
maxGasPrice: ynatm.toGwei(maxGasPriceInGwei),
gasPriceScalingFunction: ynatm.LINEAR(gasRetryIncrement),
delay: resubmissionTimeout,
})

log.debug('Resubmission tx receipt:', receipt)

Expand All @@ -166,37 +175,79 @@ export abstract class BatchSubmitter {
return this.minGasPriceInGwei
}
let minGasPriceInGwei = parseInt(
utils.formatUnits(await this.signer.getGasPrice(), 'gwei'), 10
utils.formatUnits(await this.signer.getGasPrice(), 'gwei'),
10
)
if (minGasPriceInGwei > this.maxGasPriceInGwei) {
this.log.warn('Minimum gas price is higher than max! Ethereum must be congested...')
this.log.warn(
'Minimum gas price is higher than max! Ethereum must be congested...'
)
minGasPriceInGwei = this.maxGasPriceInGwei
}
return minGasPriceInGwei
}

protected async _submitAndLogTx(
txFunc: (gasPrice) => Promise<TransactionReceipt>,
to: string,
data: string,
successMessage: string
): Promise<TransactionReceipt> {
this.lastBatchSubmissionTimestamp = Date.now()
this.log.debug('Waiting for receipt...')

const resubmissionConfig: ResubmissionConfig = {
resubmissionTimeout: this.resubmissionTimeout,
minGasPriceInGwei: await this._getMinGasPriceInGwei(),
maxGasPriceInGwei: this.maxGasPriceInGwei,
gasRetryIncrement: this.gasRetryIncrement
}
// Enable ITX by setting a provider. It'll re-use the sequencer key.
if (this.itxEnabled) {
// Only works if the Infura Provider is enabled for ITX.
const itx = this.signer.provider as JsonRpcProvider
const gas = await itx.estimateGas({ to, data })

const balance = await itx.send('relay_getBalance', [
await this.signer.getAddress(),
])
this.log.info(`Current ITX balance: ` + formatEther(balance))

const relayTransactionHash = await sendTxWithITX(
this.signer,
to,
data,
gas.toString()
)

const receipt = await BatchSubmitter.getReceiptWithResubmission(
txFunc,
resubmissionConfig,
this.log
)
this.log.info(`ITX relay transaction hash: ${relayTransactionHash}`)
const receipt = await itxWaitForTx(
itx,
relayTransactionHash,
this.numConfirmations
)
this.log.debug('Transaction receipt:', receipt)
this.log.info(successMessage)
return receipt
} else {
// Use the esclator algorithm by Optimism.
const sendTx = async (gasPrice): Promise<TransactionReceipt> => {
const tx = await this.signer.sendTransaction({ to, data, gasPrice })
return this.signer.provider.waitForTransaction(
tx.hash,
this.numConfirmations
)
}

this.log.debug('Transaction receipt:', receipt)
this.log.info(successMessage)
return receipt
const resubmissionConfig: ResubmissionConfig = {
resubmissionTimeout: this.resubmissionTimeout,
minGasPriceInGwei: await this._getMinGasPriceInGwei(),
maxGasPriceInGwei: this.maxGasPriceInGwei,
gasRetryIncrement: this.gasRetryIncrement,
}

const receipt = await BatchSubmitter.getReceiptWithResubmission(
sendTx,
resubmissionConfig,
this.log
)

this.log.debug('Transaction receipt:', receipt)
this.log.info(successMessage)
return receipt
}
}
}
20 changes: 11 additions & 9 deletions src/batch-submitter/state-batch-submitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export class StateBatchSubmitter extends BatchSubmitter {
maxGasPriceInGwei: number,
gasRetryIncrement: number,
gasThresholdInGwei: number,
itxEnabled: boolean,
log: Logger,
fraudSubmissionAddress: string
) {
Expand All @@ -54,6 +55,7 @@ export class StateBatchSubmitter extends BatchSubmitter {
maxGasPriceInGwei,
gasRetryIncrement,
gasThresholdInGwei,
itxEnabled,
log
)
this.fraudSubmissionAddress = fraudSubmissionAddress
Expand Down Expand Up @@ -92,7 +94,9 @@ export class StateBatchSubmitter extends BatchSubmitter {
).attach(ctcAddress)

this.log.info(`Using State Commitment Chain: ${this.chainContract.address}`)
this.log.info(`Using Canonical Transaction Chain: ${this.ctcContract.address}`)
this.log.info(
`Using Canonical Transaction Chain: ${this.ctcContract.address}`
)
return
}

Expand Down Expand Up @@ -146,15 +150,13 @@ export class StateBatchSubmitter extends BatchSubmitter {

const offsetStartsAtIndex = startBlock - BLOCK_OFFSET // TODO: Remove BLOCK_OFFSET by adding a tx to Geth's genesis
this.log.debug('Submitting batch. Tx:', tx)
const contractFunction = async (gasPrice): Promise<TransactionReceipt> => {
const contractTx = await this.chainContract.appendStateBatch(batch, offsetStartsAtIndex, {gasPrice})
return this.signer.provider.waitForTransaction(
contractTx.hash,
this.numConfirmations
)
}

return this._submitAndLogTx(
contractFunction,
this.chainContract.address,
this.chainContract.interface.encodeFunctionData('appendStateBatch', [
batch,
offsetStartsAtIndex,
]),
'Submitted state root batch!'
)
}
Expand Down
Loading