Skip to content

Commit

Permalink
merge #22
Browse files Browse the repository at this point in the history
  • Loading branch information
syntrust committed Oct 30, 2024
1 parent 4797ddb commit 02a9de8
Showing 2 changed files with 47 additions and 17 deletions.
43 changes: 32 additions & 11 deletions op-batcher/batcher/driver.go
Original file line number Diff line number Diff line change
@@ -26,8 +26,10 @@ import (
)

var (
ErrBatcherNotRunning = errors.New("batcher is not running")
emptyTxData = txData{
ErrBatcherNotRunning = errors.New("batcher is not running")
ErrInboxTransactionFailed = errors.New("inbox transaction failed")

emptyTxData = txData{
frames: []frameData{
{
data: []byte{},
@@ -45,6 +47,7 @@ type txRef struct {
type L1Client interface {
HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)
NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error)
CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error)
}

type L2Client interface {
@@ -87,7 +90,8 @@ type BatchSubmitter struct {
lastStoredBlock eth.BlockID
lastL1Tip eth.L1BlockRef

state *channelManager
state *channelManager
inboxIsEOA *bool
}

// NewBatchSubmitter initializes the BatchSubmitter driver from a preconfigured DriverSetup
@@ -584,20 +588,33 @@ func (l *BatchSubmitter) sendTransaction(ctx context.Context, txdata txData, que
}
candidate = l.calldataTxCandidate(data)
}

if *candidate.To != l.RollupConfig.BatchInboxAddress {
return fmt.Errorf("candidate.To is not inbox")
}
if l.inboxIsEOA == nil {
var code []byte
code, err = l.L1Client.CodeAt(ctx, *candidate.To, nil)
if err != nil {
return fmt.Errorf("CodeAt failed:%w", err)
}
isEOA := len(code) == 0
l.inboxIsEOA = &isEOA
}
l.queueTx(txdata, false, candidate, queue, receiptsCh)
return nil
}

func (l *BatchSubmitter) queueTx(txdata txData, isCancel bool, candidate *txmgr.TxCandidate, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef]) {
intrinsicGas, err := core.IntrinsicGas(candidate.TxData, nil, false, true, true, false)
if err != nil {
// we log instead of return an error here because txmgr can do its own gas estimation
l.Log.Error("Failed to calculate intrinsic gas", "err", err)
} else {
candidate.GasLimit = intrinsicGas
// only set GasLimit when inbox is EOA so that later on `EstimateGas` will be called if inbox is a contract
if *l.inboxIsEOA {
intrinsicGas, err := core.IntrinsicGas(candidate.TxData, nil, false, true, true, false)
if err != nil {
// we log instead of return an error here because txmgr can do its own gas estimation
l.Log.Error("Failed to calculate intrinsic gas", "err", err)
} else {
candidate.GasLimit = intrinsicGas
}
}

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

@@ -630,6 +647,10 @@ func (l *BatchSubmitter) handleReceipt(r txmgr.TxReceipt[txRef]) {
if r.Err != nil {
l.recordFailedTx(r.ID.id, r.Err)
} else {
if r.Receipt.Status == types.ReceiptStatusFailed {
l.recordFailedTx(r.ID.id, ErrInboxTransactionFailed)
return
}
l.recordConfirmedTx(r.ID.id, r.Receipt)
}
}
21 changes: 15 additions & 6 deletions op-node/rollup/derive/blob_data_source.go
Original file line number Diff line number Diff line change
@@ -27,13 +27,13 @@ type BlobDataSource struct {
ref eth.L1BlockRef
batcherAddr common.Address
dsCfg DataSourceConfig
fetcher L1TransactionFetcher
fetcher L1Fetcher
blobsFetcher L1BlobsFetcher
log log.Logger
}

// NewBlobDataSource creates a new blob data source.
func NewBlobDataSource(ctx context.Context, log log.Logger, dsCfg DataSourceConfig, fetcher L1TransactionFetcher, blobsFetcher L1BlobsFetcher, ref eth.L1BlockRef, batcherAddr common.Address) DataIter {
func NewBlobDataSource(ctx context.Context, log log.Logger, dsCfg DataSourceConfig, fetcher L1Fetcher, blobsFetcher L1BlobsFetcher, ref eth.L1BlockRef, batcherAddr common.Address) DataIter {
return &BlobDataSource{
ref: ref,
dsCfg: dsCfg,
@@ -85,8 +85,17 @@ func (ds *BlobDataSource) open(ctx context.Context) ([]blobOrCalldata, error) {
}
return nil, NewTemporaryError(fmt.Errorf("failed to open blob data source: %w", err))
}
_, receipts, err := ds.fetcher.FetchReceipts(ctx, ds.ref.Hash)
if err != nil {
return nil, NewTemporaryError(fmt.Errorf("failed to fetch L1 block info and receipts: %w", err))
}

txSucceeded := make(map[common.Hash]bool)
for _, receipt := range receipts {
txSucceeded[receipt.TxHash] = receipt.Status == types.ReceiptStatusSuccessful
}

data, hashes := dataAndHashesFromTxs(txs, &ds.dsCfg, ds.batcherAddr)
data, hashes := dataAndHashesFromTxs(txs, &ds.dsCfg, ds.batcherAddr, txSucceeded)

if len(hashes) == 0 {
// there are no blobs to fetch so we can return immediately
@@ -115,13 +124,13 @@ func (ds *BlobDataSource) open(ctx context.Context) ([]blobOrCalldata, error) {
// dataAndHashesFromTxs extracts calldata and datahashes from the input transactions and returns them. It
// creates a placeholder blobOrCalldata element for each returned blob hash that must be populated
// by fillBlobPointers after blob bodies are retrieved.
func dataAndHashesFromTxs(txs types.Transactions, config *DataSourceConfig, batcherAddr common.Address) ([]blobOrCalldata, []eth.IndexedBlobHash) {
func dataAndHashesFromTxs(txs types.Transactions, config *DataSourceConfig, batcherAddr common.Address, txSucceeded map[common.Hash]bool) ([]blobOrCalldata, []eth.IndexedBlobHash) {
data := []blobOrCalldata{}
var hashes []eth.IndexedBlobHash
blobIndex := 0 // index of each blob in the block's blob sidecar
for _, tx := range txs {
// skip any non-batcher transactions
if !isValidBatchTx(tx, config.l1Signer, config.batchInboxAddress, batcherAddr) {
// skip any non-batcher transactions or failed transactions
if !(isValidBatchTx(tx, config.l1Signer, config.batchInboxAddress, batcherAddr) && txSucceeded[tx.Hash()]) {
blobIndex += len(tx.BlobHashes())
continue
}

0 comments on commit 02a9de8

Please sign in to comment.