github.com/Finschia/finschia-sdk@v0.48.1/baseapp/recovery.go (about) 1 package baseapp 2 3 import ( 4 "fmt" 5 "runtime/debug" 6 7 sdk "github.com/Finschia/finschia-sdk/types" 8 sdkerrors "github.com/Finschia/finschia-sdk/types/errors" 9 ) 10 11 // RecoveryHandler handles recovery() object. 12 // Return a non-nil error if recoveryObj was processed. 13 // Return nil if recoveryObj was not processed. 14 type RecoveryHandler func(recoveryObj interface{}) error 15 16 // recoveryMiddleware is wrapper for RecoveryHandler to create chained recovery handling. 17 // returns (recoveryMiddleware, nil) if recoveryObj was not processed and should be passed to the next middleware in chain. 18 // returns (nil, error) if recoveryObj was processed and middleware chain processing should be stopped. 19 type recoveryMiddleware func(recoveryObj interface{}) (recoveryMiddleware, error) 20 21 // processRecovery processes recoveryMiddleware chain for recovery() object. 22 // Chain processing stops on non-nil error or when chain is processed. 23 func processRecovery(recoveryObj interface{}, middleware recoveryMiddleware) error { 24 if middleware == nil { 25 return nil 26 } 27 28 next, err := middleware(recoveryObj) 29 if err != nil { 30 return err 31 } 32 33 return processRecovery(recoveryObj, next) 34 } 35 36 // newRecoveryMiddleware creates a RecoveryHandler middleware. 37 func newRecoveryMiddleware(handler RecoveryHandler, next recoveryMiddleware) recoveryMiddleware { 38 return func(recoveryObj interface{}) (recoveryMiddleware, error) { 39 if err := handler(recoveryObj); err != nil { 40 return nil, err 41 } 42 43 return next, nil 44 } 45 } 46 47 // newOutOfGasRecoveryMiddleware creates a standard OutOfGas recovery middleware for app.runTx method. 48 func newOutOfGasRecoveryMiddleware(gasWanted uint64, ctx sdk.Context, next recoveryMiddleware) recoveryMiddleware { 49 handler := func(recoveryObj interface{}) error { 50 err, ok := recoveryObj.(sdk.ErrorOutOfGas) 51 if !ok { 52 return nil 53 } 54 55 return sdkerrors.Wrap( 56 sdkerrors.ErrOutOfGas, fmt.Sprintf( 57 "out of gas in location: %v; gasWanted: %d, gasUsed: %d", 58 err.Descriptor, gasWanted, ctx.GasMeter().GasConsumed(), 59 ), 60 ) 61 } 62 63 return newRecoveryMiddleware(handler, next) 64 } 65 66 // newDefaultRecoveryMiddleware creates a default (last in chain) recovery middleware for app.runTx method. 67 func newDefaultRecoveryMiddleware() recoveryMiddleware { 68 handler := func(recoveryObj interface{}) error { 69 return sdkerrors.Wrap( 70 sdkerrors.ErrPanic, fmt.Sprintf( 71 "recovered: %v\nstack:\n%v", recoveryObj, string(debug.Stack()), 72 ), 73 ) 74 } 75 76 return newRecoveryMiddleware(handler, nil) 77 }