refactor(x/tx): use dynamicpb instead of type resolver in any marshal (#16048)

Co-authored-by: Aaron Craelius <aaron@regen.network>
This commit is contained in:
Matt Kocubinski
2023-05-08 19:20:23 +00:00
committed by GitHub
co-authored by Aaron Craelius
parent 12923c33ed
commit 2f21cb5050
17 changed files with 181 additions and 49 deletions
+39
View File
@@ -11,8 +11,12 @@ import (
gogoproto "github.com/cosmos/gogoproto/proto"
"google.golang.org/grpc/encoding"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/types/dynamicpb"
"google.golang.org/protobuf/types/known/anypb"
"cosmossdk.io/x/tx/signing/aminojson"
"github.com/cosmos/cosmos-sdk/codec/types"
)
@@ -160,6 +164,41 @@ func (pc *ProtoCodec) MustMarshalJSON(o gogoproto.Message) []byte {
return bz
}
// MarshalAminoJSON provides aminojson.Encoder compatibility for gogoproto messages.
// x/tx/signing/aminojson cannot marshal gogoproto messages directly since this type does not implement
// the standard library google.golang.org/protobuf/proto.Message.
// We convert gogo types to dynamicpb messages and then marshal that directly to amino JSON.
func (pc *ProtoCodec) MarshalAminoJSON(msg gogoproto.Message) ([]byte, error) {
encoder := aminojson.NewEncoder(aminojson.EncoderOptions{FileResolver: pc.interfaceRegistry})
gogoBytes, err := gogoproto.Marshal(msg)
if err != nil {
return nil, err
}
var protoMsg protoreflect.ProtoMessage
typ, err := protoregistry.GlobalTypes.FindMessageByURL(fmt.Sprintf("/%s", gogoproto.MessageName(msg)))
if typ != nil && err != nil {
protoMsg = typ.New().Interface()
} else {
desc, err := pc.interfaceRegistry.FindDescriptorByName(protoreflect.FullName(gogoproto.MessageName(msg)))
if err != nil {
return nil, err
}
dynamicMsgType := dynamicpb.NewMessageType(desc.(protoreflect.MessageDescriptor))
protoMsg = dynamicMsgType.New().Interface()
}
err = proto.Unmarshal(gogoBytes, protoMsg)
if err != nil {
return nil, err
}
jsonBytes, err := encoder.Marshal(protoMsg)
if err != nil {
return nil, err
}
return jsonBytes, nil
}
// UnmarshalJSON implements JSONCodec.UnmarshalJSON method,
// it unmarshals from JSON using proto codec.
// NOTE: this function must be used with a concrete type which