Skip to content
Closed
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
45 changes: 38 additions & 7 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -1424,8 +1424,23 @@ func (app *App) ProcessTxsSynchronousGiga(ctx sdk.Context, txs [][]byte, typedTx
continue
}

// Execute EVM transaction through giga executor
result, execErr := app.executeEVMTxWithGigaExecutor(ctx, evmMsg, cache)
// Execute EVM transaction through giga executor with panic recovery
// (matches V2's recover behavior in legacyabci/deliver_tx.go)
var result *abci.ExecTxResult
var execErr error
func() {
defer func() {
if r := recover(); r != nil {
logger.Error("panic in giga synchronous executor", "panic", r, "stack", string(debug.Stack()))
result = &abci.ExecTxResult{
Code: sdkerrors.ErrPanic.ABCICode(),
Log: fmt.Sprintf("panic recovered: %v", r),
}
}
}()
result, execErr = app.executeEVMTxWithGigaExecutor(ctx, evmMsg, cache)
}()

if execErr != nil {
// Check if this is a fail-fast error (Cosmos precompile interop detected)
if gigautils.ShouldExecutionAbort(execErr) {
Expand Down Expand Up @@ -1950,13 +1965,29 @@ func (app *App) executeEVMTxWithGigaExecutor(ctx sdk.Context, msg *evmtypes.MsgE
// makeGigaDeliverTx returns an OCC-compatible deliverTx callback that captures the given
// block cache, avoiding mutable state on App for cache lifecycle management.
func (app *App) makeGigaDeliverTx(cache *gigaBlockCache) func(sdk.Context, abci.RequestDeliverTxV2, sdk.Tx, [32]byte) abci.ResponseDeliverTx {
return func(ctx sdk.Context, req abci.RequestDeliverTxV2, tx sdk.Tx, checksum [32]byte) abci.ResponseDeliverTx {
return func(ctx sdk.Context, req abci.RequestDeliverTxV2, tx sdk.Tx, checksum [32]byte) (resp abci.ResponseDeliverTx) {
defer func() {
if r := recover(); r != nil {
// OCC abort panics are expected - the scheduler uses them to detect conflicts
// and reschedule transactions. Don't log these as errors.
if _, isOCCAbort := r.(occ.Abort); !isOCCAbort {
logger.Error("benchmark panic in gigaDeliverTx", "panic", r, "stack", string(debug.Stack()))
// Handle panics as v2 does: ErrOCCAbort, ErrOutOfGas, or ErrPanic
if abort, isOCCAbort := r.(occ.Abort); isOCCAbort {
resp = abci.ResponseDeliverTx{
Code: sdkerrors.ErrOCCAbort.ABCICode(),
Log: fmt.Sprintf("occ abort occurred with dependent index %d and error: %v", abort.DependentTxIdx, abort.Err),
}
return
}
if oogErr, isOOG := r.(sdk.ErrorOutOfGas); isOOG {
resp = abci.ResponseDeliverTx{
Code: sdkerrors.ErrOutOfGas.ABCICode(),
Log: fmt.Sprintf("out of gas in location: %v", oogErr.Descriptor),
}
return
}
// For other panics (e.g., nil deref from malformed protobuf), log and return ErrPanic
logger.Error("panic in gigaDeliverTx", "panic", r, "stack", string(debug.Stack()))
resp = abci.ResponseDeliverTx{
Code: sdkerrors.ErrPanic.ABCICode(),
Log: fmt.Sprintf("recovered: %v\nstack:\n%v", r, string(debug.Stack())),
}
}
}()
Expand Down
Loading