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 }