forked from evmos/ethermint
-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Problem: native fee handler don't respect DefaultPriorityReduction
Solution: - vendor fee deduct decorator - a little refactor to remove `DeductTxCostsFromUserBalance` and call the DeductFees directly next: will modify the DeductFees to provide a different impl for parallel exec Apply suggestions from code review Signed-off-by: yihuang <[email protected]>
- Loading branch information
Showing
10 changed files
with
181 additions
and
43 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
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
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
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,133 @@ | ||
package ante | ||
|
||
import ( | ||
"fmt" | ||
|
||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" | ||
"github.com/cosmos/cosmos-sdk/x/auth/ante" | ||
"github.com/cosmos/cosmos-sdk/x/auth/types" | ||
) | ||
|
||
// DeductFeeDecorator deducts fees from the fee payer. The fee payer is the fee granter (if specified) or first signer of the tx. | ||
// If the fee payer does not have the funds to pay for the fees, return an 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 types.BankKeeper | ||
feegrantKeeper ante.FeegrantKeeper | ||
txFeeChecker ante.TxFeeChecker | ||
} | ||
|
||
func NewDeductFeeDecorator(ak ante.AccountKeeper, bk types.BankKeeper, fk ante.FeegrantKeeper, tfc ante.TxFeeChecker) DeductFeeDecorator { | ||
if tfc == nil { | ||
tfc = checkTxFeeWithValidatorMinGasPrices | ||
} | ||
|
||
return DeductFeeDecorator{ | ||
accountKeeper: ak, | ||
bankKeeper: bk, | ||
feegrantKeeper: fk, | ||
txFeeChecker: tfc, | ||
} | ||
} | ||
|
||
func (dfd DeductFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { | ||
feeTx, ok := tx.(sdk.FeeTx) | ||
if !ok { | ||
return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be a FeeTx") | ||
} | ||
|
||
if !simulate && ctx.BlockHeight() > 0 && feeTx.GetGas() == 0 { | ||
return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidGasLimit, "must provide positive gas") | ||
} | ||
|
||
var ( | ||
priority int64 | ||
err error | ||
) | ||
|
||
fee := feeTx.GetFee() | ||
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 | ||
} | ||
|
||
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 sdkerrors.Wrap(sdkerrors.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 sdkerrors.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 sdkerrors.Wrapf(err, "%s does not allow to pay fees for %s", feeGranter, feePayer) | ||
} | ||
} | ||
|
||
deductFeesFrom = feeGranter | ||
} | ||
|
||
deductFeesFromAcc := dfd.accountKeeper.GetAccount(ctx, deductFeesFrom) | ||
if deductFeesFromAcc == nil { | ||
return sdkerrors.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 | ||
} | ||
} | ||
|
||
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 sdkerrors.Wrapf(sdkerrors.ErrInsufficientFee, "invalid fee amount: %s", fees) | ||
} | ||
|
||
err := bankKeeper.SendCoinsFromAccountToModule(ctx, acc.GetAddress(), types.FeeCollectorName, fees) | ||
if err != nil { | ||
return sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, err.Error()) | ||
} | ||
|
||
return nil | ||
} |
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
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