From 35665ded101015db21fe9611eb2443215ef641c9 Mon Sep 17 00:00:00 2001 From: Prathamesh Musale Date: Mon, 12 May 2025 19:19:20 +0530 Subject: [PATCH] Add a custom ante handler to accept fees only in alps --- app/ante.go | 78 ++++++++++++++++++++++++++++++++++++++++++++ app/app.go | 24 ++++++++++++++ x/bond/params.go | 2 +- x/registry/params.go | 10 +++--- 4 files changed, 108 insertions(+), 6 deletions(-) create mode 100644 app/ante.go diff --git a/app/ante.go b/app/ante.go new file mode 100644 index 00000000..9bdcc33b --- /dev/null +++ b/app/ante.go @@ -0,0 +1,78 @@ +package app + +import ( + _ "embed" + "math" + + errorsmod "cosmossdk.io/errors" + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + + "git.vdb.to/cerc-io/laconicd/app/params" +) + +// Reference: https://github.com/cosmos/cosmos-sdk/blob/v0.50.10/x/auth/ante/validator_tx_fee.go#L15 + +// checkTxFeeWithValidatorMinGasPrices implements the default fee logic, where the minimum price per +// unit of gas is fixed and set by each validator, can the tx priority is computed from the gas price. +func checkTxFeeWithValidatorMinGasPrices(ctx sdk.Context, tx sdk.Tx) (sdk.Coins, int64, error) { + feeTx, ok := tx.(sdk.FeeTx) + if !ok { + return nil, 0, errorsmod.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx") + } + + feeCoins := feeTx.GetFee() + gas := feeTx.GetGas() + + for _, coin := range feeCoins { + if coin.Denom != params.BaseCoinUnit { + return nil, 0, errorsmod.Wrapf(sdkerrors.ErrInvalidCoins, "only alps is accepted as fee denom") + } + } + + // Ensure that the provided fees meet a minimum threshold for the validator, + // if this is a CheckTx. This is only for local mempool purposes, and thus + // is only ran on check tx. + if ctx.IsCheckTx() { + minGasPrices := ctx.MinGasPrices() + if !minGasPrices.IsZero() { + requiredFees := make(sdk.Coins, len(minGasPrices)) + + // Determine the required fees by multiplying each required minimum gas + // price by the gas limit, where fee = ceil(minGasPrice * gasLimit). + glDec := sdkmath.LegacyNewDec(int64(gas)) + for i, gp := range minGasPrices { + fee := gp.Amount.Mul(glDec) + requiredFees[i] = sdk.NewCoin(gp.Denom, fee.Ceil().RoundInt()) + } + + if !feeCoins.IsAnyGTE(requiredFees) { + return nil, 0, errorsmod.Wrapf(sdkerrors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeCoins, requiredFees) + } + } + } + + priority := getTxPriority(feeCoins, int64(gas)) + return feeCoins, priority, nil +} + +// getTxPriority returns a naive tx priority based on the amount of the smallest denomination of the gas price +// provided in a transaction. +// NOTE: This implementation should be used with a great consideration as it opens potential attack vectors +// where txs with multiple coins could not be prioritize as expected. +func getTxPriority(fee sdk.Coins, gas int64) int64 { + var priority int64 + for _, c := range fee { + p := int64(math.MaxInt64) + gasPrice := c.Amount.QuoRaw(gas) + if gasPrice.IsInt64() { + p = gasPrice.Int64() + } + if priority == 0 || p < priority { + priority = p + } + } + + return priority +} diff --git a/app/app.go b/app/app.go index 98dba649..08d39552 100644 --- a/app/app.go +++ b/app/app.go @@ -27,6 +27,7 @@ import ( "github.com/cosmos/cosmos-sdk/server/config" servertypes "github.com/cosmos/cosmos-sdk/server/types" "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/x/auth/ante" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" consensuskeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper" @@ -185,6 +186,9 @@ func NewLaconicApp( app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, make(map[string]module.AppModuleSimulation, 0)) app.sm.RegisterStoreDecoders() + // set custom ante handlers + app.setCustomAnteHandler() + if err := app.Load(loadLatest); err != nil { return nil, err } @@ -232,3 +236,23 @@ func (app *LaconicApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.AP panic(err) } } + +// setCustomAnteHandler overwrites default ante handlers with custom ante handlers +// Reference: https://github.com/cosmos/cosmos-sdk/blob/v0.50.10/x/auth/tx/config/config.go#L149 +func (app *LaconicApp) setCustomAnteHandler() { + anteHandler, err := ante.NewAnteHandler( + ante.HandlerOptions{ + AccountKeeper: app.AccountKeeper, + BankKeeper: app.BankKeeper, + SignModeHandler: app.txConfig.SignModeHandler(), + SigGasConsumer: ante.DefaultSigVerificationGasConsumer, + TxFeeChecker: checkTxFeeWithValidatorMinGasPrices, + }, + ) + if err != nil { + panic(err) + } + + // Set the AnteHandler for the app + app.SetAnteHandler(anteHandler) +} diff --git a/x/bond/params.go b/x/bond/params.go index 3c6714de..f9b4161c 100644 --- a/x/bond/params.go +++ b/x/bond/params.go @@ -10,7 +10,7 @@ import ( ) // DefaultMaxBondAmountTokens are the default parameter values. -var DefaultMaxBondAmountTokens = sdkmath.NewInt(1000000000000) // 10^12 alnt +var DefaultMaxBondAmountTokens = sdkmath.NewInt(1000000000000) // 10^12 alps func NewParams(maxBondAmount sdk.Coin) Params { return Params{MaxBondAmount: maxBondAmount} diff --git a/x/registry/params.go b/x/registry/params.go index 858f1176..88f2a6f1 100644 --- a/x/registry/params.go +++ b/x/registry/params.go @@ -13,21 +13,21 @@ import ( // Default parameter values. var ( // DefaultRecordRent is the default record rent for 1 time period (see expiry time). - DefaultRecordRent = sdkmath.NewInt(1000000) // 10^6 alnt + DefaultRecordRent = sdkmath.NewInt(1000000) // 10^6 alps // DefaultRecordExpiryTime is the default record expiry time (1 year). DefaultRecordExpiryTime = time.Hour * 24 * 365 - DefaultAuthorityRent = sdkmath.NewInt(1000000) // 10^6 alnt + DefaultAuthorityRent = sdkmath.NewInt(1000000) // 10^6 alps DefaultAuthorityExpiryTime = time.Hour * 24 * 365 DefaultAuthorityGracePeriod = time.Hour * 24 * 2 DefaultAuthorityAuctionEnabled = false DefaultCommitsDuration = time.Hour * 24 DefaultRevealsDuration = time.Hour * 24 - DefaultCommitFee = sdkmath.NewInt(1000000) // 10^6 alnt - DefaultRevealFee = sdkmath.NewInt(1000000) // 10^6 alnt - DefaultMinimumBid = sdkmath.NewInt(5000000) // 5 * 10^6 alnt + DefaultCommitFee = sdkmath.NewInt(1000000) // 10^6 alps + DefaultRevealFee = sdkmath.NewInt(1000000) // 10^6 alps + DefaultMinimumBid = sdkmath.NewInt(5000000) // 5 * 10^6 alps ) // NewParams creates a new Params instance