-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[BP: release/v5 <- #86]
fix!: queries that panic should return `ack…
…-err` (#138) * fix!: queries that panic should return `ack-err` (#86) * adding ApplyFuncIfNoError * Moving cache_ctx.go to the keeper * updating comment * chore: address linter errors --------- Co-authored-by: jtieri <[email protected]> (cherry picked from commit 83f866e) # Conflicts: # modules/async-icq/testing/demo-simapp/app/export.go * fix: remove demo simapp code that was never backported --------- Co-authored-by: Vitaly Volozhinov <[email protected]> Co-authored-by: jtieri <[email protected]>
- Loading branch information
1 parent
5b5a86c
commit 16e0000
Showing
3 changed files
with
93 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package keeper | ||
|
||
// This file was copied from here: https://github.com/osmosis-labs/osmosis/blob/62757d309957fa9e02e6fb0b5dc8caf1ca68e696/osmoutils/cache_ctx.go | ||
|
||
import ( | ||
"errors" | ||
"runtime" | ||
"runtime/debug" | ||
|
||
"github.com/cosmos/cosmos-sdk/store/types" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
) | ||
|
||
// This function lets you run the function f, but if theres an error or panic | ||
// drop the state machine change and log the error. | ||
// If there is no error, proceeds as normal (but with some slowdown due to SDK store weirdness) | ||
// Try to avoid usage of iterators in f. | ||
// | ||
// If its an out of gas panic, this function will also panic like in normal tx execution flow. | ||
// This is still safe for beginblock / endblock code though, as they do not have out of gas panics. | ||
func applyFuncIfNoError(ctx sdk.Context, f func(ctx sdk.Context) error) (err error) { | ||
// Add a panic safeguard | ||
defer func() { | ||
if recoveryError := recover(); recoveryError != nil { | ||
if isErr, _ := isOutOfGasError(recoveryError); isErr { | ||
// We panic with the same error, to replicate the normal tx execution flow. | ||
panic(recoveryError) | ||
} else { | ||
printPanicRecoveryError(ctx, recoveryError) | ||
err = errors.New("panic occurred during execution") | ||
} | ||
} | ||
}() | ||
// makes a new cache context, which all state changes get wrapped inside of. | ||
cacheCtx, write := ctx.CacheContext() | ||
err = f(cacheCtx) | ||
if err != nil { | ||
ctx.Logger().Error(err.Error()) | ||
} else { | ||
// no error, write the output of f | ||
write() | ||
ctx.EventManager().EmitEvents(cacheCtx.EventManager().Events()) | ||
} | ||
return err | ||
} | ||
|
||
// Frustratingly, this has to return the error descriptor, not an actual error itself | ||
// because the SDK errors here are not actually errors. (They don't implement error interface) | ||
func isOutOfGasError(err any) (bool, string) { | ||
switch e := err.(type) { | ||
case types.ErrorOutOfGas: | ||
return true, e.Descriptor | ||
case types.ErrorGasOverflow: | ||
return true, e.Descriptor | ||
default: | ||
return false, "" | ||
} | ||
} | ||
|
||
// printPanicRecoveryError error logs the recoveryError, along with the stacktrace, if it can be parsed. | ||
// If not emits them to stdout. | ||
func printPanicRecoveryError(ctx sdk.Context, recoveryError interface{}) { | ||
errStackTrace := string(debug.Stack()) | ||
switch e := recoveryError.(type) { | ||
case types.ErrorOutOfGas: | ||
ctx.Logger().Debug("out of gas error inside panic recovery block: " + e.Descriptor) | ||
return | ||
case string: | ||
ctx.Logger().Error("Recovering from (string) panic: " + e) | ||
case runtime.Error: | ||
ctx.Logger().Error("recovered (runtime.Error) panic: " + e.Error()) | ||
case error: | ||
ctx.Logger().Error("recovered (error) panic: " + e.Error()) | ||
default: | ||
ctx.Logger().Error("recovered (default) panic. Could not capture logs in ctx, see stdout") | ||
debug.PrintStack() | ||
return | ||
} | ||
ctx.Logger().Error("stack trace: " + errStackTrace) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters