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  }