Skip to content

Commit

Permalink
Merge pull request #468 from CosmWasm/any-msg
Browse files Browse the repository at this point in the history
Handle both `stargate` and `any` CosmosMsg variant
  • Loading branch information
chipshort authored Nov 16, 2023
2 parents 035407a + 97bb4d8 commit 5af85d0
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 3 deletions.
45 changes: 42 additions & 3 deletions types/msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,49 @@ type CosmosMsg struct {
Gov *GovMsg `json:"gov,omitempty"`
IBC *IBCMsg `json:"ibc,omitempty"`
Staking *StakingMsg `json:"staking,omitempty"`
Stargate *StargateMsg `json:"stargate,omitempty"`
Any *AnyMsg `json:"any,omitempty"`
Wasm *WasmMsg `json:"wasm,omitempty"`
}

func (m *CosmosMsg) UnmarshalJSON(data []byte) error {
// We need a custom unmarshaler to parse both the "stargate" and "any" variants
type InternalCosmosMsg struct {
Bank *BankMsg `json:"bank,omitempty"`
Custom json.RawMessage `json:"custom,omitempty"`
Distribution *DistributionMsg `json:"distribution,omitempty"`
Gov *GovMsg `json:"gov,omitempty"`
IBC *IBCMsg `json:"ibc,omitempty"`
Staking *StakingMsg `json:"staking,omitempty"`
Any *AnyMsg `json:"any,omitempty"`
Wasm *WasmMsg `json:"wasm,omitempty"`
Stargate *AnyMsg `json:"stargate,omitempty"`
}
var tmp InternalCosmosMsg
err := json.Unmarshal(data, &tmp)
if err != nil {
return err
}

if tmp.Any != nil && tmp.Stargate != nil {
return fmt.Errorf("invalid CosmosMsg: both 'any' and 'stargate' fields are set")
} else if tmp.Any == nil && tmp.Stargate != nil {
// Use "Any" for both variants
tmp.Any = tmp.Stargate
}

*m = CosmosMsg{
Bank: tmp.Bank,
Custom: tmp.Custom,
Distribution: tmp.Distribution,
Gov: tmp.Gov,
IBC: tmp.IBC,
Staking: tmp.Staking,
Any: tmp.Any,
Wasm: tmp.Wasm,
}
return nil
}

type BankMsg struct {
Send *SendMsg `json:"send,omitempty"`
Burn *BurnMsg `json:"burn,omitempty"`
Expand Down Expand Up @@ -272,9 +311,9 @@ type FundCommunityPoolMsg struct {
Amount Coins `json:"amount"`
}

// StargateMsg is encoded the same way as a protobof [Any](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto).
// AnyMsg is encoded the same way as a protobof [Any](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto).
// This is the same structure as messages in `TxBody` from [ADR-020](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-020-protobuf-transaction-encoding.md)
type StargateMsg struct {
type AnyMsg struct {
TypeURL string `json:"type_url"`
Value []byte `json:"value"`
}
Expand Down
39 changes: 39 additions & 0 deletions types/msg_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package types

import (
"encoding/base64"
"encoding/json"
"testing"

Expand Down Expand Up @@ -76,6 +77,44 @@ func TestWasmMsgInstantiate2Serialization(t *testing.T) {
require.Equal(t, []byte{0x52, 0x43, 0x95, 0x6b, 0x38, 0x62, 0xc2, 0x8a}, msg.Instantiate2.Salt)
}

func TestAnyMsgSerialization(t *testing.T) {
expectedData, err := base64.StdEncoding.DecodeString("5yu/rQ+HrMcxH1zdga7P5hpGMLE=")
require.NoError(t, err)

// test backwards compatibility with old stargate variant
document1 := []byte(`{"stargate":{"type_url":"/cosmos.foo.v1beta.MsgBar","value":"5yu/rQ+HrMcxH1zdga7P5hpGMLE="}}`)
var res CosmosMsg
err = json.Unmarshal(document1, &res)
require.NoError(t, err)
require.Equal(t, CosmosMsg{
Any: &AnyMsg{
TypeURL: "/cosmos.foo.v1beta.MsgBar",
Value: expectedData,
},
}, res)

// test new any variant
document2 := []byte(`{"any":{"type_url":"/cosmos.foo.v1beta.MsgBar","value":"5yu/rQ+HrMcxH1zdga7P5hpGMLE="}}`)
var res2 CosmosMsg
err = json.Unmarshal(document2, &res2)
require.NoError(t, err)
require.Equal(t, res, res2)

// serializing should use the new any variant
serialized, err := json.Marshal(res)
require.NoError(t, err)
require.Equal(t, document2, serialized)

// test providing both variants is rejected
document3 := []byte(`{
"stargate":{"type_url":"/cosmos.foo.v1beta.MsgBar","value":"5yu/rQ+HrMcxH1zdga7P5hpGMLE="},
"any":{"type_url":"/cosmos.foo.v1beta.MsgBar","value":"5yu/rQ+HrMcxH1zdga7P5hpGMLE="}
}`)
var res3 CosmosMsg
err = json.Unmarshal(document3, &res3)
require.Error(t, err)
}

func TestGovMsgVoteSerialization(t *testing.T) {
document := []byte(`{"vote":{"proposal_id":4,"vote":"no_with_veto"}}`)

Expand Down

0 comments on commit 5af85d0

Please sign in to comment.