refactor(x/auth/tx): Implement UnorderedTxManager tx validator (#21426)
This commit is contained in:
parent
58bbcd9d75
commit
17d864f6c0
@ -2,8 +2,10 @@ package ante
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -69,29 +71,41 @@ func (d *UnorderedTxDecorator) AnteHandle(
|
||||
_ bool,
|
||||
next sdk.AnteHandler,
|
||||
) (sdk.Context, error) {
|
||||
if err := d.ValidateTx(ctx, tx); err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
return next(ctx, tx, false)
|
||||
}
|
||||
|
||||
func (d *UnorderedTxDecorator) ValidateTx(ctx context.Context, tx transaction.Tx) error {
|
||||
sdkTx, ok := tx.(sdk.Tx)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid tx type %T, expected sdk.Tx", tx)
|
||||
}
|
||||
|
||||
unorderedTx, ok := tx.(sdk.TxWithUnordered)
|
||||
if !ok || !unorderedTx.GetUnordered() {
|
||||
// If the transaction does not implement unordered capabilities or has the
|
||||
// unordered value as false, we bypass.
|
||||
return next(ctx, tx, false)
|
||||
return nil
|
||||
}
|
||||
|
||||
headerInfo := d.env.HeaderService.HeaderInfo(ctx)
|
||||
timeoutTimestamp := unorderedTx.GetTimeoutTimeStamp()
|
||||
if timeoutTimestamp.IsZero() || timeoutTimestamp.Unix() == 0 {
|
||||
return ctx, errorsmod.Wrap(
|
||||
return errorsmod.Wrap(
|
||||
sdkerrors.ErrInvalidRequest,
|
||||
"unordered transaction must have timeout_timestamp set",
|
||||
)
|
||||
}
|
||||
if timeoutTimestamp.Before(headerInfo.Time) {
|
||||
return ctx, errorsmod.Wrap(
|
||||
return errorsmod.Wrap(
|
||||
sdkerrors.ErrInvalidRequest,
|
||||
"unordered transaction has a timeout_timestamp that has already passed",
|
||||
)
|
||||
}
|
||||
if timeoutTimestamp.After(headerInfo.Time.Add(d.maxTimeoutDuration)) {
|
||||
return ctx, errorsmod.Wrapf(
|
||||
return errorsmod.Wrapf(
|
||||
sdkerrors.ErrInvalidRequest,
|
||||
"unordered tx ttl exceeds %s",
|
||||
d.maxTimeoutDuration.String(),
|
||||
@ -100,24 +114,24 @@ func (d *UnorderedTxDecorator) AnteHandle(
|
||||
|
||||
// consume gas in all exec modes to avoid gas estimation discrepancies
|
||||
if err := d.env.GasService.GasMeter(ctx).Consume(d.sha256Cost, "consume gas for calculating tx hash"); err != nil {
|
||||
return ctx, errorsmod.Wrap(sdkerrors.ErrOutOfGas, "out of gas")
|
||||
return errorsmod.Wrap(sdkerrors.ErrOutOfGas, "out of gas")
|
||||
}
|
||||
|
||||
// Avoid checking for duplicates and creating the identifier in simulation mode
|
||||
// This is done to avoid sha256 computation in simulation mode
|
||||
if d.env.TransactionService.ExecMode(ctx) == transaction.ExecModeSimulate {
|
||||
return next(ctx, tx, false)
|
||||
return nil
|
||||
}
|
||||
|
||||
// calculate the tx hash
|
||||
txHash, err := TxIdentifier(uint64(timeoutTimestamp.Unix()), tx)
|
||||
txHash, err := TxIdentifier(uint64(timeoutTimestamp.Unix()), sdkTx)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
return err
|
||||
}
|
||||
|
||||
// check for duplicates
|
||||
if d.txManager.Contains(txHash) {
|
||||
return ctx, errorsmod.Wrap(
|
||||
return errorsmod.Wrap(
|
||||
sdkerrors.ErrInvalidRequest,
|
||||
"tx %X is duplicated",
|
||||
)
|
||||
@ -127,7 +141,7 @@ func (d *UnorderedTxDecorator) AnteHandle(
|
||||
d.txManager.Add(txHash, timeoutTimestamp)
|
||||
}
|
||||
|
||||
return next(ctx, tx, false)
|
||||
return nil
|
||||
}
|
||||
|
||||
// TxIdentifier returns a unique identifier for a transaction that is intended to be unordered.
|
||||
|
||||
@ -121,8 +121,9 @@ func ProvideModule(in ModuleInputs) ModuleOutputs {
|
||||
)
|
||||
|
||||
var (
|
||||
minGasPrices sdk.DecCoins
|
||||
feeTxValidator *ante.DeductFeeDecorator
|
||||
minGasPrices sdk.DecCoins
|
||||
feeTxValidator *ante.DeductFeeDecorator
|
||||
unorderedTxValidator *ante.UnorderedTxDecorator
|
||||
)
|
||||
if in.AccountKeeper != nil && in.BankKeeper != nil && in.Viper != nil {
|
||||
minGasPricesStr := in.Viper.GetString(flagMinGasPricesV2)
|
||||
@ -135,8 +136,12 @@ func ProvideModule(in ModuleInputs) ModuleOutputs {
|
||||
feeTxValidator.SetMinGasPrices(minGasPrices) // set min gas price in deduct fee decorator
|
||||
}
|
||||
|
||||
if in.UnorderedTxManager != nil {
|
||||
unorderedTxValidator = ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxTimeoutDuration, in.UnorderedTxManager, in.Environment, ante.DefaultSha256Cost)
|
||||
}
|
||||
|
||||
return ModuleOutputs{
|
||||
Module: NewAppModule(svd, feeTxValidator, in.ExtraTxValidators...),
|
||||
Module: NewAppModule(svd, feeTxValidator, unorderedTxValidator, in.ExtraTxValidators...),
|
||||
BaseAppOption: newBaseAppOption(txConfig, in),
|
||||
TxConfig: txConfig,
|
||||
TxConfigOptions: txConfigOptions,
|
||||
|
||||
@ -18,8 +18,9 @@ var (
|
||||
// Additionally, it registers tx validators that do not really have a place in other modules.
|
||||
// This module is only useful for chains using server/v2. Ante/Post handlers are setup via baseapp options in depinject.
|
||||
type AppModule struct {
|
||||
sigVerification ante.SigVerificationDecorator
|
||||
feeTxValidator *ante.DeductFeeDecorator
|
||||
sigVerification ante.SigVerificationDecorator
|
||||
feeTxValidator *ante.DeductFeeDecorator
|
||||
unorderTxValidator *ante.UnorderedTxDecorator
|
||||
// txValidators contains tx validator that can be injected into the module via depinject.
|
||||
// tx validators should be module based, but it can happen that you do not want to create a new module
|
||||
// and simply depinject-it.
|
||||
@ -30,12 +31,14 @@ type AppModule struct {
|
||||
func NewAppModule(
|
||||
sigVerification ante.SigVerificationDecorator,
|
||||
feeTxValidator *ante.DeductFeeDecorator,
|
||||
unorderTxValidator *ante.UnorderedTxDecorator,
|
||||
txValidators ...appmodulev2.TxValidator[transaction.Tx],
|
||||
) AppModule {
|
||||
return AppModule{
|
||||
sigVerification: sigVerification,
|
||||
feeTxValidator: feeTxValidator,
|
||||
txValidators: txValidators,
|
||||
sigVerification: sigVerification,
|
||||
feeTxValidator: feeTxValidator,
|
||||
unorderTxValidator: unorderTxValidator,
|
||||
txValidators: txValidators,
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,5 +60,11 @@ func (a AppModule) TxValidator(ctx context.Context, tx transaction.Tx) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if a.unorderTxValidator != nil {
|
||||
if err := a.unorderTxValidator.ValidateTx(ctx, tx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return a.sigVerification.ValidateTx(ctx, tx)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user