From 19f72e3e4e63348dd4e458af8f7bd55fb5b9f680 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Fri, 16 Dec 2022 18:49:25 +0100 Subject: [PATCH 1/2] feat(gov): support v1.Proposal in v1beta1.Proposal.Content --- CHANGELOG.md | 4 +++ x/gov/migrations/v046/convert.go | 14 ++++++++++- x/gov/migrations/v046/convert_test.go | 36 +++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25800d8001b0..58cf9658293a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [Unreleased] +### Improvements + +* (x/gov) [#14347](https://github.com/cosmos/cosmos-sdk/pull/14347) Support `v1.Proposal` message in `v1beta1.Proposal.Content`. + ## [v0.46.7](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.46.7) - 2022-12-13 ### Features diff --git a/x/gov/migrations/v046/convert.go b/x/gov/migrations/v046/convert.go index 267418064e34..300910b820fd 100644 --- a/x/gov/migrations/v046/convert.go +++ b/x/gov/migrations/v046/convert.go @@ -5,6 +5,7 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" @@ -13,6 +14,7 @@ import ( // ConvertToLegacyProposal takes a new proposal and attempts to convert it to the // legacy proposal format. This conversion is best effort. New proposal types that // don't have a legacy message will return a "nil" content. +// Returns error when the amount of messages in `proposal` is different than one. func ConvertToLegacyProposal(proposal v1.Proposal) (v1beta1.Proposal, error) { var err error legacyProposal := v1beta1.Proposal{ @@ -46,6 +48,9 @@ func ConvertToLegacyProposal(proposal v1.Proposal) (v1beta1.Proposal, error) { if err != nil { return v1beta1.Proposal{}, err } + if len(msgs) != 1 { + return v1beta1.Proposal{}, sdkerrors.ErrInvalidType.Wrap("can't convert a gov/v1 Proposal to gov/v1beta1 Proposal when amount of proposal messages is more than one") + } for _, msg := range msgs { if legacyMsg, ok := msg.(*v1.MsgExecLegacyContent); ok { // check that the content struct can be unmarshalled @@ -54,9 +59,16 @@ func ConvertToLegacyProposal(proposal v1.Proposal) (v1beta1.Proposal, error) { return v1beta1.Proposal{}, err } legacyProposal.Content = legacyMsg.Content + return legacyProposal, nil } } - return legacyProposal, nil + // hack to fill up the content with the first message + // this is to support clients that have not yet (properly) use gov/v1 endpoints + // https://github.com/cosmos/cosmos-sdk/issues/14334 + // VerifyBasic assures that we have at least one message. + legacyProposal.Content, err = codectypes.NewAnyWithValue(msgs[0]) + + return legacyProposal, err } func ConvertToLegacyTallyResult(tally *v1.TallyResult) (v1beta1.TallyResult, error) { diff --git a/x/gov/migrations/v046/convert_test.go b/x/gov/migrations/v046/convert_test.go index 64375e796aef..aa4250df14e3 100644 --- a/x/gov/migrations/v046/convert_test.go +++ b/x/gov/migrations/v046/convert_test.go @@ -5,10 +5,12 @@ import ( "time" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/tx" v046 "github.com/cosmos/cosmos-sdk/x/gov/migrations/v046" v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" "github.com/stretchr/testify/require" ) @@ -60,11 +62,45 @@ func TestConvertToLegacyProposal(t *testing.T) { require.Equal(t, v1beta1Proposal.FinalTallyResult.No, sdk.NewInt(0)) require.Equal(t, v1beta1Proposal.FinalTallyResult.NoWithVeto, sdk.NewInt(0)) require.Equal(t, v1beta1Proposal.FinalTallyResult.Abstain, sdk.NewInt(0)) + tp, ok := v1beta1Proposal.Content.GetCachedValue().(*v1beta1.TextProposal) + require.Truef(t, ok, "expected *TextProposal, got %T", v1beta1Proposal.Content.GetCachedValue()) + require.Equal(t, tp.Title, "title") + require.Equal(t, tp.Description, "description") } }) } } +func TestConvertToLegacyProposalContent(t *testing.T) { + msg := upgradetypes.MsgSoftwareUpgrade{Authority: "gov module", Plan: upgradetypes.Plan{Name: "test upgrade"}} + msgsAny, err := tx.SetMsgs([]sdk.Msg{&msg}) + require.NoError(t, err) + tallyResult := v1.EmptyTallyResult() + proposal := v1.Proposal{ + Id: 1, + Status: v1.StatusDepositPeriod, + Messages: msgsAny, + Metadata: "proposal metadata", + FinalTallyResult: &tallyResult, + } + + legacyP, err := v046.ConvertToLegacyProposal(proposal) + require.NoError(t, err) + tp, ok := legacyP.Content.GetCachedValue().(*upgradetypes.MsgSoftwareUpgrade) + require.Truef(t, ok, "expected *MsgSoftwareUpgrade, got %T", legacyP.Content.GetCachedValue()) + require.Equal(t, &msg, tp) + + // more than one message is not supported + proposal.Messages, err = tx.SetMsgs([]sdk.Msg{&msg, &msg}) + require.NoError(t, err) + _, err = v046.ConvertToLegacyProposal(proposal) + require.ErrorIs(t, sdkerrors.ErrInvalidType, err) + + // zero messages is not supported + proposal.Messages = nil + _, err = v046.ConvertToLegacyProposal(proposal) + require.ErrorIs(t, sdkerrors.ErrInvalidType, err) +} func TestConvertToLegacyTallyResult(t *testing.T) { tallyResult := v1.EmptyTallyResult() testCases := map[string]struct { From 7a5b0e5644067f5fef4854aa56aec3b1d0fdcf33 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Fri, 23 Dec 2022 00:35:23 +0100 Subject: [PATCH 2/2] remove for loop --- x/gov/migrations/v046/convert.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/x/gov/migrations/v046/convert.go b/x/gov/migrations/v046/convert.go index 300910b820fd..e368a0b2b2b6 100644 --- a/x/gov/migrations/v046/convert.go +++ b/x/gov/migrations/v046/convert.go @@ -51,16 +51,14 @@ func ConvertToLegacyProposal(proposal v1.Proposal) (v1beta1.Proposal, error) { if len(msgs) != 1 { return v1beta1.Proposal{}, sdkerrors.ErrInvalidType.Wrap("can't convert a gov/v1 Proposal to gov/v1beta1 Proposal when amount of proposal messages is more than one") } - for _, msg := range msgs { - if legacyMsg, ok := msg.(*v1.MsgExecLegacyContent); ok { - // check that the content struct can be unmarshalled - _, err := v1.LegacyContentFromMessage(legacyMsg) - if err != nil { - return v1beta1.Proposal{}, err - } - legacyProposal.Content = legacyMsg.Content - return legacyProposal, nil + if legacyMsg, ok := msgs[0].(*v1.MsgExecLegacyContent); ok { + // check that the content struct can be unmarshalled + _, err := v1.LegacyContentFromMessage(legacyMsg) + if err != nil { + return v1beta1.Proposal{}, err } + legacyProposal.Content = legacyMsg.Content + return legacyProposal, nil } // hack to fill up the content with the first message // this is to support clients that have not yet (properly) use gov/v1 endpoints