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  }