refactor(x/**): rewrite ante handlers as tx validators (#20488)
Co-authored-by: Likhita Polavarapu <78951027+likhita-809@users.noreply.github.com>
This commit is contained in:
parent
d1aab15790
commit
2a5ff384fa
@ -23,6 +23,11 @@ COPY x/bank/go.mod x/bank/go.sum /work/x/bank/
|
||||
COPY x/mint/go.mod x/mint/go.sum /work/x/mint/
|
||||
COPY x/consensus/go.mod x/consensus/go.sum /work/x/consensus/
|
||||
COPY x/accounts/go.mod x/accounts/go.sum /work/x/accounts/
|
||||
COPY runtime/v2/go.mod runtime/v2/go.sum /work/runtime/v2/
|
||||
COPY server/v2/appmanager/go.mod server/v2/appmanager/go.sum /work/server/v2/appmanager/
|
||||
COPY server/v2/core/go.mod server/v2/core/go.sum /work/server/v2/core/
|
||||
COPY server/v2/stf/go.mod server/v2/stf/go.sum /work/server/v2/stf/
|
||||
|
||||
RUN go mod download
|
||||
|
||||
COPY ./ /work
|
||||
|
||||
1
go.mod
1
go.mod
@ -194,6 +194,7 @@ replace (
|
||||
cosmossdk.io/x/bank => ./x/bank
|
||||
cosmossdk.io/x/consensus => ./x/consensus
|
||||
cosmossdk.io/x/staking => ./x/staking
|
||||
cosmossdk.io/x/tx => ./x/tx
|
||||
)
|
||||
|
||||
// Below are the long-lived replace of the Cosmos SDK
|
||||
|
||||
2
go.sum
2
go.sum
@ -10,8 +10,6 @@ cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE=
|
||||
cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k=
|
||||
cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 h1:eb0kcGyaYHSS0do7+MIWg7UKlskSH01biRNENbm/zDA=
|
||||
cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5/go.mod h1:drzY4oVisyWvSgpsM7ccQ7IX3efMuVIvd9Eij1Gm/6o=
|
||||
cosmossdk.io/x/tx v0.13.3 h1:Ha4mNaHmxBc6RMun9aKuqul8yHiL78EKJQ8g23Zf73g=
|
||||
cosmossdk.io/x/tx v0.13.3/go.mod h1:I8xaHv0rhUdIvIdptKIqzYy27+n2+zBVaxO6fscFhys=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs=
|
||||
|
||||
@ -7,6 +7,7 @@ import (
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
|
||||
bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1"
|
||||
"cosmossdk.io/core/transaction"
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"cosmossdk.io/x/auth/signing"
|
||||
|
||||
@ -95,6 +96,22 @@ func NewTx(key, value string, accAddress sdk.AccAddress) *KVStoreTx {
|
||||
}
|
||||
}
|
||||
|
||||
func (msg *KVStoreTx) Hash() [32]byte {
|
||||
return [32]byte{}
|
||||
}
|
||||
|
||||
func (msg *KVStoreTx) GetGasLimit() (uint64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (msg *KVStoreTx) GetMessages() ([]transaction.Msg, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (msg *KVStoreTx) GetSenders() ([][]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (msg *KVStoreTx) Type() string {
|
||||
return "kvstore_tx"
|
||||
}
|
||||
|
||||
@ -23,6 +23,9 @@ func (t Tx) Hash() [32]byte {
|
||||
}
|
||||
|
||||
func (t Tx) GetMessages() ([]transaction.Msg, error) {
|
||||
if t.Msg == nil {
|
||||
return nil, errors.New("messages not available or are nil")
|
||||
}
|
||||
return []transaction.Msg{t.Msg}, nil
|
||||
}
|
||||
|
||||
|
||||
@ -38,7 +38,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
|
||||
circuitante.NewCircuitBreakerDecorator(options.CircuitKeeper),
|
||||
ante.NewExtensionOptionsDecorator(options.ExtensionOptionChecker),
|
||||
ante.NewValidateBasicDecorator(options.Environment),
|
||||
ante.NewTxTimeoutHeightDecorator(),
|
||||
ante.NewTxTimeoutHeightDecorator(options.Environment),
|
||||
ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxUnOrderedTTL, options.TxManager, options.Environment),
|
||||
ante.NewValidateMemoDecorator(options.AccountKeeper),
|
||||
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
|
||||
|
||||
@ -264,6 +264,7 @@ replace (
|
||||
cosmossdk.io/x/protocolpool => ../x/protocolpool
|
||||
cosmossdk.io/x/slashing => ../x/slashing
|
||||
cosmossdk.io/x/staking => ../x/staking
|
||||
cosmossdk.io/x/tx => ../x/tx
|
||||
cosmossdk.io/x/upgrade => ../x/upgrade
|
||||
)
|
||||
|
||||
|
||||
@ -194,8 +194,6 @@ cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0=
|
||||
cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U=
|
||||
cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE=
|
||||
cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k=
|
||||
cosmossdk.io/x/tx v0.13.3 h1:Ha4mNaHmxBc6RMun9aKuqul8yHiL78EKJQ8g23Zf73g=
|
||||
cosmossdk.io/x/tx v0.13.3/go.mod h1:I8xaHv0rhUdIvIdptKIqzYy27+n2+zBVaxO6fscFhys=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
|
||||
@ -257,6 +257,7 @@ replace (
|
||||
cosmossdk.io/x/protocolpool => ../x/protocolpool
|
||||
cosmossdk.io/x/slashing => ../x/slashing
|
||||
cosmossdk.io/x/staking => ../x/staking
|
||||
cosmossdk.io/x/tx => ../x/tx
|
||||
cosmossdk.io/x/upgrade => ../x/upgrade
|
||||
)
|
||||
|
||||
|
||||
@ -196,8 +196,6 @@ cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE=
|
||||
cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k=
|
||||
cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+D7cNLnX2JrUOQNoIPaF0Bg=
|
||||
cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU=
|
||||
cosmossdk.io/x/tx v0.13.3 h1:Ha4mNaHmxBc6RMun9aKuqul8yHiL78EKJQ8g23Zf73g=
|
||||
cosmossdk.io/x/tx v0.13.3/go.mod h1:I8xaHv0rhUdIvIdptKIqzYy27+n2+zBVaxO6fscFhys=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
_ "cosmossdk.io/api/cosmos/counter/v1"
|
||||
_ "cosmossdk.io/api/cosmos/crypto/secp256k1"
|
||||
"cosmossdk.io/core/log"
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/x/auth/signing"
|
||||
|
||||
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
|
||||
@ -75,6 +76,26 @@ var (
|
||||
_ cryptotypes.PubKey = (*testPubKey)(nil)
|
||||
)
|
||||
|
||||
func (tx testTx) Bytes() []byte {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
func (tx testTx) Hash() [32]byte {
|
||||
return [32]byte{}
|
||||
}
|
||||
|
||||
func (tx testTx) GetGasLimit() (uint64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (tx testTx) GetMessages() ([]transaction.Msg, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (tx testTx) GetSenders() ([][]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (tx testTx) GetMsgs() []sdk.Msg { return nil }
|
||||
|
||||
func (tx testTx) GetReflectMessages() ([]protoreflect.Message, error) { return nil, nil }
|
||||
@ -89,6 +110,26 @@ type sigErrTx struct {
|
||||
getSigs func() ([]txsigning.SignatureV2, error)
|
||||
}
|
||||
|
||||
func (sigErrTx) Bytes() []byte {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
func (sigErrTx) Hash() [32]byte {
|
||||
return [32]byte{}
|
||||
}
|
||||
|
||||
func (sigErrTx) GetGasLimit() (uint64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (sigErrTx) GetMessages() ([]transaction.Msg, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (sigErrTx) GetSenders() ([][]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (sigErrTx) Size() int64 { return 0 }
|
||||
|
||||
func (sigErrTx) GetMsgs() []sdk.Msg { return nil }
|
||||
|
||||
@ -8,6 +8,8 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
|
||||
"cosmossdk.io/core/transaction"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/mempool"
|
||||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||
@ -24,6 +26,26 @@ func (n nonVerifiableTx) GetReflectMessages() ([]protoreflect.Message, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (n nonVerifiableTx) Bytes() []byte {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
func (n nonVerifiableTx) Hash() [32]byte {
|
||||
return [32]byte{}
|
||||
}
|
||||
|
||||
func (n nonVerifiableTx) GetGasLimit() (uint64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (n nonVerifiableTx) GetMessages() ([]transaction.Msg, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (n nonVerifiableTx) GetSenders() ([][]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func TestDefaultSignerExtractor(t *testing.T) {
|
||||
accounts := simtypes.RandomAccounts(rand.New(rand.NewSource(0)), 1)
|
||||
sa := accounts[0].Address
|
||||
|
||||
@ -7,7 +7,7 @@ import (
|
||||
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
|
||||
coretransaction "cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/core/transaction"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
@ -16,7 +16,7 @@ import (
|
||||
|
||||
type (
|
||||
// Msg defines the interface a transaction message needed to fulfill.
|
||||
Msg = coretransaction.Msg
|
||||
Msg = transaction.Msg
|
||||
|
||||
// LegacyMsg defines the interface a transaction message needed to fulfill up through
|
||||
// v0.47.
|
||||
@ -51,6 +51,8 @@ type (
|
||||
|
||||
// Tx defines an interface a transaction must fulfill.
|
||||
Tx interface {
|
||||
transaction.Tx
|
||||
|
||||
HasMsgs
|
||||
|
||||
// GetReflectMessages gets a reflected version of the transaction's messages
|
||||
|
||||
@ -45,7 +45,7 @@ func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
|
||||
NewSetUpContextDecorator(options.Environment), // outermost AnteDecorator. SetUpContext must be called first
|
||||
NewExtensionOptionsDecorator(options.ExtensionOptionChecker),
|
||||
NewValidateBasicDecorator(options.Environment),
|
||||
NewTxTimeoutHeightDecorator(),
|
||||
NewTxTimeoutHeightDecorator(options.Environment),
|
||||
NewValidateMemoDecorator(options.AccountKeeper),
|
||||
NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
|
||||
NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package ante
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"cosmossdk.io/core/appmodule/v2"
|
||||
"cosmossdk.io/core/transaction"
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
@ -30,20 +32,30 @@ func NewValidateBasicDecorator(env appmodule.Environment) ValidateBasicDecorator
|
||||
}
|
||||
}
|
||||
|
||||
func (vbd ValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||
// AnteHandle implements an AnteHandler decorator for the ValidateBasicDecorator.
|
||||
func (vbd ValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
if err := vbd.ValidateTx(ctx, tx); err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
return next(ctx, tx, false)
|
||||
}
|
||||
|
||||
// ValidateTx implements an TxValidator for ValidateBasicDecorator
|
||||
func (vbd ValidateBasicDecorator) ValidateTx(ctx context.Context, tx sdk.Tx) error {
|
||||
// no need to validate basic on recheck tx, call next antehandler
|
||||
txService := vbd.env.TransactionService
|
||||
if txService.ExecMode(ctx) == transaction.ExecModeReCheck {
|
||||
return next(ctx, tx, false)
|
||||
return nil
|
||||
}
|
||||
|
||||
if validateBasic, ok := tx.(sdk.HasValidateBasic); ok {
|
||||
if err := validateBasic.ValidateBasic(); err != nil {
|
||||
return ctx, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return next(ctx, tx, false)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateMemoDecorator will validate memo given the parameters passed in
|
||||
@ -59,24 +71,34 @@ func NewValidateMemoDecorator(ak AccountKeeper) ValidateMemoDecorator {
|
||||
}
|
||||
}
|
||||
|
||||
func (vmd ValidateMemoDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||
// AnteHandle implements an AnteHandler decorator for the ValidateMemoDecorator.
|
||||
func (vmd ValidateMemoDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
if err := vmd.ValidateTx(ctx, tx); err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
return next(ctx, tx, false)
|
||||
}
|
||||
|
||||
// ValidateTx implements an TxValidator for ValidateMemoDecorator
|
||||
func (vmd ValidateMemoDecorator) ValidateTx(ctx context.Context, tx sdk.Tx) error {
|
||||
memoTx, ok := tx.(sdk.TxWithMemo)
|
||||
if !ok {
|
||||
return ctx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
|
||||
return errorsmod.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
|
||||
}
|
||||
|
||||
memoLength := len(memoTx.GetMemo())
|
||||
if memoLength > 0 {
|
||||
params := vmd.ak.GetParams(ctx)
|
||||
if uint64(memoLength) > params.MaxMemoCharacters {
|
||||
return ctx, errorsmod.Wrapf(sdkerrors.ErrMemoTooLarge,
|
||||
return errorsmod.Wrapf(sdkerrors.ErrMemoTooLarge,
|
||||
"maximum number of characters is %d but received %d characters",
|
||||
params.MaxMemoCharacters, memoLength,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return next(ctx, tx, false)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ConsumeTxSizeGasDecorator will take in parameters and consume gas proportional
|
||||
@ -98,14 +120,27 @@ func NewConsumeGasForTxSizeDecorator(ak AccountKeeper) ConsumeTxSizeGasDecorator
|
||||
}
|
||||
}
|
||||
|
||||
func (cgts ConsumeTxSizeGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||
// AnteHandle implements an AnteHandler decorator for the ConsumeTxSizeGasDecorator.
|
||||
func (cgts ConsumeTxSizeGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
if err := cgts.ValidateTx(ctx, tx); err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
return next(ctx, tx, false)
|
||||
}
|
||||
|
||||
// ValidateTx implements an TxValidator for ConsumeTxSizeGasDecorator
|
||||
func (cgts ConsumeTxSizeGasDecorator) ValidateTx(ctx context.Context, tx sdk.Tx) error {
|
||||
sigTx, ok := tx.(authsigning.SigVerifiableTx)
|
||||
if !ok {
|
||||
return ctx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "invalid tx type")
|
||||
return errorsmod.Wrap(sdkerrors.ErrTxDecode, "invalid tx type")
|
||||
}
|
||||
params := cgts.ak.GetParams(ctx)
|
||||
|
||||
ctx.GasMeter().ConsumeGas(params.TxSizeCostPerByte*storetypes.Gas(len(ctx.TxBytes())), "txSize")
|
||||
gasService := cgts.ak.GetEnvironment().GasService
|
||||
if err := gasService.GasMeter(ctx).Consume(params.TxSizeCostPerByte*storetypes.Gas(len(tx.Bytes())), "txSize"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// simulate gas cost for signatures in simulate mode
|
||||
txService := cgts.ak.GetEnvironment().TransactionService
|
||||
@ -113,7 +148,7 @@ func (cgts ConsumeTxSizeGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ b
|
||||
// in simulate mode, each element should be a nil signature
|
||||
sigs, err := sigTx.GetSignaturesV2()
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
return err
|
||||
}
|
||||
n := len(sigs)
|
||||
|
||||
@ -147,11 +182,13 @@ func (cgts ConsumeTxSizeGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ b
|
||||
cost *= params.TxSigLimit
|
||||
}
|
||||
|
||||
ctx.GasMeter().ConsumeGas(params.TxSizeCostPerByte*cost, "txSize")
|
||||
if err := gasService.GasMeter(ctx).Consume(params.TxSizeCostPerByte*cost, "txSize"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return next(ctx, tx, false)
|
||||
return nil
|
||||
}
|
||||
|
||||
// isIncompleteSignature tests whether SignatureData is fully filled in for simulation purposes
|
||||
@ -180,7 +217,9 @@ func isIncompleteSignature(data signing.SignatureData) bool {
|
||||
type (
|
||||
// TxTimeoutHeightDecorator defines an AnteHandler decorator that checks for a
|
||||
// tx height timeout.
|
||||
TxTimeoutHeightDecorator struct{}
|
||||
TxTimeoutHeightDecorator struct {
|
||||
env appmodule.Environment
|
||||
}
|
||||
|
||||
// TxWithTimeoutHeight defines the interface a tx must implement in order for
|
||||
// TxTimeoutHeightDecorator to process the tx.
|
||||
@ -193,26 +232,39 @@ type (
|
||||
|
||||
// TxTimeoutHeightDecorator defines an AnteHandler decorator that checks for a
|
||||
// tx height timeout.
|
||||
func NewTxTimeoutHeightDecorator() TxTimeoutHeightDecorator {
|
||||
return TxTimeoutHeightDecorator{}
|
||||
func NewTxTimeoutHeightDecorator(env appmodule.Environment) TxTimeoutHeightDecorator {
|
||||
return TxTimeoutHeightDecorator{
|
||||
env: env,
|
||||
}
|
||||
}
|
||||
|
||||
// AnteHandle implements an AnteHandler decorator for the TxTimeoutHeightDecorator
|
||||
// type where the current block height is checked against the tx's height timeout.
|
||||
// If a height timeout is provided (non-zero) and is less than the current block
|
||||
// height, then an error is returned.
|
||||
func (txh TxTimeoutHeightDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||
timeoutTx, ok := tx.(TxWithTimeoutHeight)
|
||||
if !ok {
|
||||
return ctx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "expected tx to implement TxWithTimeoutHeight")
|
||||
}
|
||||
|
||||
timeoutHeight := timeoutTx.GetTimeoutHeight()
|
||||
if timeoutHeight > 0 && uint64(ctx.BlockHeight()) > timeoutHeight {
|
||||
return ctx, errorsmod.Wrapf(
|
||||
sdkerrors.ErrTxTimeoutHeight, "block height: %d, timeout height: %d", ctx.BlockHeight(), timeoutHeight,
|
||||
)
|
||||
// AnteHandle implements an AnteHandler decorator for the TxHeightTimeoutDecorator.
|
||||
func (txh TxTimeoutHeightDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
if err := txh.ValidateTx(ctx, tx); err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
return next(ctx, tx, false)
|
||||
}
|
||||
|
||||
// ValidateTx implements an TxValidator for the TxHeightTimeoutDecorator
|
||||
// type where the current block height is checked against the tx's height timeout.
|
||||
// If a height timeout is provided (non-zero) and is less than the current block
|
||||
// height, then an error is returned.
|
||||
func (txh TxTimeoutHeightDecorator) ValidateTx(ctx context.Context, tx sdk.Tx) error {
|
||||
timeoutTx, ok := tx.(TxWithTimeoutHeight)
|
||||
if !ok {
|
||||
return errorsmod.Wrap(sdkerrors.ErrTxDecode, "expected tx to implement TxWithTimeoutHeight")
|
||||
}
|
||||
|
||||
timeoutHeight := timeoutTx.GetTimeoutHeight()
|
||||
headerInfo := txh.env.HeaderService.HeaderInfo(ctx)
|
||||
|
||||
if timeoutHeight > 0 && uint64(headerInfo.Height) > timeoutHeight {
|
||||
return errorsmod.Wrapf(
|
||||
sdkerrors.ErrTxTimeoutHeight, "block height: %d, timeout height: %d", headerInfo.Height, timeoutHeight,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
package ante_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"cosmossdk.io/core/appmodule/v2"
|
||||
"cosmossdk.io/core/header"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
"cosmossdk.io/x/auth/ante"
|
||||
|
||||
@ -95,6 +98,8 @@ func TestValidateMemo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestConsumeGasForTxSize(t *testing.T) {
|
||||
t.Skip() // TODO(@julienrbrt) Fix after https://github.com/cosmos/cosmos-sdk/pull/20072
|
||||
|
||||
suite := SetupTestSuite(t, true)
|
||||
|
||||
// keys and addresses
|
||||
@ -182,7 +187,8 @@ func TestConsumeGasForTxSize(t *testing.T) {
|
||||
func TestTxHeightTimeoutDecorator(t *testing.T) {
|
||||
suite := SetupTestSuite(t, true)
|
||||
|
||||
antehandler := sdk.ChainAnteDecorators(ante.NewTxTimeoutHeightDecorator())
|
||||
mockHeaderService := &mockHeaderService{}
|
||||
antehandler := sdk.ChainAnteDecorators(ante.NewTxTimeoutHeightDecorator(appmodule.Environment{HeaderService: mockHeaderService}))
|
||||
|
||||
// keys and addresses
|
||||
priv1, _, addr1 := testdata.KeyTestPubAddr()
|
||||
@ -221,9 +227,23 @@ func TestTxHeightTimeoutDecorator(t *testing.T) {
|
||||
tx, err := suite.CreateTestTx(suite.ctx, privs, accNums, accSeqs, suite.ctx.ChainID(), signing.SignMode_SIGN_MODE_DIRECT)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := suite.ctx.WithBlockHeight(tc.height)
|
||||
_, err = antehandler(ctx, tx, true)
|
||||
mockHeaderService.WithBlockHeight(tc.height)
|
||||
_, err = antehandler(suite.ctx, tx, true)
|
||||
require.ErrorIs(t, err, tc.expectedErr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type mockHeaderService struct {
|
||||
header.Service
|
||||
|
||||
exp header.Info
|
||||
}
|
||||
|
||||
func (m *mockHeaderService) HeaderInfo(_ context.Context) header.Info {
|
||||
return m.exp
|
||||
}
|
||||
|
||||
func (m *mockHeaderService) WithBlockHeight(height int64) {
|
||||
m.exp.Height = height
|
||||
}
|
||||
|
||||
@ -460,27 +460,37 @@ func NewValidateSigCountDecorator(ak AccountKeeper) ValidateSigCountDecorator {
|
||||
}
|
||||
}
|
||||
|
||||
func (vscd ValidateSigCountDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||
// AnteHandler implements an ante decorator for ValidateSigCountDecorator
|
||||
func (vscd ValidateSigCountDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, _ bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
if err := vscd.ValidateTx(ctx, tx); err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
return next(ctx, tx, false)
|
||||
}
|
||||
|
||||
// ValidateTx implements an TxValidator for ValidateSigCountDecorator
|
||||
func (vscd ValidateSigCountDecorator) ValidateTx(ctx context.Context, tx sdk.Tx) error {
|
||||
sigTx, ok := tx.(authsigning.SigVerifiableTx)
|
||||
if !ok {
|
||||
return ctx, errorsmod.Wrap(sdkerrors.ErrTxDecode, "Tx must be a sigTx")
|
||||
return errorsmod.Wrap(sdkerrors.ErrTxDecode, "Tx must be a sigTx")
|
||||
}
|
||||
|
||||
params := vscd.ak.GetParams(ctx)
|
||||
pubKeys, err := sigTx.GetPubKeys()
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
return err
|
||||
}
|
||||
|
||||
sigCount := 0
|
||||
for _, pk := range pubKeys {
|
||||
sigCount += CountSubKeys(pk)
|
||||
if uint64(sigCount) > params.TxSigLimit {
|
||||
return ctx, errorsmod.Wrapf(sdkerrors.ErrTooManySignatures, "signatures: %d, limit: %d", sigCount, params.TxSigLimit)
|
||||
return errorsmod.Wrapf(sdkerrors.ErrTooManySignatures, "signatures: %d, limit: %d", sigCount, params.TxSigLimit)
|
||||
}
|
||||
}
|
||||
|
||||
return next(ctx, tx, false)
|
||||
return nil
|
||||
}
|
||||
|
||||
// DefaultSigVerificationGasConsumer is the default implementation of SignatureVerificationGasConsumer. It consumes gas
|
||||
|
||||
@ -181,4 +181,5 @@ replace (
|
||||
cosmossdk.io/x/bank => ../bank
|
||||
cosmossdk.io/x/consensus => ../consensus
|
||||
cosmossdk.io/x/staking => ../staking
|
||||
cosmossdk.io/x/tx => ../tx
|
||||
)
|
||||
|
||||
@ -12,8 +12,6 @@ cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc h1:R9O9d75e0qZYUsVV0zzi+
|
||||
cosmossdk.io/store v1.1.1-0.20240418092142-896cdf1971bc/go.mod h1:amTTatOUV3u1PsKmNb87z6/galCxrRbz9kRdJkL0DyU=
|
||||
cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5 h1:eb0kcGyaYHSS0do7+MIWg7UKlskSH01biRNENbm/zDA=
|
||||
cosmossdk.io/x/accounts/defaults/lockup v0.0.0-20240417181816-5e7aae0db1f5/go.mod h1:drzY4oVisyWvSgpsM7ccQ7IX3efMuVIvd9Eij1Gm/6o=
|
||||
cosmossdk.io/x/tx v0.13.3 h1:Ha4mNaHmxBc6RMun9aKuqul8yHiL78EKJQ8g23Zf73g=
|
||||
cosmossdk.io/x/tx v0.13.3/go.mod h1:I8xaHv0rhUdIvIdptKIqzYy27+n2+zBVaxO6fscFhys=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs=
|
||||
|
||||
@ -9,14 +9,18 @@ import (
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"cosmossdk.io/core/appmodule"
|
||||
appmodulev2 "cosmossdk.io/core/appmodule/v2"
|
||||
"cosmossdk.io/core/legacy"
|
||||
"cosmossdk.io/core/registry"
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/x/auth/ante"
|
||||
"cosmossdk.io/x/auth/keeper"
|
||||
"cosmossdk.io/x/auth/simulation"
|
||||
"cosmossdk.io/x/auth/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||
)
|
||||
@ -31,10 +35,10 @@ var (
|
||||
_ module.AppModuleSimulation = AppModule{}
|
||||
_ module.HasName = AppModule{}
|
||||
|
||||
_ appmodule.HasGenesis = AppModule{}
|
||||
_ appmodule.AppModule = AppModule{}
|
||||
_ appmodule.HasServices = AppModule{}
|
||||
_ appmodule.HasMigrations = AppModule{}
|
||||
_ appmodulev2.HasGenesis = AppModule{}
|
||||
_ appmodulev2.AppModule = AppModule{}
|
||||
_ appmodule.HasServices = AppModule{}
|
||||
_ appmodulev2.HasMigrations = AppModule{}
|
||||
)
|
||||
|
||||
// AppModule implements an application module for the auth module.
|
||||
@ -150,7 +154,32 @@ func (am AppModule) ExportGenesis(ctx context.Context) (json.RawMessage, error)
|
||||
return am.cdc.MarshalJSON(gs)
|
||||
}
|
||||
|
||||
// ConsensusVersion implements HasConsensusVersion
|
||||
// TxValidator implements appmodulev2.HasTxValidator.
|
||||
// It replaces auth ante handlers for server/v2
|
||||
func (am AppModule) TxValidator(ctx context.Context, tx transaction.Tx) error {
|
||||
validators := []appmodulev2.TxValidator[sdk.Tx]{
|
||||
ante.NewValidateBasicDecorator(am.accountKeeper.GetEnvironment()),
|
||||
ante.NewTxTimeoutHeightDecorator(am.accountKeeper.GetEnvironment()),
|
||||
ante.NewValidateMemoDecorator(am.accountKeeper),
|
||||
ante.NewConsumeGasForTxSizeDecorator(am.accountKeeper),
|
||||
ante.NewValidateSigCountDecorator(am.accountKeeper),
|
||||
}
|
||||
|
||||
sdkTx, ok := tx.(sdk.Tx)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid tx type %T, expected sdk.Tx", tx)
|
||||
}
|
||||
|
||||
for _, validator := range validators {
|
||||
if err := validator.ValidateTx(ctx, sdkTx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ConsensusVersion implements appmodule.HasConsensusVersion
|
||||
func (AppModule) ConsensusVersion() uint64 { return ConsensusVersion }
|
||||
|
||||
// AppModuleSimulation functions
|
||||
|
||||
@ -33,11 +33,11 @@ func newBuilder(addressCodec address.Codec, decoder *decode.Decoder, codec codec
|
||||
}
|
||||
|
||||
func newBuilderFromDecodedTx(addrCodec address.Codec, decoder *decode.Decoder, codec codec.BinaryCodec, decoded *gogoTxWrapper) (*builder, error) {
|
||||
signatures := make([][]byte, len(decoded.decodedTx.Tx.Signatures))
|
||||
copy(signatures, decoded.decodedTx.Tx.Signatures)
|
||||
signatures := make([][]byte, len(decoded.Tx.Signatures))
|
||||
copy(signatures, decoded.Tx.Signatures)
|
||||
|
||||
sigInfos := make([]*tx.SignerInfo, len(decoded.decodedTx.Tx.AuthInfo.SignerInfos))
|
||||
for i, sigInfo := range decoded.decodedTx.Tx.AuthInfo.SignerInfos {
|
||||
sigInfos := make([]*tx.SignerInfo, len(decoded.Tx.AuthInfo.SignerInfos))
|
||||
for i, sigInfo := range decoded.Tx.AuthInfo.SignerInfos {
|
||||
modeInfoV1 := new(tx.ModeInfo)
|
||||
fromV2ModeInfo(sigInfo.ModeInfo, modeInfoV1)
|
||||
sigInfos[i] = &tx.SignerInfo{
|
||||
|
||||
@ -61,7 +61,7 @@ type ModuleOutputs struct {
|
||||
|
||||
TxConfig client.TxConfig
|
||||
TxConfigOptions tx.ConfigOptions
|
||||
BaseAppOption runtime.BaseAppOption
|
||||
BaseAppOption runtime.BaseAppOption // This is only useful for chains using baseapp. Server/v2 chains use TxValidator.
|
||||
}
|
||||
|
||||
func ProvideProtoRegistry() txsigning.ProtoFileResolver {
|
||||
|
||||
@ -16,7 +16,7 @@ func DefaultTxEncoder() sdk.TxEncoder {
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected tx type: %T", tx)
|
||||
}
|
||||
return marshalOption.Marshal(gogoWrapper.decodedTx.TxRaw)
|
||||
return marshalOption.Marshal(gogoWrapper.TxRaw)
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,6 +32,6 @@ func DefaultJSONTxEncoder(cdc codec.Codec) sdk.TxEncoder {
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected tx type: %T", tx)
|
||||
}
|
||||
return jsonMarshaler.Marshal(gogoWrapper.decodedTx.Tx)
|
||||
return jsonMarshaler.Marshal(gogoWrapper.Tx)
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
)
|
||||
|
||||
func newWrapperFromDecodedTx(addrCodec address.Codec, cdc codec.BinaryCodec, decodedTx *decode.DecodedTx) (w *gogoTxWrapper, err error) {
|
||||
func newWrapperFromDecodedTx(addrCodec address.Codec, cdc codec.BinaryCodec, decodedTx *decode.DecodedTx) (*gogoTxWrapper, error) {
|
||||
// set msgsv1
|
||||
msgs, err := decodeMsgsV1(cdc, decodedTx.Tx.Body.Messages)
|
||||
if err != nil {
|
||||
@ -79,8 +79,8 @@ func newWrapperFromDecodedTx(addrCodec address.Codec, cdc codec.BinaryCodec, dec
|
||||
}
|
||||
|
||||
return &gogoTxWrapper{
|
||||
DecodedTx: decodedTx,
|
||||
cdc: cdc,
|
||||
decodedTx: decodedTx,
|
||||
reflectMsgs: reflectMsgs,
|
||||
msgs: msgs,
|
||||
fees: fees,
|
||||
@ -92,8 +92,9 @@ func newWrapperFromDecodedTx(addrCodec address.Codec, cdc codec.BinaryCodec, dec
|
||||
// gogoTxWrapper is a gogoTxWrapper around the tx.Tx proto.Message which retain the raw
|
||||
// body and auth_info bytes.
|
||||
type gogoTxWrapper struct {
|
||||
decodedTx *decode.DecodedTx
|
||||
cdc codec.BinaryCodec
|
||||
*decode.DecodedTx
|
||||
|
||||
cdc codec.BinaryCodec
|
||||
|
||||
msgs []proto.Message
|
||||
reflectMsgs []protoreflect.Message
|
||||
@ -102,7 +103,7 @@ type gogoTxWrapper struct {
|
||||
feeGranter []byte
|
||||
}
|
||||
|
||||
func (w *gogoTxWrapper) String() string { return w.decodedTx.Tx.String() }
|
||||
func (w *gogoTxWrapper) String() string { return w.Tx.String() }
|
||||
|
||||
var (
|
||||
_ authsigning.Tx = &gogoTxWrapper{}
|
||||
@ -129,21 +130,21 @@ func (w *gogoTxWrapper) GetReflectMessages() ([]protoreflect.Message, error) {
|
||||
}
|
||||
|
||||
func (w *gogoTxWrapper) ValidateBasic() error {
|
||||
if len(w.decodedTx.Tx.Signatures) == 0 {
|
||||
if len(w.Tx.Signatures) == 0 {
|
||||
return sdkerrors.ErrNoSignatures.Wrapf("empty signatures")
|
||||
}
|
||||
if len(w.decodedTx.Signers) != len(w.decodedTx.Tx.Signatures) {
|
||||
return sdkerrors.ErrUnauthorized.Wrapf("invalid number of signatures: got %d signatures and %d signers", len(w.decodedTx.Tx.Signatures), len(w.decodedTx.Signers))
|
||||
if len(w.Signers) != len(w.Tx.Signatures) {
|
||||
return sdkerrors.ErrUnauthorized.Wrapf("invalid number of signatures: got %d signatures and %d signers", len(w.Tx.Signatures), len(w.Signers))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *gogoTxWrapper) GetSigners() ([][]byte, error) {
|
||||
return w.decodedTx.Signers, nil
|
||||
return w.Signers, nil
|
||||
}
|
||||
|
||||
func (w *gogoTxWrapper) GetPubKeys() ([]cryptotypes.PubKey, error) {
|
||||
signerInfos := w.decodedTx.Tx.AuthInfo.SignerInfos
|
||||
signerInfos := w.Tx.AuthInfo.SignerInfos
|
||||
pks := make([]cryptotypes.PubKey, len(signerInfos))
|
||||
|
||||
for i, si := range signerInfos {
|
||||
@ -168,7 +169,7 @@ func (w *gogoTxWrapper) GetPubKeys() ([]cryptotypes.PubKey, error) {
|
||||
}
|
||||
|
||||
func (w *gogoTxWrapper) GetGas() uint64 {
|
||||
return w.decodedTx.Tx.AuthInfo.Fee.GasLimit
|
||||
return w.Tx.AuthInfo.Fee.GasLimit
|
||||
}
|
||||
|
||||
func (w *gogoTxWrapper) GetFee() sdk.Coins { return w.fees }
|
||||
@ -177,18 +178,18 @@ func (w *gogoTxWrapper) FeePayer() []byte { return w.feePayer }
|
||||
|
||||
func (w *gogoTxWrapper) FeeGranter() []byte { return w.feeGranter }
|
||||
|
||||
func (w *gogoTxWrapper) GetMemo() string { return w.decodedTx.Tx.Body.Memo }
|
||||
func (w *gogoTxWrapper) GetMemo() string { return w.Tx.Body.Memo }
|
||||
|
||||
// GetTimeoutHeight returns the transaction's timeout height (if set).
|
||||
func (w *gogoTxWrapper) GetTimeoutHeight() uint64 { return w.decodedTx.Tx.Body.TimeoutHeight }
|
||||
func (w *gogoTxWrapper) GetTimeoutHeight() uint64 { return w.Tx.Body.TimeoutHeight }
|
||||
|
||||
// GetUnordered returns the transaction's unordered field (if set).
|
||||
func (w *gogoTxWrapper) GetUnordered() bool { return w.decodedTx.Tx.Body.Unordered }
|
||||
func (w *gogoTxWrapper) GetUnordered() bool { return w.Tx.Body.Unordered }
|
||||
|
||||
// GetSignaturesV2 returns the signatures of the Tx.
|
||||
func (w *gogoTxWrapper) GetSignaturesV2() ([]signing.SignatureV2, error) {
|
||||
signerInfos := w.decodedTx.Tx.AuthInfo.SignerInfos
|
||||
sigs := w.decodedTx.Tx.Signatures
|
||||
signerInfos := w.Tx.AuthInfo.SignerInfos
|
||||
sigs := w.Tx.Signatures
|
||||
pubKeys, err := w.GetPubKeys()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -225,46 +226,46 @@ func (w *gogoTxWrapper) GetSignaturesV2() ([]signing.SignatureV2, error) {
|
||||
// TODO: evaluate if this is even needed considering we have decoded tx.
|
||||
func (w *gogoTxWrapper) GetSigningTxData() txsigning.TxData {
|
||||
return txsigning.TxData{
|
||||
Body: w.decodedTx.Tx.Body,
|
||||
AuthInfo: w.decodedTx.Tx.AuthInfo,
|
||||
BodyBytes: w.decodedTx.TxRaw.BodyBytes,
|
||||
AuthInfoBytes: w.decodedTx.TxRaw.AuthInfoBytes,
|
||||
BodyHasUnknownNonCriticals: w.decodedTx.TxBodyHasUnknownNonCriticals,
|
||||
Body: w.Tx.Body,
|
||||
AuthInfo: w.Tx.AuthInfo,
|
||||
BodyBytes: w.TxRaw.BodyBytes,
|
||||
AuthInfoBytes: w.TxRaw.AuthInfoBytes,
|
||||
BodyHasUnknownNonCriticals: w.TxBodyHasUnknownNonCriticals,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *gogoTxWrapper) GetExtensionOptions() []*codectypes.Any {
|
||||
return intoAnyV1(w.decodedTx.Tx.Body.ExtensionOptions)
|
||||
return intoAnyV1(w.Tx.Body.ExtensionOptions)
|
||||
}
|
||||
|
||||
func (w *gogoTxWrapper) GetNonCriticalExtensionOptions() []*codectypes.Any {
|
||||
return intoAnyV1(w.decodedTx.Tx.Body.NonCriticalExtensionOptions)
|
||||
return intoAnyV1(w.Tx.Body.NonCriticalExtensionOptions)
|
||||
}
|
||||
|
||||
func (w *gogoTxWrapper) AsTx() (*txtypes.Tx, error) {
|
||||
body := new(txtypes.TxBody)
|
||||
authInfo := new(txtypes.AuthInfo)
|
||||
|
||||
err := w.cdc.Unmarshal(w.decodedTx.TxRaw.BodyBytes, body)
|
||||
err := w.cdc.Unmarshal(w.TxRaw.BodyBytes, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = w.cdc.Unmarshal(w.decodedTx.TxRaw.AuthInfoBytes, authInfo)
|
||||
err = w.cdc.Unmarshal(w.TxRaw.AuthInfoBytes, authInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &txtypes.Tx{
|
||||
Body: body,
|
||||
AuthInfo: authInfo,
|
||||
Signatures: w.decodedTx.TxRaw.Signatures,
|
||||
Signatures: w.TxRaw.Signatures,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (w *gogoTxWrapper) AsTxRaw() (*txtypes.TxRaw, error) {
|
||||
return &txtypes.TxRaw{
|
||||
BodyBytes: w.decodedTx.TxRaw.BodyBytes,
|
||||
AuthInfoBytes: w.decodedTx.TxRaw.AuthInfoBytes,
|
||||
Signatures: w.decodedTx.TxRaw.Signatures,
|
||||
BodyBytes: w.TxRaw.BodyBytes,
|
||||
AuthInfoBytes: w.TxRaw.AuthInfoBytes,
|
||||
Signatures: w.TxRaw.Signatures,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@ -1 +0,0 @@
|
||||
package tx
|
||||
@ -48,11 +48,11 @@ func (s signModeLegacyAminoJSONHandler) GetSignBytes(mode signingtypes.SignMode,
|
||||
return nil, fmt.Errorf("can only handle a protobuf Tx, got %T", tx)
|
||||
}
|
||||
|
||||
if protoTx.decodedTx.TxBodyHasUnknownNonCriticals {
|
||||
if protoTx.TxBodyHasUnknownNonCriticals {
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, aminoNonCriticalFieldsError)
|
||||
}
|
||||
|
||||
body := protoTx.decodedTx.Tx.Body
|
||||
body := protoTx.Tx.Body
|
||||
|
||||
if len(body.ExtensionOptions) != 0 || len(body.NonCriticalExtensionOptions) != 0 {
|
||||
return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "%s does not support protobuf extension options", signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON)
|
||||
@ -68,8 +68,8 @@ func (s signModeLegacyAminoJSONHandler) GetSignBytes(mode signingtypes.SignMode,
|
||||
legacytx.StdFee{
|
||||
Amount: protoTx.GetFee(),
|
||||
Gas: protoTx.GetGas(),
|
||||
Payer: protoTx.decodedTx.Tx.AuthInfo.Fee.Payer,
|
||||
Granter: protoTx.decodedTx.Tx.AuthInfo.Fee.Granter,
|
||||
Payer: protoTx.Tx.AuthInfo.Fee.Payer,
|
||||
Granter: protoTx.Tx.AuthInfo.Fee.Granter,
|
||||
},
|
||||
tx.GetMsgs(), protoTx.GetMemo(),
|
||||
), nil
|
||||
|
||||
@ -1,12 +1,15 @@
|
||||
package decode
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
|
||||
"github.com/cosmos/cosmos-proto/anyutil"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/protoadapt"
|
||||
|
||||
v1beta1 "cosmossdk.io/api/cosmos/tx/v1beta1"
|
||||
"cosmossdk.io/core/transaction"
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"cosmossdk.io/x/tx/signing"
|
||||
)
|
||||
@ -18,8 +21,15 @@ type DecodedTx struct {
|
||||
TxRaw *v1beta1.TxRaw
|
||||
Signers [][]byte
|
||||
TxBodyHasUnknownNonCriticals bool
|
||||
|
||||
// Cache for hash and full bytes
|
||||
cachedHash [32]byte
|
||||
cachedBytes []byte
|
||||
cachedHashed bool
|
||||
}
|
||||
|
||||
var _ transaction.Tx = &DecodedTx{}
|
||||
|
||||
// Decoder contains the dependencies required for decoding transactions.
|
||||
type Decoder struct {
|
||||
signingCtx *signing.Context
|
||||
@ -126,3 +136,56 @@ func (d *Decoder) Decode(txBytes []byte) (*DecodedTx, error) {
|
||||
Signers: signers,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Hash implements the interface for the Tx interface.
|
||||
func (dtx *DecodedTx) Hash() [32]byte {
|
||||
if !dtx.cachedHashed {
|
||||
dtx.computeHashAndBytes()
|
||||
}
|
||||
return dtx.cachedHash
|
||||
}
|
||||
|
||||
func (dtx *DecodedTx) GetGasLimit() (uint64, error) {
|
||||
if dtx == nil || dtx.Tx == nil || dtx.Tx.AuthInfo == nil || dtx.Tx.AuthInfo.Fee == nil {
|
||||
return 0, errors.New("gas limit not available or one or more required fields are nil")
|
||||
}
|
||||
return dtx.Tx.AuthInfo.Fee.GasLimit, nil
|
||||
}
|
||||
|
||||
func (dtx *DecodedTx) GetMessages() ([]transaction.Msg, error) {
|
||||
if dtx == nil || dtx.Messages == nil {
|
||||
return nil, errors.New("messages not available or are nil")
|
||||
}
|
||||
|
||||
msgs := make([]transaction.Msg, len(dtx.Messages))
|
||||
for i, msg := range dtx.Messages {
|
||||
msgs[i] = protoadapt.MessageV1Of(msg)
|
||||
}
|
||||
|
||||
return msgs, nil
|
||||
}
|
||||
|
||||
func (dtx *DecodedTx) GetSenders() ([][]byte, error) {
|
||||
if dtx == nil || dtx.Signers == nil {
|
||||
return nil, errors.New("senders not available or are nil")
|
||||
}
|
||||
return dtx.Signers, nil
|
||||
}
|
||||
|
||||
func (dtx *DecodedTx) Bytes() []byte {
|
||||
if !dtx.cachedHashed {
|
||||
dtx.computeHashAndBytes()
|
||||
}
|
||||
return dtx.cachedBytes
|
||||
}
|
||||
|
||||
func (dtx *DecodedTx) computeHashAndBytes() {
|
||||
bz, err := proto.Marshal(dtx.TxRaw)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
dtx.cachedBytes = bz
|
||||
dtx.cachedHash = sha256.Sum256(bz)
|
||||
dtx.cachedHashed = true
|
||||
}
|
||||
|
||||
@ -21,7 +21,8 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
|
||||
golang.org/x/net v0.25.0 // indirect
|
||||
@ -33,6 +34,8 @@ require (
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace cosmossdk.io/core => ../../core
|
||||
|
||||
// NOTE: we do not want to replace to the development version of cosmossdk.io/api yet
|
||||
// Until https://github.com/cosmos/cosmos-sdk/issues/19228 is resolved
|
||||
// We are tagging x/tx from main and must keep using released versions of x/tx dependencies
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
cosmossdk.io/api v0.7.5 h1:eMPTReoNmGUm8DeiQL9DyM8sYDjEhWzL1+nLbI9DqtQ=
|
||||
cosmossdk.io/api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38=
|
||||
cosmossdk.io/core v0.11.0 h1:vtIafqUi+1ZNAE/oxLOQQ7Oek2n4S48SWLG8h/+wdbo=
|
||||
cosmossdk.io/core v0.11.0/go.mod h1:LaTtayWBSoacF5xNzoF8tmLhehqlA9z1SWiPuNC6X1w=
|
||||
cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0=
|
||||
cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U=
|
||||
cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE=
|
||||
@ -10,9 +8,11 @@ github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+R
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec=
|
||||
github.com/cosmos/gogoproto v1.4.12 h1:vB6Lbe/rtnYGjQuFxkPiPYiCybqFT8QvLipDZP8JpFE=
|
||||
github.com/cosmos/gogoproto v1.4.12/go.mod h1:LnZob1bXRdUoqMMtwYlcR3wjiElmlC+FkjaZRv1/eLY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
|
||||
Loading…
Reference in New Issue
Block a user