@@ -3,10 +3,14 @@ package decode
33import (
44 "crypto/sha256"
55 "errors"
6+ "fmt"
7+ "reflect"
8+ "strings"
69
7- "github.com/cosmos/cosmos-proto/anyutil "
10+ gogoproto "github.com/cosmos/gogoproto/proto "
811 "google.golang.org/protobuf/proto"
9- "google.golang.org/protobuf/protoadapt"
12+ "google.golang.org/protobuf/reflect/protoreflect"
13+ "google.golang.org/protobuf/types/dynamicpb"
1014
1115 v1beta1 "cosmossdk.io/api/cosmos/tx/v1beta1"
1216 "cosmossdk.io/core/transaction"
@@ -16,7 +20,8 @@ import (
1620
1721// DecodedTx contains the decoded transaction, its signers, and other flags.
1822type DecodedTx struct {
19- Messages []proto.Message
23+ DynamicMessages []proto.Message
24+ Messages []gogoproto.Message
2025 Tx * v1beta1.Tx
2126 TxRaw * v1beta1.TxRaw
2227 Signers [][]byte
@@ -30,24 +35,33 @@ type DecodedTx struct {
3035
3136var _ transaction.Tx = & DecodedTx {}
3237
38+ type gogoProtoCodec interface {
39+ Unmarshal ([]byte , gogoproto.Message ) error
40+ }
41+
3342// Decoder contains the dependencies required for decoding transactions.
3443type Decoder struct {
3544 signingCtx * signing.Context
45+ codec gogoProtoCodec
3646}
3747
3848// Options are options for creating a Decoder.
3949type Options struct {
4050 SigningContext * signing.Context
51+ ProtoCodec gogoProtoCodec
4152}
4253
4354// NewDecoder creates a new Decoder for decoding transactions.
4455func NewDecoder (options Options ) (* Decoder , error ) {
4556 if options .SigningContext == nil {
4657 return nil , errors .New ("signing context is required" )
4758 }
48-
59+ if options .ProtoCodec == nil {
60+ return nil , errors .New ("proto codec is required for unmarshalling gogoproto messages" )
61+ }
4962 return & Decoder {
5063 signingCtx : options .SigningContext ,
64+ codec : options .ProtoCodec ,
5165 }, nil
5266}
5367
@@ -105,16 +119,41 @@ func (d *Decoder) Decode(txBytes []byte) (*DecodedTx, error) {
105119 Signatures : raw .Signatures ,
106120 }
107121
108- var signers [][]byte
109- var msgs []proto.Message
122+ var (
123+ signers [][]byte
124+ dynamicMsgs []proto.Message
125+ msgs []gogoproto.Message
126+ )
110127 seenSigners := map [string ]struct {}{}
111128 for _ , anyMsg := range body .Messages {
112- msg , signerErr := anyutil .Unpack (anyMsg , fileResolver , d .signingCtx .TypeResolver ())
113- if signerErr != nil {
114- return nil , errorsmod .Wrap (ErrTxDecode , signerErr .Error ())
129+ typeURL := strings .TrimPrefix (anyMsg .TypeUrl , "/" )
130+
131+ // unmarshal into dynamic message
132+ msgDesc , err := fileResolver .FindDescriptorByName (protoreflect .FullName (typeURL ))
133+ if err != nil {
134+ return nil , fmt .Errorf ("protoFiles does not have descriptor %s: %w" , anyMsg .TypeUrl , err )
135+ }
136+ dynamicMsg := dynamicpb .NewMessageType (msgDesc .(protoreflect.MessageDescriptor )).New ().Interface ()
137+ err = anyMsg .UnmarshalTo (dynamicMsg )
138+ if err != nil {
139+ return nil , err
140+ }
141+ dynamicMsgs = append (dynamicMsgs , dynamicMsg )
142+
143+ // unmarshal into gogoproto message
144+ gogoType := gogoproto .MessageType (typeURL )
145+ if gogoType == nil {
146+ return nil , fmt .Errorf ("cannot find type: %s" , anyMsg .TypeUrl )
147+ }
148+ msg := reflect .New (gogoType .Elem ()).Interface ().(gogoproto.Message )
149+ err = d .codec .Unmarshal (anyMsg .Value , msg )
150+ if err != nil {
151+ return nil , err
115152 }
116153 msgs = append (msgs , msg )
117- ss , signerErr := d .signingCtx .GetSigners (msg )
154+
155+ // fetch signers with dynamic message
156+ ss , signerErr := d .signingCtx .GetSigners (dynamicMsg )
118157 if signerErr != nil {
119158 return nil , errorsmod .Wrap (ErrTxDecode , signerErr .Error ())
120159 }
@@ -130,6 +169,7 @@ func (d *Decoder) Decode(txBytes []byte) (*DecodedTx, error) {
130169
131170 return & DecodedTx {
132171 Messages : msgs ,
172+ DynamicMessages : dynamicMsgs ,
133173 Tx : theTx ,
134174 TxRaw : & raw ,
135175 TxBodyHasUnknownNonCriticals : txBodyHasUnknownNonCriticals ,
@@ -157,12 +197,7 @@ func (dtx *DecodedTx) GetMessages() ([]transaction.Msg, error) {
157197 return nil , errors .New ("messages not available or are nil" )
158198 }
159199
160- msgs := make ([]transaction.Msg , len (dtx .Messages ))
161- for i , msg := range dtx .Messages {
162- msgs [i ] = protoadapt .MessageV1Of (msg )
163- }
164-
165- return msgs , nil
200+ return dtx .Messages , nil
166201}
167202
168203func (dtx * DecodedTx ) GetSenders () ([][]byte , error ) {
0 commit comments