-
Notifications
You must be signed in to change notification settings - Fork 555
/
codec.go
123 lines (103 loc) · 4.75 KB
/
codec.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package types
import (
errorsmod "cosmossdk.io/errors"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/gogoproto/proto"
)
// ModuleCdc references the global interchain accounts module codec. Note, the codec
// should ONLY be used in certain instances of tests and for JSON encoding.
//
// The actual codec used for serialization should be provided to interchain accounts and
// defined at the application level.
var ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry())
// RegisterInterfaces registers the interchain accounts controller types and the concrete InterchainAccount implementation
// against the associated x/auth AccountI and GenesisAccount interfaces.
func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
registry.RegisterImplementations((*authtypes.AccountI)(nil), &InterchainAccount{})
registry.RegisterImplementations((*authtypes.GenesisAccount)(nil), &InterchainAccount{})
}
// SerializeCosmosTx serializes a slice of sdk.Msg's using the CosmosTx type. The sdk.Msg's are
// packed into Any's and inserted into the Messages field of a CosmosTx. The proto marshaled CosmosTx
// bytes are returned. Only the ProtoCodec is supported for serializing messages.
func SerializeCosmosTx(cdc codec.BinaryCodec, msgs []proto.Message) ([]byte, error) {
return SerializeCosmosTxWithEncoding(cdc, msgs, EncodingProtobuf)
}
// DeserializeCosmosTx unmarshals and unpacks a slice of transaction bytes
// into a slice of sdk.Msg's. Only the ProtoCodec is supported for message
// deserialization.
func DeserializeCosmosTx(cdc codec.BinaryCodec, data []byte) ([]sdk.Msg, error) {
return DeserializeCosmosTxWithEncoding(cdc, data, EncodingProtobuf)
}
// SerializeCosmosTxWithEncoding serializes a slice of sdk.Msg's using the CosmosTx type. The sdk.Msg's are
// packed into Any's and inserted into the Messages field of a CosmosTx. The CosmosTx is marshaled
// depending on the encoding type passed in. The marshaled bytes are returned. Only the ProtoCodec
// is supported for serializing messages. Both protobuf and proto3 JSON are supported.
func SerializeCosmosTxWithEncoding(cdc codec.BinaryCodec, msgs []proto.Message, encoding string) ([]byte, error) {
// this is a defensive check to ensure only the ProtoCodec is used for message serialization
if _, ok := cdc.(*codec.ProtoCodec); !ok {
return nil, errorsmod.Wrap(ErrInvalidCodec, "only the ProtoCodec may be used for receiving messages on the host chain")
}
var bz []byte
var err error
msgAnys := make([]*codectypes.Any, len(msgs))
for i, msg := range msgs {
msgAnys[i], err = codectypes.NewAnyWithValue(msg)
if err != nil {
return nil, err
}
}
cosmosTx := &CosmosTx{
Messages: msgAnys,
}
switch encoding {
case EncodingProtobuf:
bz, err = cdc.Marshal(cosmosTx)
if err != nil {
return nil, errorsmod.Wrapf(err, "cannot marshal CosmosTx with protobuf")
}
case EncodingProto3JSON:
bz, err = cdc.(*codec.ProtoCodec).MarshalJSON(cosmosTx)
if err != nil {
return nil, errorsmod.Wrapf(ErrUnknownDataType, "cannot marshal CosmosTx with proto3 json")
}
default:
return nil, errorsmod.Wrapf(ErrInvalidCodec, "unsupported encoding format %s", encoding)
}
return bz, nil
}
// DeserializeCosmosTxWithEncoding unmarshals and unpacks a slice of transaction bytes into a slice of sdk.Msg's.
// The transaction bytes are unmarshaled depending on the encoding type passed in. The sdk.Msg's are
// unpacked from Any's and returned. Only the ProtoCodec is supported for serializing messages. Both
// protobuf and proto3 JSON are supported.
func DeserializeCosmosTxWithEncoding(cdc codec.BinaryCodec, data []byte, encoding string) ([]sdk.Msg, error) {
// this is a defensive check to ensure only the ProtoCodec is used for message deserialization
if _, ok := cdc.(*codec.ProtoCodec); !ok {
return nil, errorsmod.Wrap(ErrInvalidCodec, "only the ProtoCodec may be used for receiving messages on the host chain")
}
var cosmosTx CosmosTx
switch encoding {
case EncodingProtobuf:
if err := cdc.Unmarshal(data, &cosmosTx); err != nil {
return nil, errorsmod.Wrapf(err, "cannot unmarshal CosmosTx with protobuf")
}
case EncodingProto3JSON:
if err := cdc.(*codec.ProtoCodec).UnmarshalJSON(data, &cosmosTx); err != nil {
return nil, errorsmod.Wrapf(ErrUnknownDataType, "cannot unmarshal CosmosTx with proto3 json")
}
default:
return nil, errorsmod.Wrapf(ErrInvalidCodec, "unsupported encoding format %s", encoding)
}
msgs := make([]sdk.Msg, len(cosmosTx.Messages))
for i, protoAny := range cosmosTx.Messages {
var msg sdk.Msg
err := cdc.UnpackAny(protoAny, &msg)
if err != nil {
return nil, err
}
msgs[i] = msg
}
return msgs, nil
}