mukan-ibc/modules/apps/callbacks/internal/process.go
Mukan Erkin Törük 88dd97a9f8
Some checks failed
CodeQL / Analyze (push) Waiting to run
golangci-lint / lint (push) Waiting to run
Tests / Code Coverage / build (amd64) (push) Waiting to run
Tests / Code Coverage / build (arm64) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[additional-args:-tags="test_e2e" name:e2e path:./e2e]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:08-wasm path:./modules/light-clients/08-wasm]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:ibc-go path:.]) (push) Waiting to run
Docker Build & Push Simapp (main) / docker-build (push) Has been cancelled
refactor: replace all github.com upstream refs with git.cw.tr/mukan-network
2026-05-11 03:36:22 +03:00

61 lines
2.3 KiB
Go

package internal
import (
"fmt"
errorsmod "cosmossdk.io/errors"
storetypes "cosmossdk.io/store/types"
sdk "git.cw.tr/mukan-network/mukan-sdk/types"
"git.cw.tr/mukan-network/mukan-ibc/modules/apps/callbacks/types"
)
// ProcessCallback executes the callbackExecutor and reverts contract changes if the callbackExecutor fails.
//
// Error Precedence and Returns:
// - oogErr: Takes the highest precedence. If the callback runs out of gas, an error wrapped with types.ErrCallbackOutOfGas is returned.
// - panicErr: Takes the second-highest precedence. If a panic occurs and it is not propagated, an error wrapped with types.ErrCallbackPanic is returned.
// - callbackErr: If the callbackExecutor returns an error, it is returned as-is.
//
// panics if
// - the contractExecutor panics for any reason, and the callbackType is SendPacket, or
// - the contractExecutor runs out of gas and the relayer has not reserved gas grater than or equal to
// CommitGasLimit.
func ProcessCallback(
ctx sdk.Context, callbackType types.CallbackType,
callbackData types.CallbackData, callbackExecutor func(sdk.Context) error,
) (err error) {
cachedCtx, writeFn := ctx.CacheContext()
cachedCtx = cachedCtx.WithGasMeter(storetypes.NewGasMeter(callbackData.ExecutionGasLimit))
defer func() {
// consume the minimum of g.consumed and g.limit
ctx.GasMeter().ConsumeGas(cachedCtx.GasMeter().GasConsumedToLimit(), fmt.Sprintf("ibc %s callback", callbackType))
// recover from all panics except during SendPacket callbacks
if r := recover(); r != nil {
if callbackType == types.CallbackTypeSendPacket {
panic(r)
}
err = errorsmod.Wrapf(types.ErrCallbackPanic, "ibc %s callback panicked with: %v", callbackType, r)
}
// if the callback ran out of gas and the relayer has not reserved enough gas, then revert the state
if cachedCtx.GasMeter().IsPastLimit() {
if callbackData.AllowRetry() {
panic(storetypes.ErrorOutOfGas{Descriptor: fmt.Sprintf("ibc %s callback out of gas; commitGasLimit: %d", callbackType, callbackData.CommitGasLimit)})
}
err = errorsmod.Wrapf(types.ErrCallbackOutOfGas, "ibc %s callback out of gas", callbackType)
}
// allow the transaction to be committed, continuing the packet lifecycle
}()
err = callbackExecutor(cachedCtx)
if err == nil {
writeFn()
}
return err
}