Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {

/* Internal Imports */
import { L1DataService } from '../../../types/data'
import { BlockBatches, L2NodeService } from '../../../types'
import { GethSubmission, L2NodeService } from '../../../types'

const log = getLogger('l2-batch-submitter')

Expand All @@ -28,40 +28,38 @@ export class QueuedGethSubmitter extends ScheduledTask {
* @inheritDoc
*/
public async runTask(): Promise<void> {
let blockBatches: BlockBatches
let gethSubmission: GethSubmission
try {
blockBatches = await this.l1DataService.getNextQueuedGethSubmission()
gethSubmission = await this.l1DataService.getNextQueuedGethSubmission()
} catch (e) {
logError(log, `Error fetching next batch for L2 submission!`, e)
logError(log, `Error fetching next Geth Submission!`, e)
return
}

if (!blockBatches) {
log.debug(`No batches ready for submission to L2.`)
if (!gethSubmission) {
log.debug(`No Geth Submissions ready to be sent.`)
return
}

try {
await this.l2NodeService.sendBlockBatches(blockBatches)
await this.l2NodeService.sendGethSubmission(gethSubmission)
} catch (e) {
logError(
log,
`Error sending batch to BlockBatchSubmitter! Block Batches: ${JSON.stringify(
blockBatches
)}`,
`Error sending Geth Submission: ${JSON.stringify(gethSubmission)}`,
e
)
return
}

try {
await this.l1DataService.markQueuedGethSubmissionSubmittedToGeth(
blockBatches.batchNumber
gethSubmission.submissionNumber
)
} catch (e) {
logError(
log,
`Error marking L1 Batch as Submitted to L2. L1 Batch Number: ${blockBatches.batchNumber}`,
`Error marking Geth Submission submitted to Geth. L1 Batch Number: ${gethSubmission.submissionNumber}`,
e
)
return
Expand Down
71 changes: 35 additions & 36 deletions packages/rollup-core/src/app/data/data-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Block, TransactionResponse } from 'ethers/providers'

/* Internal Imports */
import {
BlockBatches,
GethSubmission,
DataService,
GethSubmissionQueueStatus,
TransactionBatchSubmission,
Expand Down Expand Up @@ -230,7 +230,7 @@ export class DefaultDataService implements DataService {
/**
* @inheritDoc
*/
public async getNextQueuedGethSubmission(): Promise<BlockBatches> {
public async getNextQueuedGethSubmission(): Promise<GethSubmission> {
const res: Row[] = await this.rdb.select(`
SELECT geth_submission_queue_index, target, calldata, block_timestamp, block_number, l1_tx_hash, l1_tx_index, l1_tx_log_index, queue_origin, sender, l1_message_sender, gas_limit, nonce, signature
FROM next_queued_geth_submission
Expand All @@ -245,41 +245,40 @@ export class DefaultDataService implements DataService {
const blockNumber = res[0]['block_number']

return {
batchNumber: gethSubmissionNumber,
submissionNumber: gethSubmissionNumber,
timestamp,
blockNumber,
batches: [
res.map((row: Row, indexWithinSubmission: number) => {
const tx: RollupTransaction = {
indexWithinSubmission,
l1TxHash: row['l1_tx_hash'],
l1TxIndex: row['l1_tx_index'],
l1TxLogIndex: row['l1_tx_log_index'],
target: row['target'],
calldata: row['calldata'], // TODO: may have to format Buffer => string
l1Timestamp: row['block_timestamp'],
l1BlockNumber: row['block_number'],
queueOrigin: row['queue_origin'],
}

if (!!row['sender']) {
tx.sender = row['sender']
}
if (!!row['l1MessageSender']) {
tx.l1MessageSender = row['l1_message_sender']
}
if (!!row['gas_limit']) {
tx.gasLimit = row['gas_limit']
}
if (!!row['nonce']) {
tx.nonce = row['nonce']
}
if (!!row['signature']) {
tx.nonce = row['signature']
}
return tx
}),
],
rollupTransactions: res.map((row: Row, indexWithinSubmission: number) => {
const tx: RollupTransaction = {
l1RollupTxId: parseInt(row['id'], 10),
Copy link
Contributor

Choose a reason for hiding this comment

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

Ah so adding the ID was basically trivial because we already had one assigned by the DB--that right?

Copy link
Author

@willmeister willmeister Jul 30, 2020

Choose a reason for hiding this comment

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

Yep, it's just a matter of slapping the DB's primary key onto the data structure.

indexWithinSubmission,
l1TxHash: row['l1_tx_hash'],
l1TxIndex: row['l1_tx_index'],
l1TxLogIndex: row['l1_tx_log_index'],
target: row['target'],
calldata: row['calldata'], // TODO: may have to format Buffer => string
l1Timestamp: row['block_timestamp'],
l1BlockNumber: row['block_number'],
queueOrigin: row['queue_origin'],
}

if (!!row['sender']) {
tx.sender = row['sender']
}
if (!!row['l1MessageSender']) {
tx.l1MessageSender = row['l1_message_sender']
}
if (!!row['gas_limit']) {
tx.gasLimit = row['gas_limit']
}
if (!!row['nonce']) {
tx.nonce = parseInt(row['nonce'], 10)
}
if (!!row['signature']) {
tx.nonce = row['signature']
}
return tx
}),
}
}

Expand Down Expand Up @@ -599,7 +598,7 @@ export class DefaultDataService implements DataService {
transactionHash: row['tx_hash'],
to: row['target'],
from: row['sender'],
nonce: row['nonce'],
nonce: parseInt(row['nonce'], 10),
calldata: row['calldata'],
stateRoot: row['state_root'],
gasPrice: row['gas_price'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ export class L2ChainDataPersister extends ChainDataProcessor {
if (!!response['l1MessageSender']) {
res.l1MessageSender = response['l1MessageSender']
}
if (!!response['l1RollupTxId']) {
res.l1RollupTransactionId = response['l1RollupTxId']
}
if (!!response.r && !!response.s && response.v !== undefined) {
res.signature = `${response.r}${remove0x(
response.s
Expand Down
42 changes: 28 additions & 14 deletions packages/rollup-core/src/app/l2-node-service.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
/* External Imports */
import { getLogger, Logger, numberToHexString } from '@eth-optimism/core-utils'
import {
getLogger,
Logger,
numberToHexString,
strToHexStr,
} from '@eth-optimism/core-utils'

import { JsonRpcProvider } from 'ethers/providers'
import { Wallet } from 'ethers'

/* Internal Imports */
import { BlockBatches, L2NodeService } from '../types'
import { GethSubmission, L2NodeService } from '../types'

const log: Logger = getLogger('block-batch-submitter')

export class DefaultL2NodeService implements L2NodeService {
// params: [blockBatchesJSONString, signedBlockBatchesJSONString]
// params: [gethSubmissionJSONString, signedGethSubmissionJSONString]
// -- note all numbers are replaces with hex strings when serialized
public static readonly sendBlockBatchesMethod: string = 'eth_sendBlockBatches'
public static readonly sendGethSubmission: string =
'eth_sendRollupTransactions'

private readonly l2Provider: JsonRpcProvider

Expand All @@ -23,29 +29,37 @@ export class DefaultL2NodeService implements L2NodeService {
/**
* @inheritDoc
*/
public async sendBlockBatches(blockBatches: BlockBatches): Promise<void> {
if (!blockBatches) {
const msg = `Received undefined Block Batch!.`
public async sendGethSubmission(
gethSubmission: GethSubmission
): Promise<void> {
if (!gethSubmission) {
const msg = `Received undefined Geth Submission!.`
log.error(msg)
throw msg
}

if (!blockBatches.batches || !blockBatches.batches.length) {
log.error(`Received empty block batch: ${JSON.stringify(blockBatches)}`)
if (
!gethSubmission.rollupTransactions ||
!gethSubmission.rollupTransactions.length
) {
log.error(
`Received empty Geth Submission: ${JSON.stringify(gethSubmission)}`
)
return
}

const payload = JSON.stringify(blockBatches, (k, v) => {
const payload = JSON.stringify(gethSubmission, (k, v) => {
if (typeof v === 'number') {
return v >= 0 ? numberToHexString(v) : undefined
}
return v
})

const signedPayload: string = await this.l2Wallet.signMessage(payload)
await this.l2Provider.send(DefaultL2NodeService.sendBlockBatchesMethod, [
payload,
signedPayload,
const hexPayload: string = strToHexStr(payload)
const signedPayload: string = await this.l2Wallet.signMessage(hexPayload)

await this.l2Provider.send(DefaultL2NodeService.sendGethSubmission, [
[hexPayload, signedPayload],
])
}
}
4 changes: 2 additions & 2 deletions packages/rollup-core/src/types/data/l1-data-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { Block, TransactionResponse } from 'ethers/providers'

/* Internal Imports */
import { BlockBatches, RollupTransaction } from '../types'
import { GethSubmission, RollupTransaction } from '../types'
import { GethSubmissionRecord } from './types'

export interface L1DataService {
Expand Down Expand Up @@ -88,7 +88,7 @@ export interface L1DataService {
*
* @returns The fetched Queued Geth Submission or undefined if one is not present in the DB.
*/
getNextQueuedGethSubmission(): Promise<BlockBatches>
getNextQueuedGethSubmission(): Promise<GethSubmission>

/**
* Marks the provided Queued Geth Submission as submitted to L2.
Expand Down
4 changes: 2 additions & 2 deletions packages/rollup-core/src/types/l2-node-service.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { BlockBatches } from './types'
import { GethSubmission } from './types'

export interface L2NodeService {
/**
* Sends the provided BlockBatches to the configured L2 node.
*
* @param blockBatches The block batches to send to L2
*/
sendBlockBatches(blockBatches: BlockBatches): Promise<void>
sendGethSubmission(blockBatches: GethSubmission): Promise<void>
}
19 changes: 4 additions & 15 deletions packages/rollup-core/src/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export interface L2ToL1Message {
}

export interface RollupTransaction {
l1RollupTxId?: number
indexWithinSubmission: number
target: Address
calldata: string
Expand Down Expand Up @@ -71,23 +72,11 @@ export interface LogHandlerContext {
handleLog: LogHandler
}

export type L1Batch = RollupTransaction[]
export interface BlockBatches {
batchNumber: number
export interface GethSubmission {
submissionNumber: number
timestamp: number
blockNumber: number
batches: L1Batch[]
}

export type L1BatchParser = (
l: Log,
transaction: TransactionResponse
) => Promise<L1Batch>

export interface BatchLogParserContext {
topic: string
contractAddress: Address
parseL1Batch: L1BatchParser
rollupTransactions: RollupTransaction[]
}

/* Types */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ const getTransactionResponse = (
value: undefined,
chainId: CHAIN_ID,
l1MessageSender: ZERO_ADDRESS,
l1RollupTxId: 1,
wait: (confirmations) => {
return undefined
},
Expand Down
Loading