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
5 changes: 5 additions & 0 deletions .changeset/smart-readers-remember.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@eth-optimism/sdk': patch
---

Fixes a bug in the SDK which would cause the SDK to throw if no tx nonce is provided
5 changes: 5 additions & 0 deletions .changeset/sweet-trains-hunt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@eth-optimism/batch-submitter-service': patch
---

Add MAX_PLAINTEXT_BATCH_SIZE parameter to max out compression
21 changes: 11 additions & 10 deletions batch-submitter/batch_submitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,16 +121,17 @@ func Main(gitVersion string) func(ctx *cli.Context) error {
var services []*bsscore.Service
if cfg.RunTxBatchSubmitter {
batchTxDriver, err := sequencer.NewDriver(sequencer.Config{
Name: "Sequencer",
L1Client: l1Client,
L2Client: l2Client,
BlockOffset: cfg.BlockOffset,
MinTxSize: cfg.MinL1TxSize,
MaxTxSize: cfg.MaxL1TxSize,
CTCAddr: ctcAddress,
ChainID: chainID,
PrivKey: sequencerPrivKey,
BatchType: sequencer.BatchTypeFromString(cfg.SequencerBatchType),
Name: "Sequencer",
L1Client: l1Client,
L2Client: l2Client,
BlockOffset: cfg.BlockOffset,
MinTxSize: cfg.MinL1TxSize,
MaxTxSize: cfg.MaxL1TxSize,
MaxPlaintextBatchSize: cfg.MaxPlaintextBatchSize,
CTCAddr: ctcAddress,
ChainID: chainID,
PrivKey: sequencerPrivKey,
BatchType: sequencer.BatchTypeFromString(cfg.SequencerBatchType),
})
if err != nil {
return err
Expand Down
5 changes: 5 additions & 0 deletions batch-submitter/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ type Config struct {
// by the batch submitter.
MaxL1TxSize uint64

// MaxPlaintextL1TxSize is the maximum size in bytes of the plaintext tx
// data encoded in batches.
MaxPlaintextBatchSize uint64

// MinStateRootElements is the minimum number of state root elements that
// can be submitted in single proposer batch.
MinStateRootElements uint64
Expand Down Expand Up @@ -203,6 +207,7 @@ func NewConfig(ctx *cli.Context) (Config, error) {
SCCAddress: ctx.GlobalString(flags.SCCAddressFlag.Name),
MinL1TxSize: ctx.GlobalUint64(flags.MinL1TxSizeFlag.Name),
MaxL1TxSize: ctx.GlobalUint64(flags.MaxL1TxSizeFlag.Name),
MaxPlaintextBatchSize: ctx.GlobalUint64(flags.MaxPlaintextBatchSizeFlag.Name),
MinStateRootElements: ctx.GlobalUint64(flags.MinStateRootElementsFlag.Name),
MaxStateRootElements: ctx.GlobalUint64(flags.MinStateRootElementsFlag.Name),
MaxBatchSubmissionTime: ctx.GlobalDuration(flags.MaxBatchSubmissionTimeFlag.Name),
Expand Down
47 changes: 19 additions & 28 deletions batch-submitter/drivers/sequencer/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,17 @@ const (
var bigOne = new(big.Int).SetUint64(1)

type Config struct {
Name string
L1Client *ethclient.Client
L2Client *l2ethclient.Client
BlockOffset uint64
MinTxSize uint64
MaxTxSize uint64
CTCAddr common.Address
ChainID *big.Int
PrivKey *ecdsa.PrivateKey
BatchType BatchType
Name string
L1Client *ethclient.Client
L2Client *l2ethclient.Client
BlockOffset uint64
MinTxSize uint64
MaxTxSize uint64
MaxPlaintextBatchSize uint64
CTCAddr common.Address
ChainID *big.Int
PrivKey *ecdsa.PrivateKey
BatchType BatchType
}

type Driver struct {
Expand Down Expand Up @@ -187,7 +188,7 @@ func (d *Driver) CraftBatchTx(
// Below this set will be further whittled until the raw call data
// size also adheres to this constraint.
txLen := batchElement.Tx.Size()
if totalTxSize+uint64(TxLenSize+txLen) > d.cfg.MaxTxSize {
if totalTxSize+uint64(TxLenSize+txLen) > d.cfg.MaxPlaintextBatchSize {
// Adding this transaction causes the batch to be too large, but
// we also record if the batch size without the transaction
// fails to meet our minimum size constraint. This is used below
Expand All @@ -212,24 +213,24 @@ func (d *Driver) CraftBatchTx(
return nil, err
}

// Use plaintext encoding to enforce size constraints.
plaintextBatchArguments, err := batchParams.Serialize(BatchTypeLegacy)
// Encode the batch arguments using the configured encoding type.
batchArguments, err := batchParams.Serialize(d.cfg.BatchType)
if err != nil {
return nil, err
}

appendSequencerBatchID := d.ctcABI.Methods[appendSequencerBatchMethodName].ID
plaintextCalldata := append(appendSequencerBatchID, plaintextBatchArguments...)
calldata := append(appendSequencerBatchID, batchArguments...)

log.Info(name+" testing batch size",
"plaintext_size", len(plaintextCalldata),
"calldata_size", len(calldata),
"min_tx_size", d.cfg.MinTxSize,
"max_tx_size", d.cfg.MaxTxSize)

// Continue pruning until plaintext calldata size is less than
// configured max.
plaintextCalldataSize := uint64(len(plaintextCalldata))
if plaintextCalldataSize > d.cfg.MaxTxSize {
calldataSize := uint64(len(calldata))
if calldataSize > d.cfg.MaxTxSize {
oldLen := len(batchElements)
newBatchElementsLen := (oldLen * 9) / 10
batchElements = batchElements[:newBatchElementsLen]
Expand Down Expand Up @@ -259,7 +260,7 @@ func (d *Driver) CraftBatchTx(
// becomes too small as a result. This is avoided by only applying
// the min size check when the pruneCount is zero.
ignoreMinTxSize := pruneCount > 0 || hasLargeNextTx
if !ignoreMinTxSize && plaintextCalldataSize < d.cfg.MinTxSize {
if !ignoreMinTxSize && calldataSize < d.cfg.MinTxSize {
log.Info(name+" batch tx size below minimum",
"num_txs", len(batchElements))
return nil, nil
Expand All @@ -268,16 +269,6 @@ func (d *Driver) CraftBatchTx(
d.metrics.NumElementsPerBatch().Observe(float64(len(batchElements)))
d.metrics.BatchPruneCount.Set(float64(pruneCount))

// Finally, encode the batch using the configured batch type.
var calldata = plaintextCalldata
if d.cfg.BatchType != BatchTypeLegacy {
batchArguments, err := batchParams.Serialize(d.cfg.BatchType)
if err != nil {
return nil, err
}
calldata = append(appendSequencerBatchID, batchArguments...)
}

log.Info(name+" batch constructed",
"num_txs", len(batchElements),
"final_size", len(calldata),
Expand Down
8 changes: 8 additions & 0 deletions batch-submitter/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ var (
Required: true,
EnvVar: prefixEnvVar("MAX_L1_TX_SIZE"),
}
MaxPlaintextBatchSizeFlag = cli.Uint64Flag{
Name: "max-plaintext-batch-size",
Usage: "Maximum size in bytes of of the plaintext tx data " +
"encoded in batches",
Required: true,
EnvVar: prefixEnvVar("MAX_PLAINTEXT_BATCH_SIZE"),
}
MinStateRootElementsFlag = cli.Uint64Flag{
Name: "min-state-root-elements",
Usage: "Minimum number of elements required to submit a state " +
Expand Down Expand Up @@ -254,6 +261,7 @@ var requiredFlags = []cli.Flag{
SCCAddressFlag,
MinL1TxSizeFlag,
MaxL1TxSizeFlag,
MaxPlaintextBatchSizeFlag,
MinStateRootElementsFlag,
MaxStateRootElementsFlag,
MaxBatchSubmissionTimeFlag,
Expand Down
1 change: 1 addition & 0 deletions ops/envs/batch-submitter.env
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ BATCH_SUBMITTER_LOG_LEVEL=debug
BATCH_SUBMITTER_LOG_TERMINAL=true
BATCH_SUBMITTER_MIN_L1_TX_SIZE=32
BATCH_SUBMITTER_MAX_L1_TX_SIZE=90000
BATCH_SUBMITTER_MAX_PLAINTEXT_BATCH_SIZE=120000
BATCH_SUBMITTER_MIN_STATE_ROOT_ELEMENTS=1
BATCH_SUBMITTER_MAX_STATE_ROOT_ELEMENTS=3000
BATCH_SUBMITTER_MAX_BATCH_SUBMISSION_TIME=0
Expand Down
25 changes: 23 additions & 2 deletions packages/sdk/src/l2-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,27 @@ import { toProvider, toNumber, toBigNumber } from './utils'

type ProviderTypeIsWrong = any

/**
* Gets a reasonable nonce for the transaction.
*
* @param provider Provider to get the nonce from.
* @param tx Requested transaction.
* @returns A reasonable nonce for the transaction.
*/
const getNonceForTx = async (
provider: ProviderLike,
tx: TransactionRequest
): Promise<number> => {
if (tx.nonce !== undefined) {
return toNumber(tx.nonce as NumberLike)
} else if (tx.from !== undefined) {
return toProvider(provider).getTransactionCount(tx.from)
} else {
// Large nonce with lots of non-zero bytes
return 0xffffffff
}
}

/**
* Returns a Contract object for the GasPriceOracle.
*
Expand Down Expand Up @@ -57,7 +78,7 @@ export const estimateL1Gas = async (
gasPrice: tx.gasPrice,
type: tx.type,
gasLimit: tx.gasLimit,
nonce: toNumber(tx.nonce as NumberLike),
nonce: await getNonceForTx(l2Provider, tx),
})
)
}
Expand All @@ -81,7 +102,7 @@ export const estimateL1GasCost = async (
gasPrice: tx.gasPrice,
type: tx.type,
gasLimit: tx.gasLimit,
nonce: toNumber(tx.nonce as NumberLike),
nonce: await getNonceForTx(l2Provider, tx),
})
)
}
Expand Down