Skip to content

Commit

Permalink
op-batcher: add TestBatchSubmitter_sendTx_FloorDataGas and patch `d…
Browse files Browse the repository at this point in the history
…river.sendTx` (ethereum-optimism#14517)

* op-batcher: add TestBatchSubmitter_sendTx_FloorDataGas

* op-batcher: use floorDataGas for transactions if greater than intrinsicGas

* Update op-batcher/batcher/driver.go

Co-authored-by: Sebastian Stammler <[email protected]>

* log error instead of ignoring

---------

Co-authored-by: Sebastian Stammler <[email protected]>
  • Loading branch information
2 people authored and palango committed Feb 28, 2025
1 parent f25b61c commit 03a67db
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
34 changes: 34 additions & 0 deletions op-batcher/batcher/driver.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package batcher

import (
"bytes"
"context"
"errors"
"fmt"
"io"
"math"
"math/big"
_ "net/http/pprof"
"sync"
Expand Down Expand Up @@ -851,6 +853,10 @@ func (l *BatchSubmitter) sendTransaction(txdata txData, queue *txmgr.Queue[txRef
return nil
}

type TxSender[T any] interface {
Send(id T, candidate txmgr.TxCandidate, receiptCh chan txmgr.TxReceipt[T])
}

// sendTx uses the txmgr queue to send the given transaction candidate after setting its
// gaslimit. It will block if the txmgr queue has reached its MaxPendingTransactions limit.
func (l *BatchSubmitter) sendTx(txdata txData, isCancel bool, candidate *txmgr.TxCandidate, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef]) {
Expand All @@ -862,9 +868,37 @@ func (l *BatchSubmitter) sendTx(txdata txData, isCancel bool, candidate *txmgr.T
candidate.GasLimit = intrinsicGas
}

floorDataGas, err := floorDataGas(candidate.TxData)
if err != nil {
l.Log.Warn("Failed to compute FloorDataGas: %v, continuing with intrinsic gas.")
} else if floorDataGas > candidate.GasLimit {
l.Log.Debug("Bumping gas limit to floor data gas", "intrinsic_gas", intrinsicGas, "floor_data_gas", floorDataGas)
candidate.GasLimit = floorDataGas
}

queue.Send(txRef{id: txdata.ID(), isCancel: isCancel, isBlob: txdata.daType == DaTypeBlob}, *candidate, receiptsCh)
}

// Copypaste from upstream geth
// TODO remove in #14500
func floorDataGas(data []byte) (uint64, error) {
TxTokenPerNonZeroByte := uint64(4)
TxGas := uint64(21000)
TxCostFloorPerToken := uint64(10)

var (
z = uint64(bytes.Count(data, []byte{0}))
nz = uint64(len(data)) - z
tokens = nz*TxTokenPerNonZeroByte + z
)
// Check for overflow
if (math.MaxUint64-TxGas)/TxCostFloorPerToken < tokens {
return 0, core.ErrGasUintOverflow
}
// Minimum gas required for a transaction based on its data tokens (EIP-7623).
return TxGas + tokens*TxCostFloorPerToken, nil
}

func (l *BatchSubmitter) blobTxCandidate(data txData) (*txmgr.TxCandidate, error) {
blobs, err := data.Blobs()
if err != nil {
Expand Down
44 changes: 44 additions & 0 deletions op-batcher/batcher/driver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ package batcher
import (
"context"
"errors"
"sync"
"testing"

"github.com/ethereum-optimism/optimism/op-batcher/metrics"
"github.com/ethereum-optimism/optimism/op-service/dial"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum-optimism/optimism/op-service/testutils"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -116,3 +118,45 @@ func TestBatchSubmitter_SafeL1Origin_FailsToResolveRollupClient(t *testing.T) {
_, err := bs.safeL1Origin(context.Background())
require.Error(t, err)
}

type MockTxQueue struct {
m sync.Map
}

func (q *MockTxQueue) Send(ref txRef, candidate txmgr.TxCandidate, receiptCh chan txmgr.TxReceipt[txRef]) {
q.m.Store(ref.id.String(), candidate)
}

func (q *MockTxQueue) Load(id string) txmgr.TxCandidate {
c, _ := q.m.Load(id)
return c.(txmgr.TxCandidate)
}

func TestBatchSubmitter_sendTx_FloorDataGas(t *testing.T) {
bs, _ := setup(t)

q := new(MockTxQueue)

txData := txData{
frames: []frameData{
{
data: []byte{0x01, 0x02, 0x03}, // 3 nonzero bytes = 12 tokens https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7623.md
},
},
}
candidate := txmgr.TxCandidate{
To: &bs.RollupConfig.BatchInboxAddress,
TxData: txData.CallData(),
}

bs.sendTx(txData,
false,
&candidate,
q,
make(chan txmgr.TxReceipt[txRef]))

candidateOut := q.Load(txData.ID().String())

expectedFloorDataGas := uint64(21_000 + 12*10)
require.GreaterOrEqual(t, candidateOut.GasLimit, expectedFloorDataGas)
}

0 comments on commit 03a67db

Please sign in to comment.