fix(x/tx/amino): special case for string represented decimals (#22161)
This commit is contained in:
@@ -258,6 +258,11 @@ func TestAminoJSON_LegacyParity(t *testing.T) {
|
||||
"gov/v1_msg_submit_proposal": {
|
||||
gogo: &gov_v1_types.MsgSubmitProposal{},
|
||||
},
|
||||
"gov/v1_params": {
|
||||
gogo: &gov_v1_types.Params{
|
||||
Quorum: math.LegacyMustNewDecFromStr("0.33").String(),
|
||||
},
|
||||
},
|
||||
"slashing/params/dec": {
|
||||
gogo: &slashingtypes.Params{
|
||||
DowntimeJailDuration: 1e9 + 7,
|
||||
|
||||
@@ -43,7 +43,7 @@ func cosmosIntEncoder(_ *Encoder, v protoreflect.Value, w io.Writer) error {
|
||||
}
|
||||
}
|
||||
|
||||
// cosmosDecEncoder provides legacy compatible encoding for cosmos.Dec and cosmos.Int types. These are sometimes
|
||||
// cosmosDecEncoder provides legacy compatible encoding for cosmos.Dec types. These are sometimes
|
||||
// represented as strings in pulsar messages and sometimes as bytes. This encoder handles both cases.
|
||||
func cosmosDecEncoder(_ *Encoder, v protoreflect.Value, w io.Writer) error {
|
||||
switch val := v.Interface().(type) {
|
||||
@@ -54,7 +54,7 @@ func cosmosDecEncoder(_ *Encoder, v protoreflect.Value, w io.Writer) error {
|
||||
var dec math.LegacyDec
|
||||
err := dec.Unmarshal([]byte(val))
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to unmarshal for Amino JSON encoding; string %q into Dec: %w", val, err)
|
||||
}
|
||||
return jsonMarshal(w, dec.String())
|
||||
case []byte:
|
||||
|
||||
@@ -16,6 +16,8 @@ import (
|
||||
"cosmossdk.io/x/tx/signing"
|
||||
)
|
||||
|
||||
const cosmosDecType = "cosmos.Dec"
|
||||
|
||||
// MessageEncoder is a function that can encode a protobuf protoreflect.Message to JSON.
|
||||
type MessageEncoder func(*Encoder, protoreflect.Message, io.Writer) error
|
||||
|
||||
@@ -68,8 +70,8 @@ func NewEncoder(options EncoderOptions) Encoder {
|
||||
}
|
||||
enc := Encoder{
|
||||
cosmosProtoScalarEncoders: map[string]FieldEncoder{
|
||||
"cosmos.Dec": cosmosDecEncoder,
|
||||
"cosmos.Int": cosmosIntEncoder,
|
||||
cosmosDecType: cosmosDecEncoder,
|
||||
"cosmos.Int": cosmosIntEncoder,
|
||||
},
|
||||
aminoMessageEncoders: map[string]MessageEncoder{
|
||||
"key_field": keyFieldEncoder,
|
||||
@@ -366,7 +368,7 @@ func (enc Encoder) marshalMessage(msg protoreflect.Message, writer io.Writer) er
|
||||
}
|
||||
|
||||
// encode value
|
||||
if encoder := enc.getFieldEncoding(f); encoder != nil {
|
||||
if encoder := enc.getFieldEncoder(f); encoder != nil {
|
||||
err = encoder(&enc, v, writer)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -2,11 +2,14 @@ package aminojson
|
||||
|
||||
import (
|
||||
cosmos_proto "github.com/cosmos/cosmos-proto"
|
||||
gogo "github.com/cosmos/gogoproto/gogoproto"
|
||||
gogoproto "github.com/cosmos/gogoproto/proto"
|
||||
"github.com/iancoleman/strcase"
|
||||
"github.com/pkg/errors"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/runtime/protoimpl"
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
|
||||
"cosmossdk.io/api/amino"
|
||||
)
|
||||
@@ -100,7 +103,16 @@ func (enc Encoder) getMessageEncoder(message protoreflect.Message) MessageEncode
|
||||
return nil
|
||||
}
|
||||
|
||||
func (enc Encoder) getFieldEncoding(field protoreflect.FieldDescriptor) FieldEncoder {
|
||||
var customTypeExtension = protoimpl.ExtensionInfo{
|
||||
ExtendedType: (*descriptorpb.FieldOptions)(nil),
|
||||
ExtensionType: gogo.E_Customtype.ExtensionType,
|
||||
Field: gogo.E_Customtype.Field,
|
||||
Name: gogo.E_Customtype.Name,
|
||||
Tag: gogo.E_Customtype.Tag,
|
||||
Filename: gogo.E_Customtype.Filename,
|
||||
}
|
||||
|
||||
func (enc Encoder) getFieldEncoder(field protoreflect.FieldDescriptor) FieldEncoder {
|
||||
opts := field.Options()
|
||||
if proto.HasExtension(opts, amino.E_Encoding) {
|
||||
encoding := proto.GetExtension(opts, amino.E_Encoding).(string)
|
||||
@@ -110,6 +122,18 @@ func (enc Encoder) getFieldEncoding(field protoreflect.FieldDescriptor) FieldEnc
|
||||
}
|
||||
if proto.HasExtension(opts, cosmos_proto.E_Scalar) {
|
||||
scalar := proto.GetExtension(opts, cosmos_proto.E_Scalar).(string)
|
||||
// do not handle encoding of fields tagged only with scalar which are not backed by a
|
||||
// LegacyDec custom type. This types are handled by the default encoding, as they are
|
||||
// expected to already be encoded as their human readable string representation
|
||||
// containing a radix, i.e. "1.2345".
|
||||
// For example:
|
||||
// https://github.com/cosmos/cosmos-sdk/blob/9076487d035e43d39fe54e8498da1ce31b9c845c/x/gov/proto/cosmos/gov/v1/gov.proto#L274
|
||||
if scalar == cosmosDecType {
|
||||
customType := proto.GetExtension(opts, &customTypeExtension)
|
||||
if customType != "cosmossdk.io/math.LegacyDec" {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if fn, ok := enc.cosmosProtoScalarEncoders[scalar]; ok {
|
||||
return fn
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user