diff --git a/docs/apps/interchain-accounts/client.md b/docs/apps/interchain-accounts/client.md index 868aeaeb4e4..83e10a73bf7 100644 --- a/docs/apps/interchain-accounts/client.md +++ b/docs/apps/interchain-accounts/client.md @@ -84,7 +84,7 @@ simd tx interchain-accounts host --help ##### `generate-packet-data` -The `generate-packet-data` command allows users to generate protobuf encoded interchain accounts packet data for input message(s). The packet data can then be used with the controller submodule's [`send-tx` command](#send-tx). +The `generate-packet-data` command allows users to generate protobuf or proto3 JSON encoded interchain accounts packet data for input message(s). The packet data can then be used with the controller submodule's [`send-tx` command](#send-tx). The `--encoding` flag can be uesd to specify the encoding format (value must be either `proto3` or `proto3json`); if not specified, the default will be `proto3`. The `--memo` flag can be used to include a memo string in the interchain accounts packet data. ```shell simd tx interchain-accounts host generate-packet-data [message] diff --git a/modules/apps/27-interchain-accounts/host/client/cli/tx.go b/modules/apps/27-interchain-accounts/host/client/cli/tx.go index d3902d35f9a..da9c24c7537 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/tx.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/tx.go @@ -12,21 +12,24 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/version" + "github.com/cosmos/ibc-go/v7/internal/collections" icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types" ) const ( - memoFlag string = "memo" + memoFlag string = "memo" + encodingFlag string = "encoding" ) func generatePacketDataCmd() *cobra.Command { cmd := &cobra.Command{ Use: "generate-packet-data [message]", - Short: "Generates protobuf encoded ICA packet data.", - Long: `generate-packet-data accepts a message string and serializes it using protobuf -into packet data which is outputted to stdout. It can be used in conjunction with send-tx" -which submits pre-built packet data containing messages to be executed on the host chain. -`, + Short: "Generates protobuf or proto3 JSON encoded ICA packet data.", + Long: `generate-packet-data accepts a message string and serializes it (depending on the +encoding parameter) using protobuf or proto3 JSON into packet data which is outputted to stdout. +It can be used in conjunction with send-tx which submits pre-built packet data containing messages +to be executed on the host chain. The default encoding format is protobuf if none is specified; +otherwise the encoding flag can be used in combination with either "proto3" or "proto3json".`, Example: fmt.Sprintf(`%s tx interchain-accounts host generate-packet-data '{ "@type":"/cosmos.bank.v1beta1.MsgSend", "from_address":"cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", @@ -37,7 +40,7 @@ which submits pre-built packet data containing messages to be executed on the ho "amount": "1000" } ] -}' --memo memo +}' --memo memo --encoding proto3json %s tx interchain-accounts host generate-packet-data '[{ @@ -74,7 +77,16 @@ which submits pre-built packet data containing messages to be executed on the ho return err } - packetDataBytes, err := generatePacketData(cdc, []byte(args[0]), memo) + encoding, err := cmd.Flags().GetString(encodingFlag) + if err != nil { + return err + } + + if !collections.Contains(encoding, []string{icatypes.EncodingProtobuf, icatypes.EncodingProto3JSON}) { + return fmt.Errorf("unsupported encoding type: %s", encoding) + } + + packetDataBytes, err := generatePacketData(cdc, []byte(args[0]), memo, encoding) if err != nil { return err } @@ -85,19 +97,20 @@ which submits pre-built packet data containing messages to be executed on the ho }, } - cmd.Flags().String(memoFlag, "", "an optional memo to be included in the interchain account packet data") + cmd.Flags().String(memoFlag, "", "optional memo to be included in the interchain accounts packet data") + cmd.Flags().String(encodingFlag, "", "optional encoding format of the messages in the interchain accounts packet data") return cmd } // generatePacketData takes in message bytes and a memo and serializes the message into an // instance of InterchainAccountPacketData which is returned as bytes. -func generatePacketData(cdc *codec.ProtoCodec, msgBytes []byte, memo string) ([]byte, error) { +func generatePacketData(cdc *codec.ProtoCodec, msgBytes []byte, memo string, encoding string) ([]byte, error) { protoMessages, err := convertBytesIntoProtoMessages(cdc, msgBytes) if err != nil { return nil, err } - return generateIcaPacketDataFromProtoMessages(cdc, protoMessages, memo) + return generateIcaPacketDataFromProtoMessages(cdc, protoMessages, memo, encoding) } // convertBytesIntoProtoMessages returns a list of proto messages from bytes. The bytes can be in the form of a single @@ -129,8 +142,8 @@ func convertBytesIntoProtoMessages(cdc *codec.ProtoCodec, msgBytes []byte) ([]pr } // generateIcaPacketDataFromProtoMessages generates ica packet data as bytes from a given set of proto encoded sdk messages and a memo. -func generateIcaPacketDataFromProtoMessages(cdc *codec.ProtoCodec, sdkMessages []proto.Message, memo string) ([]byte, error) { - icaPacketDataBytes, err := icatypes.SerializeCosmosTx(cdc, sdkMessages, icatypes.EncodingProtobuf) +func generateIcaPacketDataFromProtoMessages(cdc *codec.ProtoCodec, sdkMessages []proto.Message, memo string, encoding string) ([]byte, error) { + icaPacketDataBytes, err := icatypes.SerializeCosmosTx(cdc, sdkMessages, encoding) if err != nil { return nil, err } diff --git a/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go b/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go index f9c4c0a4d71..9d31ceb3884 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go @@ -101,44 +101,46 @@ func TestGeneratePacketData(t *testing.T) { }, } - for _, tc := range tests { - tc := tc - ir := codectypes.NewInterfaceRegistry() - if tc.registerInterfaceFn != nil { - tc.registerInterfaceFn(ir) - } + encodings := []string{icatypes.EncodingProtobuf, icatypes.EncodingProto3JSON} + for _, encoding := range encodings { + for _, tc := range tests { + tc := tc + ir := codectypes.NewInterfaceRegistry() + if tc.registerInterfaceFn != nil { + tc.registerInterfaceFn(ir) + } - cdc := codec.NewProtoCodec(ir) + cdc := codec.NewProtoCodec(ir) - t.Run(tc.name, func(t *testing.T) { - bz, err := generatePacketData(cdc, []byte(tc.message), tc.memo) + t.Run(fmt.Sprintf("%s with %s encoding", tc.name, encoding), func(t *testing.T) { + bz, err := generatePacketData(cdc, []byte(tc.message), tc.memo, encoding) - if tc.expectedPass { - require.NoError(t, err) - require.NotNil(t, bz) + if tc.expectedPass { + require.NoError(t, err) + require.NotNil(t, bz) - packetData := icatypes.InterchainAccountPacketData{} - err = cdc.UnmarshalJSON(bz, &packetData) - require.NoError(t, err) + packetData := icatypes.InterchainAccountPacketData{} + err = cdc.UnmarshalJSON(bz, &packetData) + require.NoError(t, err) - require.Equal(t, icatypes.EXECUTE_TX, packetData.Type) - require.Equal(t, tc.memo, packetData.Memo) + require.Equal(t, icatypes.EXECUTE_TX, packetData.Type) + require.Equal(t, tc.memo, packetData.Memo) - data := packetData.Data - // cli tx commands always use protobuf encoding - messages, err := icatypes.DeserializeCosmosTx(cdc, data, icatypes.EncodingProtobuf) + data := packetData.Data + messages, err := icatypes.DeserializeCosmosTx(cdc, data, encoding) - require.NoError(t, err) - require.NotNil(t, messages) + require.NoError(t, err) + require.NotNil(t, messages) - if tc.assertionFn != nil { - tc.assertionFn(t, messages) + if tc.assertionFn != nil { + tc.assertionFn(t, messages) + } + } else { + require.Error(t, err) + require.Nil(t, bz) } - } else { - require.Error(t, err) - require.Nil(t, bz) - } - }) + }) + } } }