refactor: migrate codec/types to type aliases, remove depinject dep on sdk (#24336)
Co-authored-by: Alex | Interchain Labs <alex@interchainlabs.io> Co-authored-by: Tyler <48813565+technicallyty@users.noreply.github.com>
This commit is contained in:
co-authored by
Alex | Interchain Labs
Tyler
parent
41e3e9d004
commit
167f3f12e2
+7
-147
@@ -1,154 +1,14 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
protov2 "google.golang.org/protobuf/proto"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
gogoany "github.com/cosmos/gogoproto/types/any"
|
||||
)
|
||||
|
||||
type Any struct {
|
||||
// A URL/resource name that uniquely identifies the type of the serialized
|
||||
// protocol buffer message. This string must contain at least
|
||||
// one "/" character. The last segment of the URL's path must represent
|
||||
// the fully qualified name of the type (as in
|
||||
// `path/google.protobuf.Duration`). The name should be in a canonical form
|
||||
// (e.g., leading "." is not accepted).
|
||||
//
|
||||
// In practice, teams usually precompile into the binary all types that they
|
||||
// expect it to use in the context of Any. However, for URLs which use the
|
||||
// scheme `http`, `https`, or no scheme, one can optionally set up a type
|
||||
// server that maps type URLs to message definitions as follows:
|
||||
//
|
||||
// * If no scheme is provided, `https` is assumed.
|
||||
// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
|
||||
// value in binary format, or produce an error.
|
||||
// * Applications are allowed to cache lookup results based on the
|
||||
// URL, or have them precompiled into a binary to avoid any
|
||||
// lookup. Therefore, binary compatibility needs to be preserved
|
||||
// on changes to types. (Use versioned type names to manage
|
||||
// breaking changes.)
|
||||
//
|
||||
// Note: this functionality is not currently available in the official
|
||||
// protobuf release, and it is not used for type URLs beginning with
|
||||
// type.googleapis.com.
|
||||
//
|
||||
// Schemes other than `http`, `https` (or the empty scheme) might be
|
||||
// used with implementation specific semantics.
|
||||
// Any is an alias for github.com/cosmos/gogoproto/types/any.Any.
|
||||
type Any = gogoany.Any
|
||||
|
||||
TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"`
|
||||
// NewAnyWithValue is an alias for github.com/cosmos/gogoproto/types/any.NewAnyWithCacheWithValue.
|
||||
var NewAnyWithValue = gogoany.NewAnyWithCacheWithValue
|
||||
|
||||
// Must be a valid serialized protocol buffer of the above specified type.
|
||||
Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
|
||||
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
|
||||
cachedValue interface{}
|
||||
|
||||
compat *anyCompat
|
||||
}
|
||||
|
||||
// NewAnyWithValue constructs a new Any packed with the value provided or
|
||||
// returns an error if that value couldn't be packed. This also caches
|
||||
// the packed value so that it can be retrieved from GetCachedValue without
|
||||
// unmarshaling
|
||||
func NewAnyWithValue(v proto.Message) (*Any, error) {
|
||||
if v == nil {
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrPackAny, "Expecting non nil value to create a new Any")
|
||||
}
|
||||
|
||||
var (
|
||||
bz []byte
|
||||
err error
|
||||
)
|
||||
if msg, ok := v.(protov2.Message); ok {
|
||||
protov2MarshalOpts := protov2.MarshalOptions{Deterministic: true}
|
||||
bz, err = protov2MarshalOpts.Marshal(msg)
|
||||
} else {
|
||||
bz, err = proto.Marshal(v)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Any{
|
||||
TypeUrl: MsgTypeURL(v),
|
||||
Value: bz,
|
||||
cachedValue: v,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UnsafePackAny packs the value x in the Any and instead of returning the error
|
||||
// in the case of a packing failure, keeps the cached value. This should only
|
||||
// be used in situations where compatibility is needed with amino. Amino-only
|
||||
// values can safely be packed using this method when they will only be
|
||||
// marshaled with amino and not protobuf.
|
||||
func UnsafePackAny(x interface{}) *Any {
|
||||
if msg, ok := x.(proto.Message); ok {
|
||||
any, err := NewAnyWithValue(msg)
|
||||
if err == nil {
|
||||
return any
|
||||
}
|
||||
}
|
||||
return &Any{cachedValue: x}
|
||||
}
|
||||
|
||||
// pack packs the value x in the Any or returns an error. This also caches
|
||||
// the packed value so that it can be retrieved from GetCachedValue without
|
||||
// unmarshaling
|
||||
func (any *Any) pack(x proto.Message) error {
|
||||
any.TypeUrl = MsgTypeURL(x)
|
||||
|
||||
var (
|
||||
bz []byte
|
||||
err error
|
||||
)
|
||||
if msg, ok := x.(protov2.Message); ok {
|
||||
protov2MarshalOpts := protov2.MarshalOptions{Deterministic: true}
|
||||
bz, err = protov2MarshalOpts.Marshal(msg)
|
||||
} else {
|
||||
bz, err = proto.Marshal(x)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
any.Value = bz
|
||||
any.cachedValue = x
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetCachedValue returns the cached value from the Any if present
|
||||
func (any *Any) GetCachedValue() interface{} {
|
||||
return any.cachedValue
|
||||
}
|
||||
|
||||
// GoString returns a string representing valid go code to reproduce the current state of
|
||||
// the struct.
|
||||
func (any *Any) GoString() string {
|
||||
if any == nil {
|
||||
return "nil"
|
||||
}
|
||||
extra := ""
|
||||
if any.XXX_unrecognized != nil {
|
||||
extra = fmt.Sprintf(",\n XXX_unrecognized: %#v,\n", any.XXX_unrecognized)
|
||||
}
|
||||
return fmt.Sprintf("&Any{TypeUrl: %#v,\n Value: %#v%s\n}",
|
||||
any.TypeUrl, any.Value, extra)
|
||||
}
|
||||
|
||||
// String implements the stringer interface
|
||||
func (any *Any) String() string {
|
||||
if any == nil {
|
||||
return "nil"
|
||||
}
|
||||
return fmt.Sprintf("&Any{TypeUrl:%v,Value:%v,XXX_unrecognized:%v}",
|
||||
any.TypeUrl, any.Value, any.XXX_unrecognized)
|
||||
}
|
||||
// UnsafePackAny is an alias for github.com/cosmos/gogoproto/types/any.UnsafePackAnyWithCache.
|
||||
var UnsafePackAny = gogoany.UnsafePackAnyWithCache
|
||||
|
||||
@@ -1,535 +0,0 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: google/protobuf/any.proto
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
bytes "bytes"
|
||||
fmt "fmt"
|
||||
_ "github.com/cosmos/gogoproto/gogoproto"
|
||||
proto "github.com/cosmos/gogoproto/proto"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
func (m *Any) Reset() { *m = Any{} }
|
||||
func (*Any) ProtoMessage() {}
|
||||
func (*Any) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_b53526c13ae22eb4, []int{0}
|
||||
}
|
||||
func (*Any) XXX_WellKnownType() string { return "Any" }
|
||||
func (m *Any) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *Any) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_Any.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *Any) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Any.Merge(m, src)
|
||||
}
|
||||
func (m *Any) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *Any) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Any.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Any proto.InternalMessageInfo
|
||||
|
||||
func (m *Any) GetTypeUrl() string {
|
||||
if m != nil {
|
||||
return m.TypeUrl
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Any) GetValue() []byte {
|
||||
if m != nil {
|
||||
return m.Value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*Any) XXX_MessageName() string {
|
||||
return "google.protobuf.Any"
|
||||
}
|
||||
func init() {
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor_b53526c13ae22eb4) }
|
||||
|
||||
var fileDescriptor_b53526c13ae22eb4 = []byte{
|
||||
// 248 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xcf, 0xcf, 0x4f,
|
||||
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcc, 0xab, 0xd4,
|
||||
0x03, 0x73, 0x84, 0xf8, 0x21, 0x52, 0x7a, 0x30, 0x29, 0x29, 0x91, 0xf4, 0xfc, 0xf4, 0x7c, 0x30,
|
||||
0x4f, 0x1f, 0xc4, 0x82, 0x48, 0x28, 0x79, 0x70, 0x31, 0x3b, 0xe6, 0x55, 0x0a, 0x49, 0x72, 0x71,
|
||||
0x94, 0x54, 0x16, 0xa4, 0xc6, 0x97, 0x16, 0xe5, 0x48, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0xb1,
|
||||
0x83, 0xf8, 0xa1, 0x45, 0x39, 0x42, 0x22, 0x5c, 0xac, 0x65, 0x89, 0x39, 0xa5, 0xa9, 0x12, 0x4c,
|
||||
0x0a, 0x8c, 0x1a, 0x3c, 0x41, 0x10, 0x8e, 0x95, 0xc0, 0x8c, 0x05, 0xf2, 0x0c, 0x1b, 0x16, 0xc8,
|
||||
0x33, 0x7c, 0x58, 0x28, 0xcf, 0xd0, 0x70, 0x47, 0x81, 0xc1, 0xa9, 0x99, 0xf1, 0xc6, 0x43, 0x39,
|
||||
0x86, 0x0f, 0x0f, 0xe5, 0x18, 0x7f, 0x3c, 0x94, 0x63, 0x6c, 0x78, 0x24, 0xc7, 0xb8, 0xe2, 0x91,
|
||||
0x1c, 0xe3, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0xf8, 0xe2,
|
||||
0x91, 0x1c, 0xc3, 0x07, 0x90, 0xf8, 0x63, 0x39, 0xc6, 0x03, 0x8f, 0xe5, 0x18, 0x4e, 0x3c, 0x96,
|
||||
0x63, 0xe4, 0x12, 0x4e, 0xce, 0xcf, 0xd5, 0x43, 0x73, 0xab, 0x13, 0x87, 0x63, 0x5e, 0x65, 0x00,
|
||||
0x88, 0x13, 0xc0, 0x18, 0xc5, 0x0a, 0x72, 0x48, 0xf1, 0x22, 0x26, 0x66, 0xf7, 0x00, 0xa7, 0x55,
|
||||
0x4c, 0x72, 0xee, 0x10, 0xa5, 0x01, 0x50, 0xa5, 0x7a, 0xe1, 0xa9, 0x39, 0x39, 0xde, 0x79, 0xf9,
|
||||
0xe5, 0x79, 0x21, 0x20, 0x65, 0x49, 0x6c, 0x60, 0x33, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff,
|
||||
0x4d, 0x91, 0x00, 0xa0, 0x1a, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (this *Any) Compare(that interface{}) int {
|
||||
if that == nil {
|
||||
if this == nil {
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
that1, ok := that.(*Any)
|
||||
if !ok {
|
||||
that2, ok := that.(Any)
|
||||
if ok {
|
||||
that1 = &that2
|
||||
} else {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
if that1 == nil {
|
||||
if this == nil {
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
} else if this == nil {
|
||||
return -1
|
||||
}
|
||||
if this.TypeUrl != that1.TypeUrl {
|
||||
if this.TypeUrl < that1.TypeUrl {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
if c := bytes.Compare(this.Value, that1.Value); c != 0 {
|
||||
return c
|
||||
}
|
||||
if c := bytes.Compare(this.XXX_unrecognized, that1.XXX_unrecognized); c != 0 {
|
||||
return c
|
||||
}
|
||||
return 0
|
||||
}
|
||||
func (this *Any) Equal(that interface{}) bool {
|
||||
if that == nil {
|
||||
return this == nil
|
||||
}
|
||||
|
||||
that1, ok := that.(*Any)
|
||||
if !ok {
|
||||
that2, ok := that.(Any)
|
||||
if ok {
|
||||
that1 = &that2
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if that1 == nil {
|
||||
return this == nil
|
||||
} else if this == nil {
|
||||
return false
|
||||
}
|
||||
if this.TypeUrl != that1.TypeUrl {
|
||||
return false
|
||||
}
|
||||
if !bytes.Equal(this.Value, that1.Value) {
|
||||
return false
|
||||
}
|
||||
if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
func (m *Any) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *Any) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *Any) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.XXX_unrecognized != nil {
|
||||
i -= len(m.XXX_unrecognized)
|
||||
copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
if len(m.Value) > 0 {
|
||||
i -= len(m.Value)
|
||||
copy(dAtA[i:], m.Value)
|
||||
i = encodeVarintAny(dAtA, i, uint64(len(m.Value)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
if len(m.TypeUrl) > 0 {
|
||||
i -= len(m.TypeUrl)
|
||||
copy(dAtA[i:], m.TypeUrl)
|
||||
i = encodeVarintAny(dAtA, i, uint64(len(m.TypeUrl)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintAny(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovAny(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func NewPopulatedAny(r randyAny, easy bool) *Any {
|
||||
this := &Any{}
|
||||
this.TypeUrl = string(randStringAny(r))
|
||||
v1 := r.Intn(100)
|
||||
this.Value = make([]byte, v1)
|
||||
for i := 0; i < v1; i++ {
|
||||
this.Value[i] = byte(r.Intn(256))
|
||||
}
|
||||
if !easy && r.Intn(10) != 0 {
|
||||
this.XXX_unrecognized = randUnrecognizedAny(r, 3)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
type randyAny interface {
|
||||
Float32() float32
|
||||
Float64() float64
|
||||
Int63() int64
|
||||
Int31() int32
|
||||
Uint32() uint32
|
||||
Intn(n int) int
|
||||
}
|
||||
|
||||
func randUTF8RuneAny(r randyAny) rune {
|
||||
ru := r.Intn(62)
|
||||
if ru < 10 {
|
||||
return rune(ru + 48)
|
||||
} else if ru < 36 {
|
||||
return rune(ru + 55)
|
||||
}
|
||||
return rune(ru + 61)
|
||||
}
|
||||
func randStringAny(r randyAny) string {
|
||||
v2 := r.Intn(100)
|
||||
tmps := make([]rune, v2)
|
||||
for i := 0; i < v2; i++ {
|
||||
tmps[i] = randUTF8RuneAny(r)
|
||||
}
|
||||
return string(tmps)
|
||||
}
|
||||
func randUnrecognizedAny(r randyAny, maxFieldNumber int) (dAtA []byte) {
|
||||
l := r.Intn(5)
|
||||
for i := 0; i < l; i++ {
|
||||
wire := r.Intn(4)
|
||||
if wire == 3 {
|
||||
wire = 5
|
||||
}
|
||||
fieldNumber := maxFieldNumber + r.Intn(100)
|
||||
dAtA = randFieldAny(dAtA, r, fieldNumber, wire)
|
||||
}
|
||||
return dAtA
|
||||
}
|
||||
func randFieldAny(dAtA []byte, r randyAny, fieldNumber int, wire int) []byte {
|
||||
key := uint32(fieldNumber)<<3 | uint32(wire)
|
||||
switch wire {
|
||||
case 0:
|
||||
dAtA = encodeVarintPopulateAny(dAtA, uint64(key))
|
||||
v3 := r.Int63()
|
||||
if r.Intn(2) == 0 {
|
||||
v3 *= -1
|
||||
}
|
||||
dAtA = encodeVarintPopulateAny(dAtA, uint64(v3))
|
||||
case 1:
|
||||
dAtA = encodeVarintPopulateAny(dAtA, uint64(key))
|
||||
dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))
|
||||
case 2:
|
||||
dAtA = encodeVarintPopulateAny(dAtA, uint64(key))
|
||||
ll := r.Intn(100)
|
||||
dAtA = encodeVarintPopulateAny(dAtA, uint64(ll))
|
||||
for j := 0; j < ll; j++ {
|
||||
dAtA = append(dAtA, byte(r.Intn(256)))
|
||||
}
|
||||
default:
|
||||
dAtA = encodeVarintPopulateAny(dAtA, uint64(key))
|
||||
dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))
|
||||
}
|
||||
return dAtA
|
||||
}
|
||||
func encodeVarintPopulateAny(dAtA []byte, v uint64) []byte {
|
||||
for v >= 1<<7 {
|
||||
dAtA = append(dAtA, uint8(uint64(v)&0x7f|0x80))
|
||||
v >>= 7
|
||||
}
|
||||
dAtA = append(dAtA, uint8(v))
|
||||
return dAtA
|
||||
}
|
||||
func (m *Any) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.TypeUrl)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovAny(uint64(l))
|
||||
}
|
||||
l = len(m.Value)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovAny(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovAny(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozAny(x uint64) (n int) {
|
||||
return sovAny(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *Any) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowAny
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Any: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Any: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field TypeUrl", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowAny
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthAny
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthAny
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.TypeUrl = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowAny
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthAny
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthAny
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Value = append(m.Value[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.Value == nil {
|
||||
m.Value = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipAny(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthAny
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipAny(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowAny
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowAny
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowAny
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthAny
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupAny
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthAny
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthAny = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowAny = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupAny = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
@@ -1,67 +0,0 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type Dog struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=size,proto3" json:"size,omitempty"`
|
||||
}
|
||||
|
||||
func (d Dog) Greet() string { return d.Name }
|
||||
|
||||
// We implement a minimal proto.Message interface
|
||||
func (d *Dog) Reset() { d.Name = "" }
|
||||
func (d *Dog) String() string { return d.Name }
|
||||
func (d *Dog) ProtoMessage() {}
|
||||
func (d *Dog) XXX_MessageName() string { return "tests/dog" }
|
||||
|
||||
type Animal interface {
|
||||
Greet() string
|
||||
}
|
||||
|
||||
var (
|
||||
_ Animal = (*Dog)(nil)
|
||||
_ proto.Message = (*Dog)(nil)
|
||||
)
|
||||
|
||||
func TestAnyPackUnpack(t *testing.T) {
|
||||
registry := NewInterfaceRegistry()
|
||||
registry.RegisterInterface("Animal", (*Animal)(nil))
|
||||
registry.RegisterImplementations(
|
||||
(*Animal)(nil),
|
||||
&Dog{},
|
||||
)
|
||||
|
||||
spot := &Dog{Name: "Spot"}
|
||||
var animal Animal
|
||||
|
||||
// with cache
|
||||
any, err := NewAnyWithValue(spot)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, spot, any.GetCachedValue())
|
||||
err = registry.UnpackAny(any, &animal)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, spot, animal)
|
||||
|
||||
// without cache
|
||||
any.cachedValue = nil
|
||||
err = registry.UnpackAny(any, &animal)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, spot, animal)
|
||||
}
|
||||
|
||||
func TestString(t *testing.T) {
|
||||
require := require.New(t)
|
||||
spot := &Dog{Name: "Spot"}
|
||||
any, err := NewAnyWithValue(spot)
|
||||
require.NoError(err)
|
||||
|
||||
require.Equal("&Any{TypeUrl:/tests/dog,Value:[10 4 83 112 111 116],XXX_unrecognized:[]}", any.String())
|
||||
require.Equal(`&Any{TypeUrl: "/tests/dog",
|
||||
Value: []byte{0xa, 0x4, 0x53, 0x70, 0x6f, 0x74}
|
||||
}`, any.GoString())
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
package types_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
)
|
||||
|
||||
type errOnMarshal struct {
|
||||
testdata.Dog
|
||||
}
|
||||
|
||||
var _ proto.Message = (*errOnMarshal)(nil)
|
||||
|
||||
var errAlways = fmt.Errorf("always erroring")
|
||||
|
||||
func (eom *errOnMarshal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return nil, errAlways
|
||||
}
|
||||
|
||||
var eom = &errOnMarshal{}
|
||||
|
||||
// Ensure that returning an error doesn't suddenly allocate and waste bytes.
|
||||
// See https://github.com/cosmos/cosmos-sdk/issues/8537
|
||||
func TestNewAnyWithCustomTypeURLWithErrorNoAllocation(t *testing.T) {
|
||||
// This tests continues to fail inconsistently.
|
||||
//
|
||||
// Example: https://github.com/cosmos/cosmos-sdk/pull/9246/checks?check_run_id=2643313958#step:6:118
|
||||
// Ref: https://github.com/cosmos/cosmos-sdk/issues/9010
|
||||
t.SkipNow()
|
||||
|
||||
// make sure we're not in the middle of a GC.
|
||||
runtime.GC()
|
||||
|
||||
var ms1, ms2 runtime.MemStats
|
||||
runtime.ReadMemStats(&ms1)
|
||||
any, err := types.NewAnyWithValue(eom)
|
||||
runtime.ReadMemStats(&ms2)
|
||||
// Ensure that no fresh allocation was made.
|
||||
if diff := ms2.HeapAlloc - ms1.HeapAlloc; diff > 0 {
|
||||
t.Errorf("Unexpected allocation of %d bytes", diff)
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatal("err wasn't returned")
|
||||
}
|
||||
if any != nil {
|
||||
t.Fatalf("Unexpectedly got a non-nil Any value: %v", any)
|
||||
}
|
||||
}
|
||||
|
||||
var sink interface{}
|
||||
|
||||
func BenchmarkNewAnyWithCustomTypeURLWithErrorReturned(b *testing.B) {
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
any, err := types.NewAnyWithValue(eom)
|
||||
if err == nil {
|
||||
b.Fatal("err wasn't returned")
|
||||
}
|
||||
if any != nil {
|
||||
b.Fatalf("Unexpectedly got a non-nil Any value: %v", any)
|
||||
}
|
||||
sink = any
|
||||
}
|
||||
if sink == nil {
|
||||
b.Fatal("benchmark didn't run")
|
||||
}
|
||||
sink = (interface{})(nil)
|
||||
}
|
||||
+12
-199
@@ -1,210 +1,23 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"runtime/debug"
|
||||
|
||||
"github.com/cosmos/gogoproto/jsonpb"
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
gogoany "github.com/cosmos/gogoproto/types/any"
|
||||
)
|
||||
|
||||
type anyCompat struct {
|
||||
aminoBz []byte
|
||||
jsonBz []byte
|
||||
err error
|
||||
}
|
||||
|
||||
// Deprecated: this is no longer used for anything.
|
||||
var Debug = true
|
||||
|
||||
func anyCompatError(errType string, x interface{}) error {
|
||||
if Debug {
|
||||
debug.PrintStack()
|
||||
}
|
||||
return fmt.Errorf(
|
||||
"%s marshaling error for %+v, this is likely because "+
|
||||
"amino is being used directly (instead of codec.LegacyAmino which is preferred) "+
|
||||
"or UnpackInterfacesMessage is not defined for some type which contains "+
|
||||
"a protobuf Any either directly or via one of its members. To see a "+
|
||||
"stacktrace of where the error is coming from, set the var Debug = true "+
|
||||
"in codec/types/compat.go",
|
||||
errType, x,
|
||||
)
|
||||
}
|
||||
// AminoUnpacker is an alias for github.com/cosmos/gogoproto/types/any.AminoUnpacker.
|
||||
type AminoUnpacker = gogoany.AminoUnpacker
|
||||
|
||||
func (any Any) MarshalAmino() ([]byte, error) {
|
||||
ac := any.compat
|
||||
if ac == nil {
|
||||
return nil, anyCompatError("amino binary marshal", any)
|
||||
}
|
||||
return ac.aminoBz, ac.err
|
||||
}
|
||||
// AminoPacker is an alias for github.com/cosmos/gogoproto/types/any.AminoPacker.
|
||||
type AminoPacker = gogoany.AminoPacker
|
||||
|
||||
func (any *Any) UnmarshalAmino(bz []byte) error {
|
||||
any.compat = &anyCompat{
|
||||
aminoBz: bz,
|
||||
err: nil,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// AminoJSONUnpacker is an alias for github.com/cosmos/gogoproto/types/any.AminoJSONUnpacker.
|
||||
type AminoJSONUnpacker = gogoany.AminoJSONUnpacker
|
||||
|
||||
func (any *Any) MarshalJSON() ([]byte, error) {
|
||||
ac := any.compat
|
||||
if ac == nil {
|
||||
return nil, anyCompatError("JSON marshal", any)
|
||||
}
|
||||
return ac.jsonBz, ac.err
|
||||
}
|
||||
// AminoJSONPacker is an alias for github.com/cosmos/gogoproto/types/any.AminoJSONPacker.
|
||||
type AminoJSONPacker = gogoany.AminoJSONPacker
|
||||
|
||||
func (any *Any) UnmarshalJSON(bz []byte) error {
|
||||
any.compat = &anyCompat{
|
||||
jsonBz: bz,
|
||||
err: nil,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AminoUnpacker is an AnyUnpacker provided for backwards compatibility with
|
||||
// amino for the binary un-marshaling phase
|
||||
type AminoUnpacker struct {
|
||||
Cdc *amino.Codec
|
||||
}
|
||||
|
||||
var _ AnyUnpacker = AminoUnpacker{}
|
||||
|
||||
func (a AminoUnpacker) UnpackAny(any *Any, iface interface{}) error {
|
||||
ac := any.compat
|
||||
if ac == nil {
|
||||
return anyCompatError("amino binary unmarshal", reflect.TypeOf(iface))
|
||||
}
|
||||
err := a.Cdc.UnmarshalBinaryBare(ac.aminoBz, iface)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
val := reflect.ValueOf(iface).Elem().Interface()
|
||||
err = UnpackInterfaces(val, a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if m, ok := val.(proto.Message); ok {
|
||||
if err = any.pack(m); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
any.cachedValue = val
|
||||
}
|
||||
|
||||
// this is necessary for tests that use reflect.DeepEqual and compare
|
||||
// proto vs amino marshaled values
|
||||
any.compat = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AminoUnpacker is an AnyUnpacker provided for backwards compatibility with
|
||||
// amino for the binary marshaling phase
|
||||
type AminoPacker struct {
|
||||
Cdc *amino.Codec
|
||||
}
|
||||
|
||||
var _ AnyUnpacker = AminoPacker{}
|
||||
|
||||
func (a AminoPacker) UnpackAny(any *Any, _ interface{}) error {
|
||||
err := UnpackInterfaces(any.cachedValue, a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bz, err := a.Cdc.MarshalBinaryBare(any.cachedValue)
|
||||
any.compat = &anyCompat{
|
||||
aminoBz: bz,
|
||||
err: err,
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// AminoUnpacker is an AnyUnpacker provided for backwards compatibility with
|
||||
// amino for the JSON marshaling phase
|
||||
type AminoJSONUnpacker struct {
|
||||
Cdc *amino.Codec
|
||||
}
|
||||
|
||||
var _ AnyUnpacker = AminoJSONUnpacker{}
|
||||
|
||||
func (a AminoJSONUnpacker) UnpackAny(any *Any, iface interface{}) error {
|
||||
ac := any.compat
|
||||
if ac == nil {
|
||||
return anyCompatError("JSON unmarshal", reflect.TypeOf(iface))
|
||||
}
|
||||
err := a.Cdc.UnmarshalJSON(ac.jsonBz, iface)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
val := reflect.ValueOf(iface).Elem().Interface()
|
||||
err = UnpackInterfaces(val, a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if m, ok := val.(proto.Message); ok {
|
||||
if err = any.pack(m); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
any.cachedValue = val
|
||||
}
|
||||
|
||||
// this is necessary for tests that use reflect.DeepEqual and compare
|
||||
// proto vs amino marshaled values
|
||||
any.compat = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AminoUnpacker is an AnyUnpacker provided for backwards compatibility with
|
||||
// amino for the JSON un-marshaling phase
|
||||
type AminoJSONPacker struct {
|
||||
Cdc *amino.Codec
|
||||
}
|
||||
|
||||
var _ AnyUnpacker = AminoJSONPacker{}
|
||||
|
||||
func (a AminoJSONPacker) UnpackAny(any *Any, _ interface{}) error {
|
||||
err := UnpackInterfaces(any.cachedValue, a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bz, err := a.Cdc.MarshalJSON(any.cachedValue)
|
||||
any.compat = &anyCompat{
|
||||
jsonBz: bz,
|
||||
err: err,
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// ProtoJSONPacker is an AnyUnpacker provided for compatibility with jsonpb
|
||||
type ProtoJSONPacker struct {
|
||||
JSONPBMarshaler *jsonpb.Marshaler
|
||||
}
|
||||
|
||||
var _ AnyUnpacker = ProtoJSONPacker{}
|
||||
|
||||
func (a ProtoJSONPacker) UnpackAny(any *Any, _ interface{}) error {
|
||||
if any == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if any.cachedValue != nil {
|
||||
err := UnpackInterfaces(any.cachedValue, a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
bz, err := a.JSONPBMarshaler.MarshalToString(any)
|
||||
any.compat = &anyCompat{
|
||||
jsonBz: []byte(bz),
|
||||
err: err,
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
// ProtoUnpacker is an alias for github.com/cosmos/gogoproto/types/any.ProtoJSONPacker.
|
||||
type ProtoJSONPacker = gogoany.ProtoJSONPacker
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
package types_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
)
|
||||
|
||||
type TypeWithInterface struct {
|
||||
Animal testdata.Animal `json:"animal"`
|
||||
X int64 `json:"x,omitempty"`
|
||||
}
|
||||
|
||||
type Suite struct {
|
||||
suite.Suite
|
||||
cdc *amino.Codec
|
||||
a TypeWithInterface
|
||||
b testdata.HasAnimal
|
||||
spot *testdata.Dog
|
||||
}
|
||||
|
||||
func (s *Suite) SetupTest() {
|
||||
s.cdc = amino.NewCodec()
|
||||
s.cdc.RegisterInterface((*testdata.Animal)(nil), nil)
|
||||
s.cdc.RegisterConcrete(&testdata.Dog{}, "testdata/Dog", nil)
|
||||
|
||||
s.spot = &testdata.Dog{Size_: "small", Name: "Spot"}
|
||||
s.a = TypeWithInterface{Animal: s.spot}
|
||||
|
||||
any, err := types.NewAnyWithValue(s.spot)
|
||||
s.Require().NoError(err)
|
||||
s.b = testdata.HasAnimal{Animal: any}
|
||||
}
|
||||
|
||||
func (s *Suite) TestAminoBinary() {
|
||||
bz, err := s.cdc.MarshalBinaryBare(s.a)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// expect plain amino marshal to fail
|
||||
_, err = s.cdc.MarshalBinaryBare(s.b)
|
||||
s.Require().Error(err)
|
||||
|
||||
// expect unpack interfaces before amino marshal to succeed
|
||||
err = types.UnpackInterfaces(s.b, types.AminoPacker{Cdc: s.cdc})
|
||||
s.Require().NoError(err)
|
||||
bz2, err := s.cdc.MarshalBinaryBare(s.b)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(bz, bz2)
|
||||
|
||||
var c testdata.HasAnimal
|
||||
err = s.cdc.UnmarshalBinaryBare(bz, &c)
|
||||
s.Require().NoError(err)
|
||||
err = types.UnpackInterfaces(c, types.AminoUnpacker{Cdc: s.cdc})
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(s.spot, c.Animal.GetCachedValue())
|
||||
}
|
||||
|
||||
func (s *Suite) TestAminoJSON() {
|
||||
bz, err := s.cdc.MarshalJSON(s.a)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// expect plain amino marshal to fail
|
||||
_, err = s.cdc.MarshalJSON(s.b)
|
||||
s.Require().Error(err)
|
||||
|
||||
// expect unpack interfaces before amino marshal to succeed
|
||||
err = types.UnpackInterfaces(s.b, types.AminoJSONPacker{Cdc: s.cdc})
|
||||
s.Require().NoError(err)
|
||||
bz2, err := s.cdc.MarshalJSON(s.b)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(string(bz), string(bz2))
|
||||
|
||||
var c testdata.HasAnimal
|
||||
err = s.cdc.UnmarshalJSON(bz, &c)
|
||||
s.Require().NoError(err)
|
||||
err = types.UnpackInterfaces(c, types.AminoJSONUnpacker{Cdc: s.cdc})
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(s.spot, c.Animal.GetCachedValue())
|
||||
}
|
||||
|
||||
func (s *Suite) TestNested() {
|
||||
s.cdc.RegisterInterface((*testdata.HasAnimalI)(nil), nil)
|
||||
s.cdc.RegisterInterface((*testdata.HasHasAnimalI)(nil), nil)
|
||||
s.cdc.RegisterConcrete(&testdata.HasAnimal{}, "testdata/HasAnimal", nil)
|
||||
s.cdc.RegisterConcrete(&testdata.HasHasAnimal{}, "testdata/HasHasAnimal", nil)
|
||||
s.cdc.RegisterConcrete(&testdata.HasHasHasAnimal{}, "testdata/HasHasHasAnimal", nil)
|
||||
|
||||
any, err := types.NewAnyWithValue(&s.b)
|
||||
s.Require().NoError(err)
|
||||
hha := testdata.HasHasAnimal{HasAnimal: any}
|
||||
any2, err := types.NewAnyWithValue(&hha)
|
||||
s.Require().NoError(err)
|
||||
hhha := testdata.HasHasHasAnimal{HasHasAnimal: any2}
|
||||
|
||||
// marshal
|
||||
err = types.UnpackInterfaces(hhha, types.AminoPacker{Cdc: s.cdc})
|
||||
s.Require().NoError(err)
|
||||
bz, err := s.cdc.MarshalBinaryBare(hhha)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// unmarshal
|
||||
var hhha2 testdata.HasHasHasAnimal
|
||||
err = s.cdc.UnmarshalBinaryBare(bz, &hhha2)
|
||||
s.Require().NoError(err)
|
||||
err = types.UnpackInterfaces(hhha2, types.AminoUnpacker{Cdc: s.cdc})
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Equal(s.spot, hhha2.TheHasHasAnimal().TheHasAnimal().TheAnimal())
|
||||
|
||||
// json marshal
|
||||
err = types.UnpackInterfaces(hhha, types.AminoJSONPacker{Cdc: s.cdc})
|
||||
s.Require().NoError(err)
|
||||
jsonBz, err := s.cdc.MarshalJSON(hhha)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// json unmarshal
|
||||
var hhha3 testdata.HasHasHasAnimal
|
||||
err = s.cdc.UnmarshalJSON(jsonBz, &hhha3)
|
||||
s.Require().NoError(err)
|
||||
err = types.UnpackInterfaces(hhha3, types.AminoJSONUnpacker{Cdc: s.cdc})
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Equal(s.spot, hhha3.TheHasHasAnimal().TheHasAnimal().TheAnimal())
|
||||
}
|
||||
|
||||
func TestSuite(t *testing.T) {
|
||||
suite.Run(t, &Suite{})
|
||||
}
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Package types defines a custom wrapper for google.protobuf.Any which supports
|
||||
cached values as well as InterfaceRegistry which keeps track of types which can
|
||||
be used with Any for both security and introspection
|
||||
Package types defines the InterfaceRegistry type as well as
|
||||
aliases for types that now live in the github.com/cosmos/gogoproto/types/any package
|
||||
for backwards compatibility with legacy code.
|
||||
*/
|
||||
package types
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/cosmos/gogoproto/jsonpb"
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
gogoprotoany "github.com/cosmos/gogoproto/types/any"
|
||||
"google.golang.org/protobuf/reflect/protodesc"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
|
||||
@@ -24,23 +25,24 @@ var (
|
||||
MaxUnpackAnyRecursionDepth = 10
|
||||
)
|
||||
|
||||
// AnyUnpacker is an interface which allows safely unpacking types packed
|
||||
// in Any's against a whitelist of registered types
|
||||
type AnyUnpacker interface {
|
||||
// UnpackAny unpacks the value in any to the interface pointer passed in as
|
||||
// iface. Note that the type in any must have been registered in the
|
||||
// underlying whitelist registry as a concrete type for that interface
|
||||
// Ex:
|
||||
// var msg sdk.Msg
|
||||
// err := cdc.UnpackAny(any, &msg)
|
||||
// ...
|
||||
UnpackAny(any *Any, iface interface{}) error
|
||||
// AnyUnpacker is an alias for github.com/cosmos/gogoproto/types/any.AnyUnpacker.
|
||||
type AnyUnpacker = gogoprotoany.AnyUnpacker
|
||||
|
||||
// UnpackInterfaces is a convenience function that calls UnpackInterfaces
|
||||
// on x if x implements UnpackInterfacesMessage
|
||||
func UnpackInterfaces(x interface{}, unpacker gogoprotoany.AnyUnpacker) error {
|
||||
if msg, ok := x.(gogoprotoany.UnpackInterfacesMessage); ok {
|
||||
return msg.UnpackInterfaces(unpacker)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var protoMessageType = reflect.TypeOf((*proto.Message)(nil)).Elem()
|
||||
|
||||
// InterfaceRegistry provides a mechanism for registering interfaces and
|
||||
// implementations that can be safely unpacked from Any
|
||||
type InterfaceRegistry interface {
|
||||
AnyUnpacker
|
||||
gogoprotoany.AnyUnpacker
|
||||
jsonpb.AnyResolver
|
||||
|
||||
// RegisterInterface associates protoName as the public name for the
|
||||
@@ -107,7 +109,7 @@ type UnpackInterfacesMessage interface {
|
||||
// }
|
||||
// return nil
|
||||
// }
|
||||
UnpackInterfaces(unpacker AnyUnpacker) error
|
||||
UnpackInterfaces(unpacker gogoprotoany.AnyUnpacker) error
|
||||
}
|
||||
|
||||
type interfaceRegistry struct {
|
||||
@@ -315,10 +317,10 @@ func (r statefulUnpacker) cloneForRecursion() *statefulUnpacker {
|
||||
// UnpackAny deserializes a protobuf Any message into the provided interface, ensuring the interface is a pointer.
|
||||
// It applies stateful constraints such as max depth and call limits, and unpacks interfaces if required.
|
||||
func (r *statefulUnpacker) UnpackAny(any *Any, iface interface{}) error {
|
||||
if r.maxDepth == 0 {
|
||||
if r.maxDepth <= 0 {
|
||||
return errors.New("max depth exceeded")
|
||||
}
|
||||
if r.maxCalls.count == 0 {
|
||||
if r.maxCalls.count <= 0 {
|
||||
return errors.New("call limit exceeded")
|
||||
}
|
||||
// here we gracefully handle the case in which `any` itself is `nil`, which may occur in message decoding
|
||||
@@ -335,12 +337,12 @@ func (r *statefulUnpacker) UnpackAny(any *Any, iface interface{}) error {
|
||||
|
||||
rv := reflect.ValueOf(iface)
|
||||
if rv.Kind() != reflect.Ptr {
|
||||
return fmt.Errorf("UnpackAny expects a pointer")
|
||||
return errors.New("UnpackAny expects a pointer")
|
||||
}
|
||||
|
||||
rt := rv.Elem().Type()
|
||||
|
||||
cachedValue := any.cachedValue
|
||||
cachedValue := any.GetCachedValue()
|
||||
if cachedValue != nil {
|
||||
if reflect.TypeOf(cachedValue).AssignableTo(rt) {
|
||||
rv.Elem().Set(reflect.ValueOf(cachedValue))
|
||||
@@ -358,11 +360,13 @@ func (r *statefulUnpacker) UnpackAny(any *Any, iface interface{}) error {
|
||||
return fmt.Errorf("no concrete type registered for type URL %s against interface %T", any.TypeUrl, iface)
|
||||
}
|
||||
|
||||
msg, ok := reflect.New(typ.Elem()).Interface().(proto.Message)
|
||||
if !ok {
|
||||
return fmt.Errorf("can't proto unmarshal %T", msg)
|
||||
// Firstly check if the type implements proto.Message to avoid
|
||||
// unnecessary invocations to reflect.New
|
||||
if !typ.Implements(protoMessageType) {
|
||||
return fmt.Errorf("can't proto unmarshal %T", typ)
|
||||
}
|
||||
|
||||
msg := reflect.New(typ.Elem()).Interface().(proto.Message)
|
||||
err := proto.Unmarshal(any.Value, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -375,8 +379,12 @@ func (r *statefulUnpacker) UnpackAny(any *Any, iface interface{}) error {
|
||||
|
||||
rv.Elem().Set(reflect.ValueOf(msg))
|
||||
|
||||
any.cachedValue = msg
|
||||
newAnyWithCache, err := NewAnyWithValue(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*any = *newAnyWithCache
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -403,15 +411,6 @@ func (registry *interfaceRegistry) SigningContext() *signing.Context {
|
||||
|
||||
func (registry *interfaceRegistry) mustEmbedInterfaceRegistry() {}
|
||||
|
||||
// UnpackInterfaces is a convenience function that calls UnpackInterfaces
|
||||
// on x if x implements UnpackInterfacesMessage
|
||||
func UnpackInterfaces(x interface{}, unpacker AnyUnpacker) error {
|
||||
if msg, ok := x.(UnpackInterfacesMessage); ok {
|
||||
return msg.UnpackInterfaces(unpacker)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type failingAddressCodec struct{}
|
||||
|
||||
func (f failingAddressCodec) StringToBytes(string) ([]byte, error) {
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
package types_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/cosmos/gogoproto/jsonpb"
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
)
|
||||
|
||||
func TestAnyPackUnpack(t *testing.T) {
|
||||
registry := testdata.NewTestInterfaceRegistry()
|
||||
|
||||
spot := &testdata.Dog{Name: "Spot"}
|
||||
var animal testdata.Animal
|
||||
|
||||
// with cache
|
||||
any, err := types.NewAnyWithValue(spot)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, spot, any.GetCachedValue())
|
||||
err = registry.UnpackAny(any, &animal)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, spot, animal)
|
||||
}
|
||||
|
||||
type TestI interface {
|
||||
DoSomething()
|
||||
}
|
||||
|
||||
// A struct that has the same typeURL as testdata.Dog, but is actually another
|
||||
// concrete type.
|
||||
type FakeDog struct{}
|
||||
|
||||
var (
|
||||
_ proto.Message = &FakeDog{}
|
||||
_ testdata.Animal = &FakeDog{}
|
||||
)
|
||||
|
||||
// dummy implementation of proto.Message and testdata.Animal
|
||||
func (dog FakeDog) Reset() {}
|
||||
func (dog FakeDog) String() string { return "fakedog" }
|
||||
func (dog FakeDog) ProtoMessage() {}
|
||||
func (dog FakeDog) XXX_MessageName() string { return proto.MessageName(&testdata.Dog{}) }
|
||||
func (dog FakeDog) Greet() string { return "fakedog" }
|
||||
|
||||
func TestRegister(t *testing.T) {
|
||||
registry := types.NewInterfaceRegistry()
|
||||
registry.RegisterInterface("Animal", (*testdata.Animal)(nil))
|
||||
registry.RegisterInterface("TestI", (*TestI)(nil))
|
||||
|
||||
// Happy path.
|
||||
require.NotPanics(t, func() {
|
||||
registry.RegisterImplementations((*testdata.Animal)(nil), &testdata.Dog{})
|
||||
})
|
||||
|
||||
// testdata.Dog doesn't implement TestI
|
||||
require.Panics(t, func() {
|
||||
registry.RegisterImplementations((*TestI)(nil), &testdata.Dog{})
|
||||
})
|
||||
|
||||
// nil proto message
|
||||
require.Panics(t, func() {
|
||||
registry.RegisterImplementations((*TestI)(nil), nil)
|
||||
})
|
||||
|
||||
// Not an interface.
|
||||
require.Panics(t, func() {
|
||||
registry.RegisterInterface("not_an_interface", (*testdata.Dog)(nil))
|
||||
})
|
||||
|
||||
// Duplicate registration with same concrete type.
|
||||
require.NotPanics(t, func() {
|
||||
registry.RegisterImplementations((*testdata.Animal)(nil), &testdata.Dog{})
|
||||
})
|
||||
|
||||
// Duplicate registration with different concrete type on same typeURL.
|
||||
require.PanicsWithError(
|
||||
t,
|
||||
"concrete type *testdata.Dog has already been registered under typeURL /testpb.Dog, cannot register *types_test.FakeDog under same typeURL. "+
|
||||
"This usually means that there are conflicting modules registering different concrete types for a same interface implementation",
|
||||
func() {
|
||||
registry.RegisterImplementations((*testdata.Animal)(nil), &FakeDog{})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestUnpackInterfaces(t *testing.T) {
|
||||
registry := testdata.NewTestInterfaceRegistry()
|
||||
|
||||
spot := &testdata.Dog{Name: "Spot"}
|
||||
any, err := types.NewAnyWithValue(spot)
|
||||
require.NoError(t, err)
|
||||
|
||||
hasAny := testdata.HasAnimal{
|
||||
Animal: any,
|
||||
X: 1,
|
||||
}
|
||||
bz, err := hasAny.Marshal()
|
||||
require.NoError(t, err)
|
||||
|
||||
var hasAny2 testdata.HasAnimal
|
||||
err = hasAny2.Unmarshal(bz)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = types.UnpackInterfaces(hasAny2, registry)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, spot, hasAny2.Animal.GetCachedValue())
|
||||
}
|
||||
|
||||
func TestNested(t *testing.T) {
|
||||
registry := testdata.NewTestInterfaceRegistry()
|
||||
|
||||
spot := &testdata.Dog{Name: "Spot"}
|
||||
any, err := types.NewAnyWithValue(spot)
|
||||
require.NoError(t, err)
|
||||
|
||||
ha := &testdata.HasAnimal{Animal: any}
|
||||
any2, err := types.NewAnyWithValue(ha)
|
||||
require.NoError(t, err)
|
||||
|
||||
hha := &testdata.HasHasAnimal{HasAnimal: any2}
|
||||
any3, err := types.NewAnyWithValue(hha)
|
||||
require.NoError(t, err)
|
||||
|
||||
hhha := testdata.HasHasHasAnimal{HasHasAnimal: any3}
|
||||
|
||||
// marshal
|
||||
bz, err := hhha.Marshal()
|
||||
require.NoError(t, err)
|
||||
|
||||
// unmarshal
|
||||
var hhha2 testdata.HasHasHasAnimal
|
||||
err = hhha2.Unmarshal(bz)
|
||||
require.NoError(t, err)
|
||||
err = types.UnpackInterfaces(hhha2, registry)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, spot, hhha2.TheHasHasAnimal().TheHasAnimal().TheAnimal())
|
||||
}
|
||||
|
||||
func TestAny_ProtoJSON(t *testing.T) {
|
||||
spot := &testdata.Dog{Name: "Spot"}
|
||||
any, err := types.NewAnyWithValue(spot)
|
||||
require.NoError(t, err)
|
||||
|
||||
jm := &jsonpb.Marshaler{}
|
||||
json, err := jm.MarshalToString(any)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "{\"@type\":\"/testpb.Dog\",\"name\":\"Spot\"}", json)
|
||||
|
||||
registry := testdata.NewTestInterfaceRegistry()
|
||||
jum := &jsonpb.Unmarshaler{}
|
||||
var any2 types.Any
|
||||
err = jum.Unmarshal(strings.NewReader(json), &any2)
|
||||
require.NoError(t, err)
|
||||
var animal testdata.Animal
|
||||
err = registry.UnpackAny(&any2, &animal)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, spot, animal)
|
||||
|
||||
ha := &testdata.HasAnimal{
|
||||
Animal: any,
|
||||
}
|
||||
err = ha.UnpackInterfaces(types.ProtoJSONPacker{JSONPBMarshaler: jm})
|
||||
require.NoError(t, err)
|
||||
json, err = jm.MarshalToString(ha)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "{\"animal\":{\"@type\":\"/testpb.Dog\",\"name\":\"Spot\"}}", json)
|
||||
|
||||
require.NoError(t, err)
|
||||
var ha2 testdata.HasAnimal
|
||||
err = jum.Unmarshal(strings.NewReader(json), &ha2)
|
||||
require.NoError(t, err)
|
||||
err = ha2.UnpackInterfaces(registry)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, spot, ha2.Animal.GetCachedValue())
|
||||
}
|
||||
Reference in New Issue
Block a user