github.com/cosmos/cosmos-sdk@v0.50.10/x/auth/tx/config.go (about) 1 package tx 2 3 import ( 4 "fmt" 5 6 txsigning "cosmossdk.io/x/tx/signing" 7 "cosmossdk.io/x/tx/signing/aminojson" 8 "cosmossdk.io/x/tx/signing/direct" 9 "cosmossdk.io/x/tx/signing/directaux" 10 "cosmossdk.io/x/tx/signing/textual" 11 12 "github.com/cosmos/cosmos-sdk/client" 13 "github.com/cosmos/cosmos-sdk/codec" 14 sdk "github.com/cosmos/cosmos-sdk/types" 15 signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" 16 authcodec "github.com/cosmos/cosmos-sdk/x/auth/codec" 17 ) 18 19 type config struct { 20 handler *txsigning.HandlerMap 21 decoder sdk.TxDecoder 22 encoder sdk.TxEncoder 23 jsonDecoder sdk.TxDecoder 24 jsonEncoder sdk.TxEncoder 25 protoCodec codec.Codec 26 signingContext *txsigning.Context 27 } 28 29 // ConfigOptions define the configuration of a TxConfig when calling NewTxConfigWithOptions. 30 // An empty struct is a valid configuration and will result in a TxConfig with default values. 31 type ConfigOptions struct { 32 // If SigningHandler is specified it will be used instead constructing one. 33 // This option supersedes all below options, whose sole purpose are to configure the creation of 34 // txsigning.HandlerMap. 35 SigningHandler *txsigning.HandlerMap 36 // EnabledSignModes is the list of sign modes that will be enabled in the txsigning.HandlerMap. 37 EnabledSignModes []signingtypes.SignMode 38 // If SigningContext is specified it will be used when constructing sign mode handlers. If nil, one will be created 39 // with the options specified in SigningOptions. 40 SigningContext *txsigning.Context 41 // SigningOptions are the options that will be used when constructing a txsigning.Context and sign mode handlers. 42 // If nil defaults will be used. 43 SigningOptions *txsigning.Options 44 // TextualCoinMetadataQueryFn is the function that will be used to query coin metadata when constructing 45 // textual sign mode handler. This is required if SIGN_MODE_TEXTUAL is enabled. 46 TextualCoinMetadataQueryFn textual.CoinMetadataQueryFn 47 // CustomSignModes are the custom sign modes that will be added to the txsigning.HandlerMap. 48 CustomSignModes []txsigning.SignModeHandler 49 // ProtoDecoder is the decoder that will be used to decode protobuf transactions. 50 ProtoDecoder sdk.TxDecoder 51 // ProtoEncoder is the encoder that will be used to encode protobuf transactions. 52 ProtoEncoder sdk.TxEncoder 53 // JSONDecoder is the decoder that will be used to decode json transactions. 54 JSONDecoder sdk.TxDecoder 55 // JSONEncoder is the encoder that will be used to encode json transactions. 56 JSONEncoder sdk.TxEncoder 57 } 58 59 // DefaultSignModes are the default sign modes enabled for protobuf transactions. 60 var DefaultSignModes = []signingtypes.SignMode{ 61 signingtypes.SignMode_SIGN_MODE_DIRECT, 62 signingtypes.SignMode_SIGN_MODE_DIRECT_AUX, 63 signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON, 64 // signingtypes.SignMode_SIGN_MODE_TEXTUAL is not enabled by default, as it requires a x/bank keeper or gRPC connection. 65 } 66 67 // NewTxConfig returns a new protobuf TxConfig using the provided ProtoCodec and sign modes. The 68 // first enabled sign mode will become the default sign mode. 69 // 70 // NOTE: Use NewTxConfigWithOptions to provide a custom signing handler in case the sign mode 71 // is not supported by default (eg: SignMode_SIGN_MODE_EIP_191), or to enable SIGN_MODE_TEXTUAL. 72 // 73 // We prefer to use depinject to provide client.TxConfig, but we permit this constructor usage. Within the SDK, 74 // this constructor is primarily used in tests, but also sees usage in app chains like: 75 // https://github.com/evmos/evmos/blob/719363fbb92ff3ea9649694bd088e4c6fe9c195f/encoding/config.go#L37 76 func NewTxConfig(protoCodec codec.Codec, enabledSignModes []signingtypes.SignMode, 77 customSignModes ...txsigning.SignModeHandler, 78 ) client.TxConfig { 79 txConfig, err := NewTxConfigWithOptions(protoCodec, ConfigOptions{ 80 EnabledSignModes: enabledSignModes, 81 CustomSignModes: customSignModes, 82 }) 83 if err != nil { 84 panic(err) 85 } 86 return txConfig 87 } 88 89 // NewDefaultSigningOptions returns the sdk default signing options used by x/tx. This includes account and 90 // validator address prefix enabled codecs. 91 func NewDefaultSigningOptions() (*txsigning.Options, error) { 92 sdkConfig := sdk.GetConfig() 93 return &txsigning.Options{ 94 AddressCodec: authcodec.NewBech32Codec(sdkConfig.GetBech32AccountAddrPrefix()), 95 ValidatorAddressCodec: authcodec.NewBech32Codec(sdkConfig.GetBech32ValidatorAddrPrefix()), 96 }, nil 97 } 98 99 // NewSigningHandlerMap returns a new txsigning.HandlerMap using the provided ConfigOptions. 100 // It is recommended to use types.InterfaceRegistry in the field ConfigOptions.FileResolver as shown in 101 // NewTxConfigWithOptions but this fn does not enforce it. 102 func NewSigningHandlerMap(configOpts ConfigOptions) (*txsigning.HandlerMap, error) { 103 var err error 104 if configOpts.SigningOptions == nil { 105 configOpts.SigningOptions, err = NewDefaultSigningOptions() 106 if err != nil { 107 return nil, err 108 } 109 } 110 if configOpts.SigningContext == nil { 111 configOpts.SigningContext, err = txsigning.NewContext(*configOpts.SigningOptions) 112 if err != nil { 113 return nil, err 114 } 115 } 116 117 signingOpts := configOpts.SigningOptions 118 119 if len(configOpts.EnabledSignModes) == 0 { 120 configOpts.EnabledSignModes = DefaultSignModes 121 } 122 123 lenSignModes := len(configOpts.EnabledSignModes) 124 handlers := make([]txsigning.SignModeHandler, lenSignModes+len(configOpts.CustomSignModes)) 125 for i, m := range configOpts.EnabledSignModes { 126 var err error 127 switch m { 128 case signingtypes.SignMode_SIGN_MODE_DIRECT: 129 handlers[i] = &direct.SignModeHandler{} 130 case signingtypes.SignMode_SIGN_MODE_DIRECT_AUX: 131 handlers[i], err = directaux.NewSignModeHandler(directaux.SignModeHandlerOptions{ 132 TypeResolver: signingOpts.TypeResolver, 133 SignersContext: configOpts.SigningContext, 134 }) 135 if err != nil { 136 return nil, err 137 } 138 case signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON: 139 handlers[i] = aminojson.NewSignModeHandler(aminojson.SignModeHandlerOptions{ 140 FileResolver: signingOpts.FileResolver, 141 TypeResolver: signingOpts.TypeResolver, 142 }) 143 case signingtypes.SignMode_SIGN_MODE_TEXTUAL: 144 handlers[i], err = textual.NewSignModeHandler(textual.SignModeOptions{ 145 CoinMetadataQuerier: configOpts.TextualCoinMetadataQueryFn, 146 FileResolver: signingOpts.FileResolver, 147 TypeResolver: signingOpts.TypeResolver, 148 }) 149 if configOpts.TextualCoinMetadataQueryFn == nil { 150 return nil, fmt.Errorf("cannot enable SIGN_MODE_TEXTUAL without a TextualCoinMetadataQueryFn") 151 } 152 if err != nil { 153 return nil, err 154 } 155 } 156 } 157 for i, m := range configOpts.CustomSignModes { 158 handlers[i+lenSignModes] = m 159 } 160 161 handler := txsigning.NewHandlerMap(handlers...) 162 return handler, nil 163 } 164 165 // NewTxConfigWithOptions returns a new protobuf TxConfig using the provided ProtoCodec, ConfigOptions and 166 // custom sign mode handlers. If ConfigOptions is an empty struct then default values will be used. 167 func NewTxConfigWithOptions(protoCodec codec.Codec, configOptions ConfigOptions) (client.TxConfig, error) { 168 txConfig := &config{ 169 protoCodec: protoCodec, 170 decoder: configOptions.ProtoDecoder, 171 encoder: configOptions.ProtoEncoder, 172 jsonDecoder: configOptions.JSONDecoder, 173 jsonEncoder: configOptions.JSONEncoder, 174 } 175 if configOptions.ProtoDecoder == nil { 176 txConfig.decoder = DefaultTxDecoder(protoCodec) 177 } 178 if configOptions.ProtoEncoder == nil { 179 txConfig.encoder = DefaultTxEncoder() 180 } 181 if configOptions.JSONDecoder == nil { 182 txConfig.jsonDecoder = DefaultJSONTxDecoder(protoCodec) 183 } 184 if configOptions.JSONEncoder == nil { 185 txConfig.jsonEncoder = DefaultJSONTxEncoder(protoCodec) 186 } 187 188 var err error 189 if configOptions.SigningContext == nil { 190 if configOptions.SigningOptions == nil { 191 configOptions.SigningOptions, err = NewDefaultSigningOptions() 192 if err != nil { 193 return nil, err 194 } 195 } 196 if configOptions.SigningOptions.FileResolver == nil { 197 configOptions.SigningOptions.FileResolver = protoCodec.InterfaceRegistry() 198 } 199 configOptions.SigningContext, err = txsigning.NewContext(*configOptions.SigningOptions) 200 if err != nil { 201 return nil, err 202 } 203 } 204 txConfig.signingContext = configOptions.SigningContext 205 206 if configOptions.SigningHandler != nil { 207 txConfig.handler = configOptions.SigningHandler 208 return txConfig, nil 209 } 210 211 txConfig.handler, err = NewSigningHandlerMap(configOptions) 212 if err != nil { 213 return nil, err 214 } 215 216 return txConfig, nil 217 } 218 219 func (g config) NewTxBuilder() client.TxBuilder { 220 return newBuilder(g.protoCodec) 221 } 222 223 // WrapTxBuilder returns a builder from provided transaction 224 func (g config) WrapTxBuilder(newTx sdk.Tx) (client.TxBuilder, error) { 225 newBuilder, ok := newTx.(*wrapper) 226 if !ok { 227 return nil, fmt.Errorf("expected %T, got %T", &wrapper{}, newTx) 228 } 229 230 return newBuilder, nil 231 } 232 233 func (g config) SignModeHandler() *txsigning.HandlerMap { 234 return g.handler 235 } 236 237 func (g config) TxEncoder() sdk.TxEncoder { 238 return g.encoder 239 } 240 241 func (g config) TxDecoder() sdk.TxDecoder { 242 return g.decoder 243 } 244 245 func (g config) TxJSONEncoder() sdk.TxEncoder { 246 return g.jsonEncoder 247 } 248 249 func (g config) TxJSONDecoder() sdk.TxDecoder { 250 return g.jsonDecoder 251 } 252 253 func (g config) SigningContext() *txsigning.Context { 254 return g.signingContext 255 }