Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feemarket] Add feemarket module #592

Open
wants to merge 3 commits into
base: add-block-lanes
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 43 additions & 31 deletions app/ante.go
Original file line number Diff line number Diff line change
@@ -1,39 +1,56 @@
package band

import (
feemarketante "github.com/skip-mev/feemarket/x/feemarket/ante"
feemarketkeeper "github.com/skip-mev/feemarket/x/feemarket/keeper"

ibcante "github.com/cosmos/ibc-go/v8/modules/core/ante"
ibckeeper "github.com/cosmos/ibc-go/v8/modules/core/keeper"

storetypes "cosmossdk.io/store/types"
txsigning "cosmossdk.io/x/tx/signing"

"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"

"github.com/bandprotocol/chain/v3/app/mempool"
bandtsskeeper "github.com/bandprotocol/chain/v3/x/bandtss/keeper"
feedskeeper "github.com/bandprotocol/chain/v3/x/feeds/keeper"
"github.com/bandprotocol/chain/v3/x/globalfee/feechecker"
globalfeekeeper "github.com/bandprotocol/chain/v3/x/globalfee/keeper"
oraclekeeper "github.com/bandprotocol/chain/v3/x/oracle/keeper"
tsskeeper "github.com/bandprotocol/chain/v3/x/tss/keeper"
)

// UseFeeMarketDecorator to make the integration testing easier: we can switch off its ante and post decorators with this flag
var UseFeeMarketDecorator = true

// HandlerOptions extend the SDK's AnteHandler options by requiring the IBC
// channel keeper.
type HandlerOptions struct {
ante.HandlerOptions
Cdc codec.Codec
Cdc codec.Codec
ExtensionOptionChecker ante.ExtensionOptionChecker
SignModeHandler *txsigning.HandlerMap
SigGasConsumer func(meter storetypes.GasMeter, sig signing.SignatureV2, params authtypes.Params) error
TxFeeChecker ante.TxFeeChecker

AccountKeeper feemarketante.AccountKeeper
BankKeeper feemarketante.BankKeeper
FeegrantKeeper ante.FeegrantKeeper
AuthzKeeper *authzkeeper.Keeper
OracleKeeper *oraclekeeper.Keeper
IBCKeeper *ibckeeper.Keeper
StakingKeeper *stakingkeeper.Keeper
GlobalfeeKeeper *globalfeekeeper.Keeper
FeeMarketKeeper *feemarketkeeper.Keeper
TSSKeeper *tsskeeper.Keeper
BandtssKeeper *bandtsskeeper.Keeper
FeedsKeeper *feedskeeper.Keeper
Lanes []*mempool.Lane

Lanes []*mempool.Lane
}

func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
Expand Down Expand Up @@ -70,45 +87,22 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
if options.StakingKeeper == nil {
return nil, sdkerrors.ErrLogic.Wrap("Staking keeper is required for AnteHandler")
}
if options.GlobalfeeKeeper == nil {
return nil, sdkerrors.ErrLogic.Wrap("Globalfee keeper is required for AnteHandler")
if options.FeeMarketKeeper == nil {
return nil, sdkerrors.ErrLogic.Wrap("FeeMarket keeper is required for AnteHandler")
}

sigGasConsumer := options.SigGasConsumer
if sigGasConsumer == nil {
sigGasConsumer = ante.DefaultSigVerificationGasConsumer
}

if options.TxFeeChecker == nil {
feeChecker := feechecker.NewFeeChecker(
options.Cdc,
options.AuthzKeeper,
options.OracleKeeper,
options.GlobalfeeKeeper,
options.StakingKeeper,
options.TSSKeeper,
options.BandtssKeeper,
options.FeedsKeeper,
)
options.TxFeeChecker = feeChecker.CheckTxFee
}

anteDecorators := []sdk.AnteDecorator{
ante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first(),
ante.NewExtensionOptionsDecorator(options.ExtensionOptionChecker),
ante.NewValidateBasicDecorator(),
ante.NewTxTimeoutHeightDecorator(),
ante.NewValidateMemoDecorator(options.AccountKeeper),
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
NewIgnoreDecorator(
ante.NewDeductFeeDecorator(
options.AccountKeeper,
options.BankKeeper,
options.FeegrantKeeper,
options.TxFeeChecker,
),
options.Lanes...,
),
// SetPubKeyDecorator must be called before all signature verification decorators
ante.NewSetPubKeyDecorator(options.AccountKeeper),
ante.NewValidateSigCountDecorator(options.AccountKeeper),
Expand All @@ -118,6 +112,24 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
ibcante.NewRedundantRelayDecorator(options.IBCKeeper),
}

if UseFeeMarketDecorator {
anteDecorators = append(anteDecorators,
NewIgnoreDecorator(
feemarketante.NewFeeMarketCheckDecorator(
options.AccountKeeper,
options.BankKeeper,
options.FeegrantKeeper,
options.FeeMarketKeeper,
ante.NewDeductFeeDecorator(
options.AccountKeeper,
options.BankKeeper,
options.FeegrantKeeper,
options.TxFeeChecker)),
options.Lanes...,
),
)
}

return sdk.ChainAnteDecorators(anteDecorators...), nil
}

Expand Down
86 changes: 67 additions & 19 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os"
"path/filepath"

feemarketkeeper "github.com/skip-mev/feemarket/x/feemarket/keeper"
"github.com/spf13/cast"

abci "github.com/cometbft/cometbft/abci/types"
Expand All @@ -21,6 +22,7 @@ import (
"cosmossdk.io/client/v2/autocli"
"cosmossdk.io/core/appmodule"
"cosmossdk.io/log"
"cosmossdk.io/math"
"cosmossdk.io/x/tx/signing"
upgradetypes "cosmossdk.io/x/upgrade/types"

Expand All @@ -40,6 +42,7 @@ import (
"github.com/cosmos/cosmos-sdk/std"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/types/msgservice"
sigtypes "github.com/cosmos/cosmos-sdk/types/tx/signing"
Expand All @@ -55,7 +58,7 @@ import (
"github.com/bandprotocol/chain/v3/app/keepers"
"github.com/bandprotocol/chain/v3/app/mempool"
"github.com/bandprotocol/chain/v3/app/upgrades"
v3 "github.com/bandprotocol/chain/v3/app/upgrades/v3"
v3 "github.com/bandprotocol/chain/v3/app/upgrades/v3_mainnet"
nodeservice "github.com/bandprotocol/chain/v3/client/grpc/node"
proofservice "github.com/bandprotocol/chain/v3/client/grpc/oracle/proof"
oraclekeeper "github.com/bandprotocol/chain/v3/x/oracle/keeper"
Expand Down Expand Up @@ -269,43 +272,49 @@ func NewBandApp(

anteHandler, err := NewAnteHandler(
HandlerOptions{
HandlerOptions: ante.HandlerOptions{
AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
SignModeHandler: txConfig.SignModeHandler(),
FeegrantKeeper: app.FeeGrantKeeper,
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
},
Cdc: app.appCodec,
SignModeHandler: txConfig.SignModeHandler(),
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
TxFeeChecker: func(ctx sdk.Context, tx sdk.Tx) (sdk.Coins, int64, error) {
return minTxFeesChecker(ctx, tx, *app.FeeMarketKeeper)
},

AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
FeegrantKeeper: app.FeeGrantKeeper,
AuthzKeeper: &app.AuthzKeeper,
OracleKeeper: &app.OracleKeeper,
IBCKeeper: app.IBCKeeper,
StakingKeeper: app.StakingKeeper,
FeeMarketKeeper: app.FeeMarketKeeper,
TSSKeeper: app.TSSKeeper,
BandtssKeeper: &app.BandtssKeeper,
FeedsKeeper: &app.FeedsKeeper,
IBCKeeper: app.IBCKeeper,
StakingKeeper: app.StakingKeeper,
GlobalfeeKeeper: &app.GlobalFeeKeeper,
Lanes: []*mempool.Lane{feedsLane, tssLane, oracleLane}, // every lane except default lane

Lanes: []*mempool.Lane{feedsLane, tssLane, oracleLane}, // every lane except default lane
},
)
if err != nil {
panic(fmt.Errorf("failed to create ante handler: %s", err))
}

postHandlerOptions := PostHandlerOptions{
AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
FeeMarketKeeper: app.FeeMarketKeeper,
}
postHandler, err := NewPostHandler(postHandlerOptions)
if err != nil {
panic(err)
}

// proposal handler
proposalHandler := mempool.NewProposalHandler(app.Logger(), txConfig.TxDecoder(), bandMempool)

// set the Prepare / ProcessProposal Handlers on the app to be the `LanedMempool`'s
app.SetPrepareProposal(proposalHandler.PrepareProposalHandler())
app.SetProcessProposal(proposalHandler.ProcessProposalHandler())

postHandler, err := NewPostHandler(
PostHandlerOptions{},
)
if err != nil {
panic(fmt.Errorf("failed to create post handler: %s", err))
}

// set ante and post handlers
app.SetAnteHandler(anteHandler)
app.SetPostHandler(postHandler)
Expand Down Expand Up @@ -527,3 +536,42 @@ func (app *BandApp) AutoCliOpts() autocli.AppOptions {
ConsensusAddressCodec: authcodec.NewBech32Codec(sdk.GetConfig().GetBech32ConsensusAddrPrefix()),
}
}

// minTxFeesChecker will be executed only if the feemarket module is disabled.
// In this case, the auth module's DeductFeeDecorator is executed, and
// we use the minTxFeesChecker to enforce the minimum transaction fees.
// Min tx fees are calculated as gas_limit * feemarket_min_base_gas_price
func minTxFeesChecker(ctx sdk.Context, tx sdk.Tx, feemarketKp feemarketkeeper.Keeper) (sdk.Coins, int64, error) {
feeTx, ok := tx.(sdk.FeeTx)
if !ok {
return nil, 0, sdkerrors.ErrTxDecode.Wrap("tx must be FeeTx")
}

// To keep the gentxs with zero fees, we need to skip the validation in the first block
if ctx.BlockHeight() == 0 {
return feeTx.GetFee(), 0, nil
}

feeMarketParams, err := feemarketKp.GetParams(ctx)
if err != nil {
return nil, 0, err
}

feeRequired := sdk.NewCoins(
sdk.NewCoin(
feeMarketParams.FeeDenom,
feeMarketParams.MinBaseGasPrice.MulInt(math.NewIntFromUint64(feeTx.GetGas())).Ceil().RoundInt()))

feeCoins := feeTx.GetFee()
if len(feeCoins) != 1 {
return nil, 0, fmt.Errorf(
"expected exactly one fee coin; got %s, required: %s", feeCoins.String(), feeRequired.String())
}

if !feeCoins.IsAnyGTE(feeRequired) {
return nil, 0, fmt.Errorf(
"not enough fees provided; got %s, required: %s", feeCoins.String(), feeRequired.String())
}

return feeTx.GetFee(), 0, nil
}
18 changes: 11 additions & 7 deletions app/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"encoding/json"
"time"

feemarkettypes "github.com/skip-mev/feemarket/x/feemarket/types"

"github.com/cosmos/ibc-go/modules/capability"
capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types"
icagenesistypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/genesis/types"
Expand Down Expand Up @@ -41,12 +43,11 @@ import (
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"

v3 "github.com/bandprotocol/chain/v3/app/upgrades/v3"
v3 "github.com/bandprotocol/chain/v3/app/upgrades/v3_mainnet"
"github.com/bandprotocol/chain/v3/x/bandtss"
bandtsstypes "github.com/bandprotocol/chain/v3/x/bandtss/types"
"github.com/bandprotocol/chain/v3/x/feeds"
feedstypes "github.com/bandprotocol/chain/v3/x/feeds/types"
globalfeetypes "github.com/bandprotocol/chain/v3/x/globalfee/types"
"github.com/bandprotocol/chain/v3/x/oracle"
oracletypes "github.com/bandprotocol/chain/v3/x/oracle/types"
"github.com/bandprotocol/chain/v3/x/restake"
Expand Down Expand Up @@ -74,7 +75,7 @@ func NewDefaultGenesisState(cdc codec.Codec) GenesisState {
crisisGenesis := crisistypes.DefaultGenesisState()
slashingGenesis := slashingtypes.DefaultGenesisState()
icaGenesis := icagenesistypes.DefaultGenesis()
globalfeeGenesis := globalfeetypes.DefaultGenesisState()
feemarketGenesis := feemarkettypes.DefaultGenesisState()
// Override the genesis parameters.
authGenesis.Params.TxSizeCostPerByte = 5
stakingGenesis.Params.BondDenom = denom
Expand Down Expand Up @@ -102,9 +103,12 @@ func NewDefaultGenesisState(cdc codec.Codec) GenesisState {
AllowMessages: v3.ICAAllowMessages,
}

globalfeeGenesis.Params.MinimumGasPrices = sdk.NewDecCoins(
sdk.NewDecCoinFromDec(denom, math.LegacyNewDecWithPrec(25, 4)), // 0.0025uband
)
feemarketGenesis.Params.MaxBlockUtilization = 50_000_000
feemarketGenesis.Params.MinBaseGasPrice = math.LegacyNewDecWithPrec(25, 4) // 0.0025uband
feemarketGenesis.Params.FeeDenom = denom
feemarketGenesis.Params.Enabled = false

feemarketGenesis.State.BaseGasPrice = math.LegacyNewDecWithPrec(25, 4) // 0.0025uband

return GenesisState{
authtypes.ModuleName: cdc.MustMarshalJSON(authGenesis),
Expand All @@ -125,13 +129,13 @@ func NewDefaultGenesisState(cdc codec.Codec) GenesisState {
ibctransafertypes.ModuleName: ibctransfer.AppModuleBasic{}.DefaultGenesis(cdc),
icatypes.ModuleName: cdc.MustMarshalJSON(icaGenesis),
ibcfeetypes.ModuleName: ibcfee.AppModuleBasic{}.DefaultGenesis(cdc),
feemarkettypes.ModuleName: cdc.MustMarshalJSON(feemarketGenesis),
rollingseedtypes.ModuleName: rollingseed.AppModuleBasic{}.DefaultGenesis(cdc),
oracletypes.ModuleName: oracle.AppModuleBasic{}.DefaultGenesis(cdc),
tsstypes.ModuleName: tss.AppModuleBasic{}.DefaultGenesis(cdc),
bandtsstypes.ModuleName: bandtss.AppModuleBasic{}.DefaultGenesis(cdc),
feedstypes.ModuleName: feeds.AppModuleBasic{}.DefaultGenesis(cdc),
tunneltypes.ModuleName: tunnel.AppModuleBasic{}.DefaultGenesis(cdc),
globalfeetypes.ModuleName: cdc.MustMarshalJSON(globalfeeGenesis),
restaketypes.ModuleName: restake.AppModuleBasic{}.DefaultGenesis(cdc),
}
}
Loading
Loading