github.com/Finschia/finschia-sdk@v0.48.1/types/tx/types.go (about) 1 package tx 2 3 import ( 4 "fmt" 5 6 codectypes "github.com/Finschia/finschia-sdk/codec/types" 7 cryptotypes "github.com/Finschia/finschia-sdk/crypto/types" 8 sdk "github.com/Finschia/finschia-sdk/types" 9 sdkerrors "github.com/Finschia/finschia-sdk/types/errors" 10 ) 11 12 // MaxGasWanted defines the max gas allowed. 13 const MaxGasWanted = uint64((1 << 63) - 1) 14 15 // Interface implementation checks. 16 var _, _, _, _ codectypes.UnpackInterfacesMessage = &Tx{}, &TxBody{}, &AuthInfo{}, &SignerInfo{} 17 var _ sdk.Tx = &Tx{} 18 19 // GetMsgs implements the GetMsgs method on sdk.Tx. 20 func (t *Tx) GetMsgs() []sdk.Msg { 21 if t == nil || t.Body == nil { 22 return nil 23 } 24 25 anys := t.Body.Messages 26 res := make([]sdk.Msg, len(anys)) 27 for i, any := range anys { 28 cached := any.GetCachedValue() 29 if cached == nil { 30 panic("Any cached value is nil. Transaction messages must be correctly packed Any values.") 31 } 32 res[i] = cached.(sdk.Msg) 33 } 34 return res 35 } 36 37 // ValidateBasic implements the ValidateBasic method on sdk.Tx. 38 func (t *Tx) ValidateBasic() error { 39 if t == nil { 40 return fmt.Errorf("bad Tx") 41 } 42 43 body := t.Body 44 if body == nil { 45 return fmt.Errorf("missing TxBody") 46 } 47 48 authInfo := t.AuthInfo 49 if authInfo == nil { 50 return fmt.Errorf("missing AuthInfo") 51 } 52 53 fee := authInfo.Fee 54 if fee == nil { 55 return fmt.Errorf("missing fee") 56 } 57 58 if fee.GasLimit > MaxGasWanted { 59 return sdkerrors.Wrapf( 60 sdkerrors.ErrInvalidRequest, 61 "invalid gas supplied; %d > %d", fee.GasLimit, MaxGasWanted, 62 ) 63 } 64 65 if fee.Amount.IsAnyNil() { 66 return sdkerrors.Wrapf( 67 sdkerrors.ErrInsufficientFee, 68 "invalid fee provided: null", 69 ) 70 } 71 72 if fee.Amount.IsAnyNegative() { 73 return sdkerrors.Wrapf( 74 sdkerrors.ErrInsufficientFee, 75 "invalid fee provided: %s", fee.Amount, 76 ) 77 } 78 79 if fee.Payer != "" { 80 _, err := sdk.AccAddressFromBech32(fee.Payer) 81 if err != nil { 82 return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid fee payer address (%s)", err) 83 } 84 } 85 86 sigs := t.Signatures 87 88 if len(sigs) == 0 { 89 return sdkerrors.ErrNoSignatures 90 } 91 92 if len(sigs) != len(t.GetSigners()) { 93 return sdkerrors.Wrapf( 94 sdkerrors.ErrUnauthorized, 95 "wrong number of signers; expected %d, got %d", len(t.GetSigners()), len(sigs), 96 ) 97 } 98 99 return nil 100 } 101 102 // GetSigners retrieves all the signers of a tx. 103 // This includes all unique signers of the messages (in order), 104 // as well as the FeePayer (if specified and not already included). 105 func (t *Tx) GetSigners() []sdk.AccAddress { 106 var signers []sdk.AccAddress 107 seen := map[string]bool{} 108 109 for _, msg := range t.GetMsgs() { 110 for _, addr := range msg.GetSigners() { 111 if !seen[addr.String()] { 112 signers = append(signers, addr) 113 seen[addr.String()] = true 114 } 115 } 116 } 117 118 // ensure any specified fee payer is included in the required signers (at the end) 119 feePayer := t.AuthInfo.Fee.Payer 120 if feePayer != "" && !seen[feePayer] { 121 payerAddr := sdk.MustAccAddressFromBech32(feePayer) 122 signers = append(signers, payerAddr) 123 seen[feePayer] = true 124 } 125 126 return signers 127 } 128 129 func (t *Tx) GetGas() uint64 { 130 return t.AuthInfo.Fee.GasLimit 131 } 132 133 func (t *Tx) GetFee() sdk.Coins { 134 return t.AuthInfo.Fee.Amount 135 } 136 137 func (t *Tx) FeePayer() sdk.AccAddress { 138 feePayer := t.AuthInfo.Fee.Payer 139 if feePayer != "" { 140 return sdk.MustAccAddressFromBech32(feePayer) 141 } 142 // use first signer as default if no payer specified 143 return t.GetSigners()[0] 144 } 145 146 func (t *Tx) FeeGranter() sdk.AccAddress { 147 feePayer := t.AuthInfo.Fee.Granter 148 if feePayer != "" { 149 return sdk.MustAccAddressFromBech32(feePayer) 150 } 151 return nil 152 } 153 154 // UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method 155 func (t *Tx) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { 156 if t.Body != nil { 157 if err := t.Body.UnpackInterfaces(unpacker); err != nil { 158 return err 159 } 160 } 161 162 if t.AuthInfo != nil { 163 return t.AuthInfo.UnpackInterfaces(unpacker) 164 } 165 166 return nil 167 } 168 169 // UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method 170 func (m *TxBody) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { 171 for _, any := range m.Messages { 172 var msg sdk.Msg 173 err := unpacker.UnpackAny(any, &msg) 174 if err != nil { 175 return err 176 } 177 } 178 179 return nil 180 } 181 182 // UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method 183 func (m *AuthInfo) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { 184 for _, signerInfo := range m.SignerInfos { 185 err := signerInfo.UnpackInterfaces(unpacker) 186 if err != nil { 187 return err 188 } 189 } 190 return nil 191 } 192 193 // UnpackInterfaces implements the UnpackInterfaceMessages.UnpackInterfaces method 194 func (m *SignerInfo) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { 195 return unpacker.UnpackAny(m.PublicKey, new(cryptotypes.PubKey)) 196 } 197 198 // RegisterInterfaces registers the sdk.Tx interface. 199 func RegisterInterfaces(registry codectypes.InterfaceRegistry) { 200 registry.RegisterInterface("cosmos.tx.v1beta1.Tx", (*sdk.Tx)(nil)) 201 registry.RegisterImplementations((*sdk.Tx)(nil), &Tx{}) 202 }