github.com/cosmos/cosmos-sdk@v0.50.10/types/tx/types.go (about)

     1  package tx
     2  
     3  import (
     4  	"fmt"
     5  
     6  	protov2 "google.golang.org/protobuf/proto"
     7  
     8  	errorsmod "cosmossdk.io/errors"
     9  
    10  	"github.com/cosmos/cosmos-sdk/codec"
    11  	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
    12  	cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
    13  	sdk "github.com/cosmos/cosmos-sdk/types"
    14  	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
    15  )
    16  
    17  // MaxGasWanted defines the max gas allowed.
    18  const MaxGasWanted = uint64((1 << 63) - 1)
    19  
    20  // Interface implementation checks.
    21  var (
    22  	_, _, _, _ codectypes.UnpackInterfacesMessage = &Tx{}, &TxBody{}, &AuthInfo{}, &SignerInfo{}
    23  )
    24  
    25  // GetMsgs implements the GetMsgs method on sdk.Tx.
    26  func (t *Tx) GetMsgs() []sdk.Msg {
    27  	if t == nil || t.Body == nil {
    28  		return nil
    29  	}
    30  
    31  	anys := t.Body.Messages
    32  	res, err := GetMsgs(anys, "transaction")
    33  	if err != nil {
    34  		panic(err)
    35  	}
    36  	return res
    37  }
    38  
    39  // ValidateBasic implements the ValidateBasic method on sdk.Tx.
    40  func (t *Tx) ValidateBasic() error {
    41  	if t == nil {
    42  		return fmt.Errorf("bad Tx")
    43  	}
    44  
    45  	body := t.Body
    46  	if body == nil {
    47  		return fmt.Errorf("missing TxBody")
    48  	}
    49  
    50  	authInfo := t.AuthInfo
    51  	if authInfo == nil {
    52  		return fmt.Errorf("missing AuthInfo")
    53  	}
    54  
    55  	fee := authInfo.Fee
    56  	if fee == nil {
    57  		return fmt.Errorf("missing fee")
    58  	}
    59  
    60  	if fee.GasLimit > MaxGasWanted {
    61  		return errorsmod.Wrapf(
    62  			sdkerrors.ErrInvalidRequest,
    63  			"invalid gas supplied; %d > %d", fee.GasLimit, MaxGasWanted,
    64  		)
    65  	}
    66  
    67  	if fee.Amount.IsAnyNil() {
    68  		return errorsmod.Wrapf(
    69  			sdkerrors.ErrInsufficientFee,
    70  			"invalid fee provided: null",
    71  		)
    72  	}
    73  
    74  	if fee.Amount.IsAnyNegative() {
    75  		return errorsmod.Wrapf(
    76  			sdkerrors.ErrInsufficientFee,
    77  			"invalid fee provided: %s", fee.Amount,
    78  		)
    79  	}
    80  
    81  	if fee.Payer != "" {
    82  		_, err := sdk.AccAddressFromBech32(fee.Payer)
    83  		if err != nil {
    84  			return errorsmod.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid fee payer address (%s)", err)
    85  		}
    86  	}
    87  
    88  	sigs := t.Signatures
    89  
    90  	if len(sigs) == 0 {
    91  		return sdkerrors.ErrNoSignatures
    92  	}
    93  
    94  	return nil
    95  }
    96  
    97  // GetSigners retrieves all the signers of a tx.
    98  // This includes all unique signers of the messages (in order),
    99  // as well as the FeePayer (if specified and not already included).
   100  func (t *Tx) GetSigners(cdc codec.Codec) ([][]byte, []protov2.Message, error) {
   101  	var signers [][]byte
   102  	seen := map[string]bool{}
   103  
   104  	var msgsv2 []protov2.Message
   105  	for _, msg := range t.Body.Messages {
   106  		xs, msgv2, err := cdc.GetMsgAnySigners(msg)
   107  		if err != nil {
   108  			return nil, nil, err
   109  		}
   110  
   111  		msgsv2 = append(msgsv2, msgv2)
   112  
   113  		for _, signer := range xs {
   114  			if !seen[string(signer)] {
   115  				signers = append(signers, signer)
   116  				seen[string(signer)] = true
   117  			}
   118  		}
   119  	}
   120  
   121  	// ensure any specified fee payer is included in the required signers (at the end)
   122  	feePayer := t.AuthInfo.Fee.Payer
   123  	var feePayerAddr []byte
   124  	if feePayer != "" {
   125  		var err error
   126  		feePayerAddr, err = cdc.InterfaceRegistry().SigningContext().AddressCodec().StringToBytes(feePayer)
   127  		if err != nil {
   128  			return nil, nil, err
   129  		}
   130  	}
   131  	if feePayerAddr != nil && !seen[string(feePayerAddr)] {
   132  		signers = append(signers, feePayerAddr)
   133  		seen[string(feePayerAddr)] = true
   134  	}
   135  
   136  	return signers, msgsv2, nil
   137  }
   138  
   139  func (t *Tx) GetGas() uint64 {
   140  	return t.AuthInfo.Fee.GasLimit
   141  }
   142  
   143  func (t *Tx) GetFee() sdk.Coins {
   144  	return t.AuthInfo.Fee.Amount
   145  }
   146  
   147  func (t *Tx) FeePayer(cdc codec.Codec) []byte {
   148  	feePayer := t.AuthInfo.Fee.Payer
   149  	if feePayer != "" {
   150  		feePayerAddr, err := cdc.InterfaceRegistry().SigningContext().AddressCodec().StringToBytes(feePayer)
   151  		if err != nil {
   152  			panic(err)
   153  		}
   154  		return feePayerAddr
   155  	}
   156  	// use first signer as default if no payer specified
   157  	signers, _, err := t.GetSigners(cdc)
   158  	if err != nil {
   159  		panic(err)
   160  	}
   161  
   162  	return signers[0]
   163  }
   164  
   165  func (t *Tx) FeeGranter(cdc codec.Codec) []byte {
   166  	feeGranter := t.AuthInfo.Fee.Granter
   167  	if feeGranter != "" {
   168  		feeGranterAddr, err := cdc.InterfaceRegistry().SigningContext().AddressCodec().StringToBytes(feeGranter)
   169  		if err != nil {
   170  			panic(err)
   171  		}
   172  
   173  		return feeGranterAddr
   174  	}
   175  	return nil
   176  }
   177  
   178  // UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method
   179  func (t *Tx) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
   180  	if t.Body != nil {
   181  		if err := t.Body.UnpackInterfaces(unpacker); err != nil {
   182  			return err
   183  		}
   184  	}
   185  
   186  	if t.AuthInfo != nil {
   187  		return t.AuthInfo.UnpackInterfaces(unpacker)
   188  	}
   189  
   190  	return nil
   191  }
   192  
   193  // UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method
   194  func (m *TxBody) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
   195  	if err := UnpackInterfaces(unpacker, m.Messages); err != nil {
   196  		return err
   197  	}
   198  
   199  	if err := unpackTxExtensionOptionsI(unpacker, m.ExtensionOptions); err != nil {
   200  		return err
   201  	}
   202  
   203  	if err := unpackTxExtensionOptionsI(unpacker, m.NonCriticalExtensionOptions); err != nil {
   204  		return err
   205  	}
   206  
   207  	return nil
   208  }
   209  
   210  // UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method
   211  func (m *AuthInfo) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
   212  	for _, signerInfo := range m.SignerInfos {
   213  		err := signerInfo.UnpackInterfaces(unpacker)
   214  		if err != nil {
   215  			return err
   216  		}
   217  	}
   218  	return nil
   219  }
   220  
   221  // UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method
   222  func (m *SignerInfo) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
   223  	return unpacker.UnpackAny(m.PublicKey, new(cryptotypes.PubKey))
   224  }
   225  
   226  // RegisterInterfaces registers the sdk.Tx and MsgResponse interfaces.
   227  // Note: the registration of sdk.Msg is done in sdk.RegisterInterfaces, but it
   228  // could be moved inside this function.
   229  func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
   230  	registry.RegisterInterface(msgResponseInterfaceProtoName, (*MsgResponse)(nil))
   231  
   232  	registry.RegisterInterface("cosmos.tx.v1beta1.Tx", (*sdk.HasMsgs)(nil))
   233  	registry.RegisterImplementations((*sdk.HasMsgs)(nil), &Tx{})
   234  
   235  	registry.RegisterInterface("cosmos.tx.v1beta1.TxExtensionOptionI", (*TxExtensionOptionI)(nil))
   236  }