From 46b887f2cc10479576c2fc2040d4e7d6fdb2c6ce Mon Sep 17 00:00:00 2001 From: Vladyslav Budichenko Date: Wed, 30 Oct 2024 11:44:47 -0400 Subject: [PATCH] wip: remove logging --- app/ante/eip712_legacy.go | 451 ------------------------------------- app/ante/eip712_message.go | 151 ------------- app/ante/eip712_types.go | 375 ------------------------------ x/evm/handler.go | 6 +- x/feemarket/handler.go | 6 +- 5 files changed, 4 insertions(+), 985 deletions(-) delete mode 100644 app/ante/eip712_legacy.go delete mode 100644 app/ante/eip712_message.go delete mode 100644 app/ante/eip712_types.go diff --git a/app/ante/eip712_legacy.go b/app/ante/eip712_legacy.go deleted file mode 100644 index ce8f1bf3a7..0000000000 --- a/app/ante/eip712_legacy.go +++ /dev/null @@ -1,451 +0,0 @@ -package ante - -import ( - "encoding/json" - "fmt" - "math/big" - "reflect" // #nosec G702 for sensitive import - "strings" - "time" - - errorsmod "cosmossdk.io/errors" - sdkmath "cosmossdk.io/math" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - sdk "github.com/cosmos/cosmos-sdk/types" - errortypes "github.com/cosmos/cosmos-sdk/types/errors" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/signer/core/apitypes" -) - -type FeeDelegationOptions struct { - FeePayer sdk.AccAddress -} - -const ( - typeDefPrefix = "_" -) - -// LegacyWrapTxToTypedData is an ultimate method that wraps Amino-encoded Cosmos Tx JSON data -// into an EIP712-compatible TypedData request. -func LegacyWrapTxToTypedData( - cdc codectypes.AnyUnpacker, - chainID uint64, - msg sdk.Msg, - data []byte, - feeDelegation *FeeDelegationOptions, -) (apitypes.TypedData, error) { - txData := make(map[string]interface{}) - - if err := json.Unmarshal(data, &txData); err != nil { - return apitypes.TypedData{}, errorsmod.Wrap(errortypes.ErrJSONUnmarshal, "failed to JSON unmarshal data") - } - - domain := apitypes.TypedDataDomain{ - Name: "Cosmos Web3", - Version: "1.0.0", - ChainId: math.NewHexOrDecimal256(int64(chainID)), //nolint:gosec - VerifyingContract: "cosmos", - Salt: "0", - } - - msgTypes, err := extractMsgTypes(cdc, "MsgValue", msg) - if err != nil { - return apitypes.TypedData{}, err - } - - if feeDelegation != nil { - feeInfo, ok := txData["fee"].(map[string]interface{}) - if !ok { - return apitypes.TypedData{}, errorsmod.Wrap(errortypes.ErrInvalidType, "cannot parse fee from tx data") - } - - feeInfo["feePayer"] = feeDelegation.FeePayer.String() - - // also patching msgTypes to include feePayer - msgTypes["Fee"] = []apitypes.Type{ - {Name: "feePayer", Type: "string"}, - {Name: "amount", Type: "Coin[]"}, - {Name: "gas", Type: "string"}, - } - } - - typedData := apitypes.TypedData{ - Types: msgTypes, - PrimaryType: "Tx", - Domain: domain, - Message: txData, - } - - return typedData, nil -} - -func extractMsgTypes(cdc codectypes.AnyUnpacker, msgTypeName string, msg sdk.Msg) (apitypes.Types, error) { - rootTypes := apitypes.Types{ - "EIP712Domain": { - { - Name: "name", - Type: "string", - }, - { - Name: "version", - Type: "string", - }, - { - Name: "chainId", - Type: "uint256", - }, - { - Name: "verifyingContract", - Type: "string", - }, - { - Name: "salt", - Type: "string", - }, - }, - "Tx": { - {Name: "account_number", Type: "string"}, - {Name: "chain_id", Type: "string"}, - {Name: "fee", Type: "Fee"}, - {Name: "memo", Type: "string"}, - {Name: "msgs", Type: "Msg[]"}, - {Name: "sequence", Type: "string"}, - // Note timeout_height was removed because it was not getting filled with the legacyTx - // {Name: "timeout_height", Type: "string"}, - }, - "Fee": { - {Name: "amount", Type: "Coin[]"}, - {Name: "gas", Type: "string"}, - }, - "Coin": { - {Name: "denom", Type: "string"}, - {Name: "amount", Type: "string"}, - }, - "Msg": { - {Name: "type", Type: "string"}, - {Name: "value", Type: msgTypeName}, - }, - msgTypeName: {}, - } - - if err := walkFields(cdc, rootTypes, msgTypeName, msg); err != nil { - return nil, err - } - - return rootTypes, nil -} - -func walkFields(cdc codectypes.AnyUnpacker, typeMap apitypes.Types, rootType string, in interface{}) (err error) { - defer doRecover(&err) - - t := reflect.TypeOf(in) - v := reflect.ValueOf(in) - - for { - if t.Kind() == reflect.Ptr || - t.Kind() == reflect.Interface { - t = t.Elem() - v = v.Elem() - - continue - } - - break - } - - return legacyTraverseFields(cdc, typeMap, rootType, typeDefPrefix, t, v) -} - -type cosmosAnyWrapper struct { - Type string `json:"type"` - Value interface{} `json:"value"` -} - -func legacyTraverseFields( - cdc codectypes.AnyUnpacker, - typeMap apitypes.Types, - rootType string, - prefix string, - t reflect.Type, - v reflect.Value, -) error { - n := t.NumField() - - if prefix == typeDefPrefix { - if len(typeMap[rootType]) == n { - return nil - } - } else { - typeDef := sanitizeTypedef(prefix) - if len(typeMap[typeDef]) == n { - return nil - } - } - - for i := 0; i < n; i++ { - var ( - field reflect.Value - err error - ) - - if v.IsValid() { - field = v.Field(i) - } - - fieldType := t.Field(i).Type - fieldName := jsonNameFromTag(t.Field(i).Tag) - - if fieldType == cosmosAnyType { - // Unpack field, value as Any - if fieldType, field, err = unpackAny(cdc, field); err != nil { - return err - } - } - - // If field is an empty value, do not include in types, since it will not be present in the object - if field.IsZero() { - continue - } - - for { - if fieldType.Kind() == reflect.Ptr { - fieldType = fieldType.Elem() - - if field.IsValid() { - field = field.Elem() - } - - continue - } - - if fieldType.Kind() == reflect.Interface { - fieldType = reflect.TypeOf(field.Interface()) - continue - } - - if field.Kind() == reflect.Ptr { - field = field.Elem() - continue - } - - break - } - - var isCollection bool - if fieldType.Kind() == reflect.Array || fieldType.Kind() == reflect.Slice { - if field.Len() == 0 { - // skip empty collections from type mapping - continue - } - - fieldType = fieldType.Elem() - field = field.Index(0) - isCollection = true - - if fieldType == cosmosAnyType { - if fieldType, field, err = unpackAny(cdc, field); err != nil { - return err - } - } - } - - for { - if fieldType.Kind() == reflect.Ptr { - fieldType = fieldType.Elem() - - if field.IsValid() { - field = field.Elem() - } - - continue - } - - if fieldType.Kind() == reflect.Interface { - fieldType = reflect.TypeOf(field.Interface()) - continue - } - - if field.Kind() == reflect.Ptr { - field = field.Elem() - continue - } - - break - } - - fieldPrefix := fmt.Sprintf("%s.%s", prefix, fieldName) - - ethTyp := typToEth(fieldType) - - if len(ethTyp) > 0 { - // Support array of uint64 - if isCollection && fieldType.Kind() != reflect.Slice && fieldType.Kind() != reflect.Array { - ethTyp += "[]" - } - - if prefix == typeDefPrefix { - typeMap[rootType] = append(typeMap[rootType], apitypes.Type{ - Name: fieldName, - Type: ethTyp, - }) - } else { - typeDef := sanitizeTypedef(prefix) - typeMap[typeDef] = append(typeMap[typeDef], apitypes.Type{ - Name: fieldName, - Type: ethTyp, - }) - } - - continue - } - - if fieldType.Kind() == reflect.Struct { - var fieldTypedef string - - if isCollection { - fieldTypedef = sanitizeTypedef(fieldPrefix) + "[]" - } else { - fieldTypedef = sanitizeTypedef(fieldPrefix) - } - - if prefix == typeDefPrefix { - typeMap[rootType] = append(typeMap[rootType], apitypes.Type{ - Name: fieldName, - Type: fieldTypedef, - }) - } else { - typeDef := sanitizeTypedef(prefix) - typeMap[typeDef] = append(typeMap[typeDef], apitypes.Type{ - Name: fieldName, - Type: fieldTypedef, - }) - } - - if err := legacyTraverseFields(cdc, typeMap, rootType, fieldPrefix, fieldType, field); err != nil { - return err - } - - continue - } - } - - return nil -} - -func jsonNameFromTag(tag reflect.StructTag) string { - jsonTags := tag.Get("json") - parts := strings.Split(jsonTags, ",") - return parts[0] -} - -// Unpack the given Any value with Type/Value deconstruction -func unpackAny(cdc codectypes.AnyUnpacker, field reflect.Value) (reflect.Type, reflect.Value, error) { - anyData, ok := field.Interface().(*codectypes.Any) - if !ok { - return nil, reflect.Value{}, errorsmod.Wrapf(errortypes.ErrPackAny, "%T", field.Interface()) - } - - anyWrapper := &cosmosAnyWrapper{ - Type: anyData.TypeUrl, - } - - if err := cdc.UnpackAny(anyData, &anyWrapper.Value); err != nil { - return nil, reflect.Value{}, errorsmod.Wrap(err, "failed to unpack Any in msg struct") - } - - fieldType := reflect.TypeOf(anyWrapper) - field = reflect.ValueOf(anyWrapper) - - return fieldType, field, nil -} - -var ( - hashType = reflect.TypeOf(common.Hash{}) - addressType = reflect.TypeOf(common.Address{}) - bigIntType = reflect.TypeOf(big.Int{}) - cosmIntType = reflect.TypeOf(sdkmath.Int{}) - cosmDecType = reflect.TypeOf(sdkmath.LegacyDec{}) - timeType = reflect.TypeOf(time.Time{}) - cosmosAnyType = reflect.TypeOf(&codectypes.Any{}) - edType = reflect.TypeOf(ed25519.PubKey{}) -) - -// typToEth supports only basic types and arrays of basic types. -// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md -func typToEth(typ reflect.Type) string { - const str = "string" - - switch typ.Kind() { - case reflect.String: - return str - case reflect.Bool: - return "bool" - case reflect.Int: - return "int64" - case reflect.Int8: - return "int8" - case reflect.Int16: - return "int16" - case reflect.Int32: - return "int32" - case reflect.Int64: - return "int64" - case reflect.Uint: - return "uint64" - case reflect.Uint8: - return "uint8" - case reflect.Uint16: - return "uint16" - case reflect.Uint32: - return "uint32" - case reflect.Uint64: - return "uint64" - case reflect.Slice: - ethName := typToEth(typ.Elem()) - if len(ethName) > 0 { - return ethName + "[]" - } - case reflect.Array: - ethName := typToEth(typ.Elem()) - if len(ethName) > 0 { - return ethName + "[]" - } - case reflect.Ptr: - if typ.Elem().ConvertibleTo(bigIntType) || - typ.Elem().ConvertibleTo(timeType) || - typ.Elem().ConvertibleTo(edType) || - typ.Elem().ConvertibleTo(cosmDecType) || - typ.Elem().ConvertibleTo(cosmIntType) { - return str - } - case reflect.Struct: - if typ.ConvertibleTo(hashType) || - typ.ConvertibleTo(addressType) || - typ.ConvertibleTo(bigIntType) || - typ.ConvertibleTo(edType) || - typ.ConvertibleTo(timeType) || - typ.ConvertibleTo(cosmDecType) || - typ.ConvertibleTo(cosmIntType) { - return str - } - } - - return "" -} - -// doRecover attempts to recover in the event of a panic to -// prevent DOS and gracefully handle an error instead. -func doRecover(err *error) { - if r := recover(); r != nil { - if e, ok := r.(error); ok { - e = errorsmod.Wrap(e, "panicked with error") - *err = e - return - } - - *err = fmt.Errorf("%v", r) - } -} diff --git a/app/ante/eip712_message.go b/app/ante/eip712_message.go deleted file mode 100644 index 8742be9114..0000000000 --- a/app/ante/eip712_message.go +++ /dev/null @@ -1,151 +0,0 @@ -package ante - -import ( - "fmt" - - errorsmod "cosmossdk.io/errors" - errortypes "github.com/cosmos/cosmos-sdk/types/errors" - - "github.com/tidwall/gjson" - "github.com/tidwall/sjson" -) - -type eip712MessagePayload struct { - payload gjson.Result - numPayloadMsgs int - message map[string]interface{} -} - -const ( - payloadMsgsField = "msgs" -) - -// createEIP712MessagePayload generates the EIP-712 message payload -// corresponding to the input data. -func createEIP712MessagePayload(data []byte) (eip712MessagePayload, error) { - basicPayload, err := unmarshalBytesToJSONObject(data) - if err != nil { - return eip712MessagePayload{}, err - } - - payload, numPayloadMsgs, err := FlattenPayloadMessages(basicPayload) - if err != nil { - return eip712MessagePayload{}, errorsmod.Wrap(err, "failed to flatten payload JSON messages") - } - - message, ok := payload.Value().(map[string]interface{}) - if !ok { - return eip712MessagePayload{}, errorsmod.Wrap(errortypes.ErrInvalidType, "failed to parse JSON as map") - } - - messagePayload := eip712MessagePayload{ - payload: payload, - numPayloadMsgs: numPayloadMsgs, - message: message, - } - - return messagePayload, nil -} - -// unmarshalBytesToJSONObject converts a bytestream into -// a JSON object, then makes sure the JSON is an object. -func unmarshalBytesToJSONObject(data []byte) (gjson.Result, error) { - if !gjson.ValidBytes(data) { - return gjson.Result{}, errorsmod.Wrap(errortypes.ErrJSONUnmarshal, "invalid JSON received") - } - - payload := gjson.ParseBytes(data) - - if !payload.IsObject() { - return gjson.Result{}, errorsmod.Wrap(errortypes.ErrJSONUnmarshal, "failed to JSON unmarshal data as object") - } - - return payload, nil -} - -// FlattenPayloadMessages flattens the input payload's messages, representing -// them as key-value pairs of "msg{i}": {Msg}, rather than as an array of Msgs. -// We do this to support messages with different schemas. -func FlattenPayloadMessages(payload gjson.Result) (gjson.Result, int, error) { - flattened := payload - var err error - - msgs, err := getPayloadMessages(payload) - if err != nil { - return gjson.Result{}, 0, err - } - - for i, msg := range msgs { - flattened, err = payloadWithNewMessage(flattened, msg, i) - if err != nil { - return gjson.Result{}, 0, err - } - } - - flattened, err = payloadWithoutMsgsField(flattened) - if err != nil { - return gjson.Result{}, 0, err - } - - return flattened, len(msgs), nil -} - -// getPayloadMessages processes and returns the payload messages as a JSON array. -func getPayloadMessages(payload gjson.Result) ([]gjson.Result, error) { - rawMsgs := payload.Get(payloadMsgsField) - - if !rawMsgs.Exists() { - return nil, errorsmod.Wrap(errortypes.ErrInvalidRequest, "no messages found in payload, unable to parse") - } - - if rawMsgs.Type == gjson.Null { - return []gjson.Result{}, nil - } - - if !rawMsgs.IsArray() { - return nil, errorsmod.Wrap(errortypes.ErrInvalidRequest, "expected type array of messages, cannot parse") - } - - return rawMsgs.Array(), nil -} - -// payloadWithNewMessage returns the updated payload object with the message -// set at the field corresponding to index. -func payloadWithNewMessage(payload gjson.Result, msg gjson.Result, index int) (gjson.Result, error) { - field := msgFieldForIndex(index) - - if payload.Get(field).Exists() { - return gjson.Result{}, errorsmod.Wrapf( - errortypes.ErrInvalidRequest, - "malformed payload received, did not expect to find key at field %v", field, - ) - } - - if !msg.IsObject() { - return gjson.Result{}, errorsmod.Wrapf(errortypes.ErrInvalidRequest, "msg at index %d is not valid JSON: %v", index, msg) - } - - newRaw, err := sjson.SetRaw(payload.Raw, field, msg.Raw) - if err != nil { - return gjson.Result{}, err - } - - return gjson.Parse(newRaw), nil -} - -// msgFieldForIndex returns the payload field for a given message post-flattening. -// e.g. msgs[2] becomes 'msg2' -func msgFieldForIndex(i int) string { - return fmt.Sprintf("msg%d", i) -} - -// payloadWithoutMsgsField returns the updated payload without the "msgs" array -// field, which flattening makes obsolete. -func payloadWithoutMsgsField(payload gjson.Result) (gjson.Result, error) { - newRaw, err := sjson.Delete(payload.Raw, payloadMsgsField) - if err != nil { - return gjson.Result{}, err - } - - return gjson.Parse(newRaw), nil -} diff --git a/app/ante/eip712_types.go b/app/ante/eip712_types.go deleted file mode 100644 index e4a07f508a..0000000000 --- a/app/ante/eip712_types.go +++ /dev/null @@ -1,375 +0,0 @@ -package ante - -import ( - "bytes" - "fmt" - "sort" - "strings" - - "golang.org/x/text/cases" - "golang.org/x/text/language" - - errorsmod "cosmossdk.io/errors" - errortypes "github.com/cosmos/cosmos-sdk/types/errors" - - "github.com/ethereum/go-ethereum/signer/core/apitypes" - "github.com/tidwall/gjson" -) - -const ( - rootPrefix = "_" - typePrefix = "Type" - - txField = "Tx" - ethBool = "bool" - ethInt64 = "int64" - ethString = "string" - - msgTypeField = "type" - - maxDuplicateTypeDefs = 1000 -) - -// getEIP712Types creates and returns the EIP-712 types -// for the given message payload. -func createEIP712Types(messagePayload eip712MessagePayload) (apitypes.Types, error) { - eip712Types := apitypes.Types{ - "EIP712Domain": { - { - Name: "name", - Type: "string", - }, - { - Name: "version", - Type: "string", - }, - { - Name: "chainId", - Type: "uint256", - }, - { - Name: "verifyingContract", - Type: "string", - }, - { - Name: "salt", - Type: "string", - }, - }, - "Tx": { - {Name: "account_number", Type: "string"}, - {Name: "chain_id", Type: "string"}, - {Name: "fee", Type: "Fee"}, - {Name: "memo", Type: "string"}, - {Name: "sequence", Type: "string"}, - // Note timeout_height was removed because it was not getting filled with the legacyTx - }, - "Fee": { - {Name: "amount", Type: "Coin[]"}, - {Name: "gas", Type: "string"}, - }, - "Coin": { - {Name: "denom", Type: "string"}, - {Name: "amount", Type: "string"}, - }, - } - - for i := 0; i < messagePayload.numPayloadMsgs; i++ { - field := msgFieldForIndex(i) - msg := messagePayload.payload.Get(field) - - if err := addMsgTypesToRoot(eip712Types, field, msg); err != nil { - return nil, err - } - } - - return eip712Types, nil -} - -// addMsgTypesToRoot adds all types for the given message -// to eip712Types, recursively handling object sub-fields. -func addMsgTypesToRoot(eip712Types apitypes.Types, msgField string, msg gjson.Result) (err error) { - defer doRecover(&err) - - if !msg.IsObject() { - return errorsmod.Wrapf(errortypes.ErrInvalidRequest, "message is not valid JSON, cannot parse types") - } - - msgRootType, err := msgRootType(msg) - if err != nil { - return err - } - - msgTypeDef, err := recursivelyAddTypesToRoot(eip712Types, msgRootType, rootPrefix, msg) - if err != nil { - return err - } - - addMsgTypeDefToTxSchema(eip712Types, msgField, msgTypeDef) - - return nil -} - -// msgRootType parses the message and returns the formatted -// type signature corresponding to the message type. -func msgRootType(msg gjson.Result) (string, error) { - msgType := msg.Get(msgTypeField).Str - if msgType == "" { - // .Str is empty for arrays and objects - return "", errorsmod.Wrap(errortypes.ErrInvalidType, "malformed message type value, expected type string") - } - - // Convert e.g. cosmos-sdk/MsgSend to TypeMsgSend - typeTokenized := strings.Split(msgType, "/") - msgSignature := typeTokenized[len(typeTokenized)-1] - rootType := fmt.Sprintf("%v%v", typePrefix, msgSignature) - - return rootType, nil -} - -// addMsgTypeDefToTxSchema adds the message's field-type pairing -// to the Tx schema. -func addMsgTypeDefToTxSchema(eip712Types apitypes.Types, msgField, msgTypeDef string) { - eip712Types[txField] = append(eip712Types[txField], apitypes.Type{ - Name: msgField, - Type: msgTypeDef, - }) -} - -// recursivelyAddTypesToRoot walks all types in the given map -// and recursively adds sub-maps as new types when necessary. -// It adds all type definitions to typeMap, then returns a key -// to the json object's type definition within the map. -func recursivelyAddTypesToRoot( - typeMap apitypes.Types, - rootType string, - prefix string, - payload gjson.Result, -) (string, error) { - typesToAdd := []apitypes.Type{} - - // Must sort the JSON keys for deterministic type generation. - sortedFieldNames, err := sortedJSONKeys(payload) - if err != nil { - return "", errorsmod.Wrap(err, "unable to sort object keys") - } - - typeDef := typeDefForPrefix(prefix, rootType) - - for _, fieldName := range sortedFieldNames { - field := payload.Get(fieldName) - if !field.Exists() { - continue - } - - // Handle array type by unwrapping the first element. - // Note that arrays with multiple types are not supported - // using EIP-712, so we can ignore that case. - isCollection := false - if field.IsArray() { - fieldAsArray := field.Array() - - if len(fieldAsArray) == 0 { - // Arbitrarily add string[] type to handle empty arrays, - // since we cannot access the underlying object. - emptyArrayType := "string[]" - typesToAdd = appendedTypesList(typesToAdd, fieldName, emptyArrayType) - - continue - } - - field = fieldAsArray[0] - isCollection = true - } - - ethType := getEthTypeForJSON(field) - - // Handle JSON primitive types by adding the corresponding - // EIP-712 type to the types schema. - if ethType != "" { - if isCollection { - ethType += "[]" - } - typesToAdd = appendedTypesList(typesToAdd, fieldName, ethType) - - continue - } - - // Handle object types recursively. Note that nested array types are not supported - // in EIP-712, so we can exclude that case. - if field.IsObject() { - fieldPrefix := prefixForSubField(prefix, fieldName) - - fieldTypeDef, err := recursivelyAddTypesToRoot(typeMap, rootType, fieldPrefix, field) - if err != nil { - return "", err - } - - fieldTypeDef = sanitizeTypedef(fieldTypeDef) - if isCollection { - fieldTypeDef += "[]" - } - - typesToAdd = appendedTypesList(typesToAdd, fieldName, fieldTypeDef) - - continue - } - } - - return addTypesToRoot(typeMap, typeDef, typesToAdd) -} - -// sortedJSONKeys returns the sorted JSON keys for the input object, -// to be used for deterministic iteration. -func sortedJSONKeys(json gjson.Result) ([]string, error) { - if !json.IsObject() { - return nil, errorsmod.Wrap(errortypes.ErrInvalidType, "expected JSON map to parse") - } - - jsonMap := json.Map() - - keys := make([]string, len(jsonMap)) - i := 0 - // #nosec G705 for map iteration - for k := range jsonMap { - keys[i] = k - i++ - } - - sort.Slice(keys, func(i, j int) bool { - return strings.Compare(keys[i], keys[j]) > 0 - }) - - return keys, nil -} - -// typeDefForPrefix computes the type definition for the given -// prefix. This value will represent the types key within -// the EIP-712 types map. -func typeDefForPrefix(prefix, rootType string) string { - if prefix == rootPrefix { - return rootType - } - return sanitizeTypedef(prefix) -} - -// appendedTypesList returns an array of Types with a new element -// consisting of name and typeDef. -func appendedTypesList(types []apitypes.Type, name, typeDef string) []apitypes.Type { - return append(types, apitypes.Type{ - Name: name, - Type: typeDef, - }) -} - -// prefixForSubField computes the prefix for a subfield by -// indicating that it's derived from the object associated with prefix. -func prefixForSubField(prefix, fieldName string) string { - return fmt.Sprintf("%s.%s", prefix, fieldName) -} - -// addTypesToRoot attempts to add the types to the root at key -// typeDef and returns the key at which the types are present, -// or an error if they cannot be added. If the typeDef key is a -// duplicate, we return the key corresponding to an identical copy -// if present, without modifying the structure. Otherwise, we insert -// the types at the next available typeDef-{n} field. We do this to -// support identically named payloads with different schemas. -func addTypesToRoot(typeMap apitypes.Types, typeDef string, types []apitypes.Type) (string, error) { - var indexedTypeDef string - - indexAsDuplicate := 0 - - for { - indexedTypeDef = typeDefWithIndex(typeDef, indexAsDuplicate) - existingTypes, foundElement := typeMap[indexedTypeDef] - - // Found identical duplicate, so we can simply return - // the existing type definition. - if foundElement && typesAreEqual(types, existingTypes) { - return indexedTypeDef, nil - } - - // Found no element, so we can create a new one at this index. - if !foundElement { - break - } - - indexAsDuplicate++ - - if indexAsDuplicate == maxDuplicateTypeDefs { - return "", errorsmod.Wrap(errortypes.ErrInvalidRequest, "exceeded maximum number of duplicates for a single type definition") - } - } - - typeMap[indexedTypeDef] = types - - return indexedTypeDef, nil -} - -// typeDefWithIndex creates a duplicate-indexed type definition -// to differentiate between different schemas with the same name. -func typeDefWithIndex(typeDef string, index int) string { - return fmt.Sprintf("%v%d", typeDef, index) -} - -// typesAreEqual compares two apitypes.Type arrays -// and returns a boolean indicating whether they have -// the same values. -// It assumes both arrays are in the same sorted order. -func typesAreEqual(types1 []apitypes.Type, types2 []apitypes.Type) bool { - if len(types1) != len(types2) { - return false - } - - for i := 0; i < len(types1); i++ { - if types1[i].Name != types2[i].Name || types1[i].Type != types2[i].Type { - return false - } - } - - return true -} - -// _.foo_bar.baz -> TypeFooBarBaz -// -// Since Geth does not tolerate complex EIP-712 type names, we need to sanitize -// the inputs. -func sanitizeTypedef(str string) string { - buf := new(bytes.Buffer) - caser := cases.Title(language.English, cases.NoLower) - parts := strings.Split(str, ".") - - for _, part := range parts { - if part == rootPrefix { - buf.WriteString(typePrefix) - continue - } - - subparts := strings.Split(part, "_") - for _, subpart := range subparts { - buf.WriteString(caser.String(subpart)) - } - } - - return buf.String() -} - -// getEthTypeForJSON converts a JSON type to an Ethereum type. -// It returns an empty string for Objects, Arrays, or Null. -// See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md for more. -func getEthTypeForJSON(json gjson.Result) string { - switch json.Type { - case gjson.True, gjson.False: - return ethBool - case gjson.Number: - return ethInt64 - case gjson.String: - return ethString - case gjson.JSON: - // Array or Object type - return "" - default: - return "" - } -} diff --git a/x/evm/handler.go b/x/evm/handler.go index 4499264dde..5e6c9f45c9 100644 --- a/x/evm/handler.go +++ b/x/evm/handler.go @@ -17,17 +17,15 @@ package evm import ( errorsmod "cosmossdk.io/errors" + "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" errortypes "github.com/cosmos/cosmos-sdk/types/errors" "github.com/evmos/ethermint/x/evm/types" ) -// Handler defines the core of the state transition function of an application. -type Handler func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) - // NewHandler returns a handler for Ethermint type messages. -func NewHandler(server types.MsgServer) Handler { +func NewHandler(server types.MsgServer) baseapp.MsgServiceHandler { return func(ctx sdk.Context, msg sdk.Msg) (result *sdk.Result, err error) { ctx = ctx.WithEventManager(sdk.NewEventManager()) diff --git a/x/feemarket/handler.go b/x/feemarket/handler.go index 6a1b0f8525..efe216bff2 100644 --- a/x/feemarket/handler.go +++ b/x/feemarket/handler.go @@ -2,16 +2,14 @@ package feemarket import ( errorsmod "cosmossdk.io/errors" + "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" errortypes "github.com/cosmos/cosmos-sdk/types/errors" "github.com/evmos/ethermint/x/feemarket/types" ) -// Handler defines the core of the state transition function of an application. -type Handler func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) - // NewHandler returns a handler for Ethermint type messages. -func NewHandler(server types.MsgServer) Handler { +func NewHandler(server types.MsgServer) baseapp.MsgServiceHandler { return func(ctx sdk.Context, msg sdk.Msg) (result *sdk.Result, err error) { ctx = ctx.WithEventManager(sdk.NewEventManager())