Skip to content

Commit e42262e

Browse files
committed
Integrate StateDB bundle tracking into bundle runner
1 parent 2c0dbf2 commit e42262e

3 files changed

Lines changed: 293 additions & 90 deletions

File tree

evmcore/state_processor.go

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -336,20 +336,24 @@ func (r *transactionRunner) runTransactionBundle(
336336
ctxt *runContext,
337337
tx *types.Transaction,
338338
txIndex int,
339+
) ([]ProcessedTransaction, core_types.TransactionResult) {
340+
return r.runTransactionBundleInternal(ctxt, tx, txIndex, log.Root())
341+
}
342+
343+
func (r *transactionRunner) runTransactionBundleInternal(
344+
ctxt *runContext,
345+
tx *types.Transaction,
346+
txIndex int,
347+
log logger,
339348
) ([]ProcessedTransaction, core_types.TransactionResult) {
340349
if !ctxt.upgrades.TransactionBundles {
341-
log.Warn("Transaction bundles are not enabled, skipping bundle transaction", "tx", tx.Hash().Hex())
350+
log.Warn("Transaction bundles are not enabled, bundle transaction skipped", "tx", tx.Hash().Hex())
342351
return []ProcessedTransaction{{Transaction: tx}}, core_types.TransactionResultInvalid
343352
}
344353

345-
txBundle, err := bundle.OpenEnvelope(tx)
354+
txBundle, plan, err := bundle.ValidateEnvelope(ctxt.signer, tx)
346355
if err != nil {
347-
log.Warn("failed to open bundle envelope", "tx", tx.Hash().Hex(), "err", err)
348-
return []ProcessedTransaction{{Transaction: tx}}, core_types.TransactionResultInvalid
349-
}
350-
plan, err := bundle.ExtractExecutionPlan(ctxt.signer, tx)
351-
if err != nil {
352-
log.Warn("failed to extract execution plan", "tx", tx.Hash().Hex(), "err", err)
356+
log.Warn("Invalid bundle skipped", "tx", tx.Hash().Hex(), "error", err)
353357
return []ProcessedTransaction{{Transaction: tx}}, core_types.TransactionResultInvalid
354358
}
355359

@@ -358,13 +362,39 @@ func (r *transactionRunner) runTransactionBundle(
358362
return []ProcessedTransaction{{Transaction: tx}}, core_types.TransactionResultInvalid
359363
}
360364

365+
planHash := plan.Hash()
366+
if ctxt.statedb.HasBundleRecentlyBeenProcessed(planHash) {
367+
log.Warn("Rescheduled bundle skipped", "exec_plan_hash", planHash)
368+
return []ProcessedTransaction{{Transaction: tx}}, core_types.TransactionResultInvalid
369+
}
370+
371+
positionInBlock := bundle.PositionInBlock{
372+
Offset: uint32(txIndex),
373+
}
374+
361375
// Run the bundle and collect the processed transactions.
362376
runner := bundleTransactionRunner{ctxt: ctxt, txOffset: txIndex}
363-
if success := bundle.RunBundle(&txBundle, &runner); !success {
377+
if success := bundle.RunBundle(txBundle, &runner); !success {
364378
return []ProcessedTransaction{}, core_types.TransactionResultFailed
365379
}
366380

367-
// return all processed transactions collected by the runner
381+
// Update the position-in-block struct to track the number of transactions
382+
// added to the block as part of this bundle execution.
383+
for _, processedTx := range runner.processedTransactions {
384+
if processedTx.Receipt != nil {
385+
positionInBlock.Count++
386+
}
387+
}
388+
389+
// Mark the execution plan as processed in the StateDB to prevent processing
390+
// another bundle with the same execution plan in the same block. Also keep
391+
// track of the position of the bundle in the block.
392+
// Note: it is sufficient to mark the execution plan of a bundle after the
393+
// execution of the bundle as used since nested bundles can not contain
394+
// copies of themselves without finding a hash-function collision.
395+
ctxt.statedb.AddProcessedBundle(planHash, positionInBlock)
396+
397+
// return the
368398
return runner.processedTransactions, core_types.TransactionResultSuccessful
369399
}
370400

@@ -716,3 +746,12 @@ func TxAsMessage(tx *types.Transaction, signer types.Signer, baseFee *big.Int) (
716746
}, nil
717747
}
718748
}
749+
750+
// logger is an internal interface to enable the mocking of logging in tests.
751+
// This is in particular useful to make sure tests that trigger failing
752+
// conditions are actually triggering the correct condition.
753+
type logger interface {
754+
Debug(msg string, ctx ...any)
755+
Info(msg string, ctx ...any)
756+
Warn(msg string, ctx ...any)
757+
}

evmcore/state_processor_mock.go

Lines changed: 75 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)