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

feat: Integrate feemarket + reworked ante, post handler decorator distinction #782

Merged
merged 38 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
89c3505
feat: integrated feemarket
vishal-kanna Aug 27, 2024
defe327
chore: updated anteHandler and postHandler
vishal-kanna Aug 28, 2024
5e33e65
chore: use replace for feemarket in go.mod
vishal-kanna Aug 28, 2024
d5667f0
chore: changed go version in docker file
vishal-kanna Aug 29, 2024
8684ce9
fix : fix testing in antehandler
vishal-kanna Aug 29, 2024
ea06beb
fix: fix lint issues
vishal-kanna Aug 29, 2024
d09e816
chore: updated antehandler
vishal-kanna Aug 29, 2024
adcd9f3
fix: fix lint issues
vishal-kanna Aug 29, 2024
e2f6a74
fix: fix lint issues
vishal-kanna Aug 29, 2024
f016460
fix: lint issus
vishal-kanna Aug 29, 2024
36202e4
chore: updated ante and fix test cases
vishal-kanna Aug 30, 2024
945b3cc
fix: gofumt errors
vishal-kanna Aug 30, 2024
74089c2
fix: golint issues
vishal-kanna Aug 30, 2024
4256d7f
chore: updated postHandler
vishal-kanna Aug 30, 2024
acd8d74
testing
vishal-kanna Sep 3, 2024
4779b6a
chore: added test cases
vishal-kanna Sep 4, 2024
9557978
fix
vishal-kanna Sep 4, 2024
044bc3d
fix
vishal-kanna Sep 4, 2024
b2b8502
fix: golint issues
vishal-kanna Sep 4, 2024
e2866fb
fix : fix testcase
vishal-kanna Sep 5, 2024
9bcd0cb
fix: fix lint issues
vishal-kanna Sep 5, 2024
64c505d
disable update tests
vishal-kanna Sep 5, 2024
b05f6ee
disable report test
vishal-kanna Sep 5, 2024
9af6f82
fix: added response check in tests
vishal-kanna Sep 5, 2024
6181458
fix
vishal-kanna Sep 5, 2024
33403e1
chore: added param subsace for feemarket
vishal-kanna Sep 6, 2024
05fa0ec
addressed review comments
vishal-kanna Sep 10, 2024
281af5e
chore: merged feemarket integration PR
vishal-kanna Sep 10, 2024
0c5a67b
fix
vishal-kanna Sep 10, 2024
1fd19a2
fix
vishal-kanna Sep 10, 2024
cb727e6
fix
vishal-kanna Sep 10, 2024
611e181
TODO in app.go
vishal-kanna Sep 10, 2024
af939e1
fix: golint error
vishal-kanna Sep 10, 2024
15b751a
Temporarily disabled upgrade test runs + references
Eengineer1 Sep 18, 2024
9a64ed4
chore: added upgradeHandler and upgraded the store loader
vishal-kanna Sep 19, 2024
bd49157
Merge branch 'vishal/integrate-antehandler' of https://github.com/che…
vishal-kanna Sep 19, 2024
55441ec
Removed redundant
Eengineer1 Sep 20, 2024
77f34f5
Bump gas adjustment
Eengineer1 Sep 20, 2024
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
48 changes: 24 additions & 24 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ jobs:
path: report-integration.xml

# NOTE: This job is disabled since upgrade tests from v0.6.x to v1.x.x are not needed until next major release.
upgrade-tests:
# upgrade-tests:
name: "Upgrade Tests"
runs-on: ubuntu-20.04
steps:
Expand Down Expand Up @@ -302,8 +302,8 @@ jobs:
name: "Report"
runs-on: ubuntu-20.04
# NOTE: If not next major release, only unit and integration tests are necessary, otherwise all tests are needed.
# needs: [unit-tests, integration-tests]
needs: [unit-tests, integration-tests, upgrade-tests]
needs: [unit-tests, integration-tests]
# needs: [unit-tests, integration-tests, upgrade-tests]
if: always()

steps:
Expand All @@ -319,34 +319,34 @@ jobs:
with:
name: report-integration.xml

- name: Download pre-upgrade test Report
uses: actions/download-artifact@v4
with:
name: report-pre-upgrade.xml
# - name: Download pre-upgrade test Report
# uses: actions/download-artifact@v4
# with:
# name: report-pre-upgrade.xml

- name: Download post-upgrade test Report
uses: actions/download-artifact@v4
with:
name: report-post-upgrade.xml
# - name: Download post-upgrade test Report
# uses: actions/download-artifact@v4
# with:
# name: report-post-upgrade.xml

- name: Download upgraded integration test Report
uses: actions/download-artifact@v4
with:
name: report-upgraded-integration.xml
# - name: Download upgraded integration test Report
# uses: actions/download-artifact@v4
# with:
# name: report-upgraded-integration.xml

- name: Download pricing proposal test Report
uses: actions/download-artifact@v4
with:
name: report-pricing-proposal.xml
# - name: Download pricing proposal test Report
# uses: actions/download-artifact@v4
# with:
# name: report-pricing-proposal.xml

- name: Download pricing change test Report
uses: actions/download-artifact@v4
with:
name: report-pricing-change.xml
# - name: Download pricing change test Report
# uses: actions/download-artifact@v4
# with:
# name: report-pricing-change.xml

- name: Combine test results
run: |
python ./.github/scripts/xml_combine.py report-unit.xml report-integration.xml report-pre-upgrade.xml report-post-upgrade.xml report-upgraded-integration.xml report-pricing-proposal.xml report-pricing-change.xml > report.xml
# python ./.github/scripts/xml_combine.py report-unit.xml report-integration.xml
# run: |
# python ./.github/scripts/xml_combine.py report-unit.xml report-integration.xml > report.xml

Expand Down
23 changes: 23 additions & 0 deletions ante/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
didtypes "github.com/cheqd/cheqd-node/x/did/types"
resourcetypes "github.com/cheqd/cheqd-node/x/resource/types"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
feemarkettypes "github.com/skip-mev/feemarket/x/feemarket/types"
)

type BankKeeper interface {
Expand All @@ -12,6 +14,7 @@ type BankKeeper interface {
SendCoinsFromModuleToModule(ctx sdk.Context, senderModule, recipientModule string, amt sdk.Coins) error
BurnCoins(ctx sdk.Context, name string, amt sdk.Coins) error
IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error
SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error
}

type DidKeeper interface {
Expand All @@ -21,3 +24,23 @@ type DidKeeper interface {
type ResourceKeeper interface {
GetParams(ctx sdk.Context) (params resourcetypes.FeeParams)
}
type AccountKeeper interface {
GetParams(ctx sdk.Context) (params authtypes.Params)
GetAccount(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI
SetAccount(ctx sdk.Context, acc authtypes.AccountI)
GetModuleAddress(moduleName string) sdk.AccAddress
GetModuleAccount(ctx sdk.Context, name string) authtypes.ModuleAccountI
NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI
}
type FeeGrantKeeper interface {
UseGrantedFees(ctx sdk.Context, granter, grantee sdk.AccAddress, fee sdk.Coins, msgs []sdk.Msg) error
}

type FeeMarketKeeper interface {
GetState(ctx sdk.Context) (feemarkettypes.State, error)
GetMinGasPrice(ctx sdk.Context, denom string) (sdk.DecCoin, error)
GetParams(ctx sdk.Context) (feemarkettypes.Params, error)
SetState(ctx sdk.Context, state feemarkettypes.State) error
SetParams(ctx sdk.Context, params feemarkettypes.Params) error
ResolveToDenom(ctx sdk.Context, coin sdk.DecCoin, denom string) (sdk.DecCoin, error)
}
183 changes: 49 additions & 134 deletions ante/fee.go
Eengineer1 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,43 +1,24 @@
package ante

import (
"fmt"

"github.com/cosmos/cosmos-sdk/types/errors"

errorsmod "cosmossdk.io/errors"
sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)

type TxFeeChecker func(ctx sdk.Context, tx sdk.Tx) (sdk.Coins, int64, error)

// DeductFeeDecorator deducts fees from the first signer of the tx
// If the first signer does not have the funds to pay for the fees, return with InsufficientFunds error
// Call next AnteHandler if fees successfully deducted
// CONTRACT: Tx must implement FeeTx interface to use DeductFeeDecorator
type DeductFeeDecorator struct {
accountKeeper ante.AccountKeeper
bankKeeper BankKeeper
feegrantKeeper ante.FeegrantKeeper
txFeeChecker TxFeeChecker
type OverAllDecorator struct {
decorators []sdk.AnteDecorator
}

func NewDeductFeeDecorator(ak ante.AccountKeeper, bk BankKeeper, fk ante.FeegrantKeeper, tfc TxFeeChecker) DeductFeeDecorator {
if tfc == nil {
tfc = checkTxFeeWithValidatorMinGasPrices
}

return DeductFeeDecorator{
accountKeeper: ak,
bankKeeper: bk,
feegrantKeeper: fk,
txFeeChecker: tfc,
func NewOverAllDecorator(decorators ...sdk.AnteDecorator) OverAllDecorator {
return OverAllDecorator{
decorators: decorators,
}
}

func (dfd DeductFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
func (dfd OverAllDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
feeTx, ok := tx.(sdk.FeeTx)
if !ok {
return ctx, errorsmod.Wrap(errors.ErrTxDecode, "Tx must be a FeeTx")
Expand All @@ -51,9 +32,6 @@ func (dfd DeductFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bo
priority int64
err error
)

fee := feeTx.GetFee()

// check if the tx is a taxable tx
// CONTRACT: Taxable tx is a tx that has at least 1 taxable related Msg.
taxable := IsTaxableTxLite(tx)
Expand All @@ -65,118 +43,55 @@ func (dfd DeductFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bo
return next(newCtx, tx, simulate)
}

// if not taxable, follow default
if !simulate {
fee, priority, err = dfd.txFeeChecker(ctx, tx)
if err != nil {
return ctx, err
}
}
if err := dfd.checkDeductFee(ctx, tx, fee); err != nil {
return ctx, err
handler := sdk.ChainAnteDecorators(dfd.decorators...)
newCtx, err := handler(ctx, tx, simulate)
if err != nil {
return newCtx, err
}

newCtx := ctx.WithPriority(priority)

return next(newCtx, tx, simulate)
}

func (dfd DeductFeeDecorator) checkDeductFee(ctx sdk.Context, sdkTx sdk.Tx, fee sdk.Coins) error {
feeTx, ok := sdkTx.(sdk.FeeTx)
if !ok {
return errorsmod.Wrap(errors.ErrTxDecode, "Tx must be a FeeTx")
}

if addr := dfd.accountKeeper.GetModuleAddress(types.FeeCollectorName); addr == nil {
return fmt.Errorf("fee collector module account (%s) has not been set", types.FeeCollectorName)
}

feePayer := feeTx.FeePayer()
feeGranter := feeTx.FeeGranter()
deductFeesFrom := feePayer

// if feegranter set deduct fee from feegranter account.
// this works with only when feegrant enabled.
if feeGranter != nil {
if dfd.feegrantKeeper == nil {
return errors.ErrInvalidRequest.Wrap("fee grants are not enabled")
} else if !feeGranter.Equals(feePayer) {
err := dfd.feegrantKeeper.UseGrantedFees(ctx, feeGranter, feePayer, fee, sdkTx.GetMsgs())
if err != nil {
return errorsmod.Wrapf(err, "%s does not not allow to pay fees for %s", feeGranter, feePayer)
}
}

deductFeesFrom = feeGranter
}

deductFeesFromAcc := dfd.accountKeeper.GetAccount(ctx, deductFeesFrom)
if deductFeesFromAcc == nil {
return errors.ErrUnknownAddress.Wrapf("fee payer address: %s does not exist", deductFeesFrom)
}

// deduct the fees
if !fee.IsZero() {
err := DeductFees(dfd.bankKeeper, ctx, deductFeesFromAcc, fee)
if err != nil {
return err
// CheckTxFee implements the logic for the fee market to check if a Tx has provided sufficient
// fees given the current state of the fee market. Returns an error if insufficient fees.
func CheckTxFee(ctx sdk.Context, gasPrice sdk.DecCoin, feeCoin sdk.Coin, feeGas int64, isAnte bool) (payCoin sdk.Coin, tip sdk.Coin, err error) {
payCoin = feeCoin
// Ensure that the provided fees meet the minimum
if !gasPrice.IsZero() {
var (
requiredFee sdk.Coin
consumedFee sdk.Coin
)

// Determine the required fees by multiplying each required minimum gas
// price by the gas, where fee = ceil(minGasPrice * gas).
gasConsumed := int64(ctx.GasMeter().GasConsumed())
gcDec := sdkmath.LegacyNewDec(gasConsumed)
glDec := sdkmath.LegacyNewDec(feeGas)

consumedFeeAmount := gasPrice.Amount.Mul(gcDec)
limitFee := gasPrice.Amount.Mul(glDec)

consumedFee = sdk.NewCoin(gasPrice.Denom, consumedFeeAmount.Ceil().RoundInt())
requiredFee = sdk.NewCoin(gasPrice.Denom, limitFee.Ceil().RoundInt())

if !payCoin.IsGTE(requiredFee) {
return sdk.Coin{}, sdk.Coin{}, errors.ErrInsufficientFee.Wrapf(
"got: %s required: %s, minGasPrice: %s, gas: %d",
payCoin,
requiredFee,
gasPrice,
gasConsumed,
)
}
}

events := sdk.Events{
sdk.NewEvent(
sdk.EventTypeTx,
sdk.NewAttribute(sdk.AttributeKeyFee, fee.String()),
sdk.NewAttribute(sdk.AttributeKeyFeePayer, deductFeesFrom.String()),
),
}
ctx.EventManager().EmitEvents(events)

return nil
}

// DeductFees deducts fees from the given account.
func DeductFees(bankKeeper types.BankKeeper, ctx sdk.Context, acc types.AccountI, fees sdk.Coins) error {
if !fees.IsValid() {
return errorsmod.Wrapf(errors.ErrInsufficientFee, "invalid fee amount: %s", fees)
}

err := bankKeeper.SendCoinsFromAccountToModule(ctx, acc.GetAddress(), types.FeeCollectorName, fees)
if err != nil {
return errorsmod.Wrapf(errors.ErrInsufficientFunds, err.Error())
}

return nil
}

func IsSufficientFee(ctx sdk.Context, tax, reward, burn, feeProvided sdk.Coins, gasRequested int64) (bool, int64, error) {
// check if the provided fee is enough for `did`, `resource` module specific Msg
if !feeProvided.IsAnyGTE(tax) {
return false, 0, errorsmod.Wrapf(errors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", feeProvided, tax)
}

// check with the default validator min gas prices based on rewards distribution
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 := sdk.NewDec(gasRequested)
for i, gp := range minGasPrices {
fee := gp.Amount.Mul(glDec)
requiredFees[i] = sdk.NewCoin(gp.Denom, fee.Ceil().RoundInt())
}

// check if the fee is sufficient
if !reward.IsAnyGTE(requiredFees) {
return false, 0, errorsmod.Wrapf(errors.ErrInsufficientFee, "insufficient fees; got: %s required: %s", reward, requiredFees)
}
if isAnte {
tip = payCoin.Sub(requiredFee)
payCoin = requiredFee
} else {
tip = payCoin.Sub(consumedFee)
payCoin = consumedFee
}
}

priority := getTxPriority(tax, gasRequested)

return true, priority, nil
return payCoin, tip, nil
}
Loading