github.com/cosmos/cosmos-sdk@v0.50.10/codec/types/compat.go (about) 1 package types 2 3 import ( 4 "fmt" 5 "reflect" 6 "runtime/debug" 7 8 "github.com/cosmos/gogoproto/jsonpb" 9 "github.com/cosmos/gogoproto/proto" 10 amino "github.com/tendermint/go-amino" 11 ) 12 13 type anyCompat struct { 14 aminoBz []byte 15 jsonBz []byte 16 err error 17 } 18 19 var Debug = true 20 21 func anyCompatError(errType string, x interface{}) error { 22 if Debug { 23 debug.PrintStack() 24 } 25 return fmt.Errorf( 26 "%s marshaling error for %+v, this is likely because "+ 27 "amino is being used directly (instead of codec.LegacyAmino which is preferred) "+ 28 "or UnpackInterfacesMessage is not defined for some type which contains "+ 29 "a protobuf Any either directly or via one of its members. To see a "+ 30 "stacktrace of where the error is coming from, set the var Debug = true "+ 31 "in codec/types/compat.go", 32 errType, x, 33 ) 34 } 35 36 func (any Any) MarshalAmino() ([]byte, error) { 37 ac := any.compat 38 if ac == nil { 39 return nil, anyCompatError("amino binary marshal", any) 40 } 41 return ac.aminoBz, ac.err 42 } 43 44 func (any *Any) UnmarshalAmino(bz []byte) error { 45 any.compat = &anyCompat{ 46 aminoBz: bz, 47 err: nil, 48 } 49 return nil 50 } 51 52 func (any *Any) MarshalJSON() ([]byte, error) { 53 ac := any.compat 54 if ac == nil { 55 return nil, anyCompatError("JSON marshal", any) 56 } 57 return ac.jsonBz, ac.err 58 } 59 60 func (any *Any) UnmarshalJSON(bz []byte) error { 61 any.compat = &anyCompat{ 62 jsonBz: bz, 63 err: nil, 64 } 65 return nil 66 } 67 68 // AminoUnpacker is an AnyUnpacker provided for backwards compatibility with 69 // amino for the binary un-marshaling phase 70 type AminoUnpacker struct { 71 Cdc *amino.Codec 72 } 73 74 var _ AnyUnpacker = AminoUnpacker{} 75 76 func (a AminoUnpacker) UnpackAny(any *Any, iface interface{}) error { 77 ac := any.compat 78 if ac == nil { 79 return anyCompatError("amino binary unmarshal", reflect.TypeOf(iface)) 80 } 81 err := a.Cdc.UnmarshalBinaryBare(ac.aminoBz, iface) 82 if err != nil { 83 return err 84 } 85 val := reflect.ValueOf(iface).Elem().Interface() 86 err = UnpackInterfaces(val, a) 87 if err != nil { 88 return err 89 } 90 if m, ok := val.(proto.Message); ok { 91 if err = any.pack(m); err != nil { 92 return err 93 } 94 } else { 95 any.cachedValue = val 96 } 97 98 // this is necessary for tests that use reflect.DeepEqual and compare 99 // proto vs amino marshaled values 100 any.compat = nil 101 102 return nil 103 } 104 105 // AminoUnpacker is an AnyUnpacker provided for backwards compatibility with 106 // amino for the binary marshaling phase 107 type AminoPacker struct { 108 Cdc *amino.Codec 109 } 110 111 var _ AnyUnpacker = AminoPacker{} 112 113 func (a AminoPacker) UnpackAny(any *Any, _ interface{}) error { 114 err := UnpackInterfaces(any.cachedValue, a) 115 if err != nil { 116 return err 117 } 118 bz, err := a.Cdc.MarshalBinaryBare(any.cachedValue) 119 any.compat = &anyCompat{ 120 aminoBz: bz, 121 err: err, 122 } 123 return err 124 } 125 126 // AminoUnpacker is an AnyUnpacker provided for backwards compatibility with 127 // amino for the JSON marshaling phase 128 type AminoJSONUnpacker struct { 129 Cdc *amino.Codec 130 } 131 132 var _ AnyUnpacker = AminoJSONUnpacker{} 133 134 func (a AminoJSONUnpacker) UnpackAny(any *Any, iface interface{}) error { 135 ac := any.compat 136 if ac == nil { 137 return anyCompatError("JSON unmarshal", reflect.TypeOf(iface)) 138 } 139 err := a.Cdc.UnmarshalJSON(ac.jsonBz, iface) 140 if err != nil { 141 return err 142 } 143 val := reflect.ValueOf(iface).Elem().Interface() 144 err = UnpackInterfaces(val, a) 145 if err != nil { 146 return err 147 } 148 if m, ok := val.(proto.Message); ok { 149 if err = any.pack(m); err != nil { 150 return err 151 } 152 } else { 153 any.cachedValue = val 154 } 155 156 // this is necessary for tests that use reflect.DeepEqual and compare 157 // proto vs amino marshaled values 158 any.compat = nil 159 160 return nil 161 } 162 163 // AminoUnpacker is an AnyUnpacker provided for backwards compatibility with 164 // amino for the JSON un-marshaling phase 165 type AminoJSONPacker struct { 166 Cdc *amino.Codec 167 } 168 169 var _ AnyUnpacker = AminoJSONPacker{} 170 171 func (a AminoJSONPacker) UnpackAny(any *Any, _ interface{}) error { 172 err := UnpackInterfaces(any.cachedValue, a) 173 if err != nil { 174 return err 175 } 176 bz, err := a.Cdc.MarshalJSON(any.cachedValue) 177 any.compat = &anyCompat{ 178 jsonBz: bz, 179 err: err, 180 } 181 return err 182 } 183 184 // ProtoJSONPacker is an AnyUnpacker provided for compatibility with jsonpb 185 type ProtoJSONPacker struct { 186 JSONPBMarshaler *jsonpb.Marshaler 187 } 188 189 var _ AnyUnpacker = ProtoJSONPacker{} 190 191 func (a ProtoJSONPacker) UnpackAny(any *Any, _ interface{}) error { 192 if any == nil { 193 return nil 194 } 195 196 if any.cachedValue != nil { 197 err := UnpackInterfaces(any.cachedValue, a) 198 if err != nil { 199 return err 200 } 201 } 202 203 bz, err := a.JSONPBMarshaler.MarshalToString(any) 204 any.compat = &anyCompat{ 205 jsonBz: []byte(bz), 206 err: err, 207 } 208 209 return err 210 }