github.com/cosmos/cosmos-sdk@v0.50.10/x/gov/migrations/v3/convert.go (about) 1 package v3 2 3 import ( 4 "fmt" 5 6 "cosmossdk.io/math" 7 8 codectypes "github.com/cosmos/cosmos-sdk/codec/types" 9 "github.com/cosmos/cosmos-sdk/types" 10 sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" 11 authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" 12 v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" 13 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" 14 ) 15 16 // ConvertToLegacyProposal takes a new proposal and attempts to convert it to the 17 // legacy proposal format. This conversion is best effort. New proposal types that 18 // don't have a legacy message will return a "nil" content. 19 // Returns error when the amount of messages in `proposal` is different than one. 20 func ConvertToLegacyProposal(proposal v1.Proposal) (v1beta1.Proposal, error) { 21 var err error 22 legacyProposal := v1beta1.Proposal{ 23 ProposalId: proposal.Id, 24 Status: v1beta1.ProposalStatus(proposal.Status), 25 TotalDeposit: types.NewCoins(proposal.TotalDeposit...), 26 } 27 28 legacyProposal.FinalTallyResult, err = ConvertToLegacyTallyResult(proposal.FinalTallyResult) 29 if err != nil { 30 return v1beta1.Proposal{}, err 31 } 32 33 if proposal.VotingStartTime != nil { 34 legacyProposal.VotingStartTime = *proposal.VotingStartTime 35 } 36 37 if proposal.VotingEndTime != nil { 38 legacyProposal.VotingEndTime = *proposal.VotingEndTime 39 } 40 41 if proposal.SubmitTime != nil { 42 legacyProposal.SubmitTime = *proposal.SubmitTime 43 } 44 45 if proposal.DepositEndTime != nil { 46 legacyProposal.DepositEndTime = *proposal.DepositEndTime 47 } 48 49 msgs, err := proposal.GetMsgs() 50 if err != nil { 51 return v1beta1.Proposal{}, err 52 } 53 if len(msgs) != 1 { 54 return v1beta1.Proposal{}, sdkerrors.ErrInvalidType.Wrap("can't convert a gov/v1 Proposal to gov/v1beta1 Proposal when amount of proposal messages not exactly one") 55 } 56 if legacyMsg, ok := msgs[0].(*v1.MsgExecLegacyContent); ok { 57 // check that the content struct can be unmarshalled 58 _, err := v1.LegacyContentFromMessage(legacyMsg) 59 if err != nil { 60 return v1beta1.Proposal{}, err 61 } 62 legacyProposal.Content = legacyMsg.Content 63 return legacyProposal, nil 64 } 65 // hack to fill up the content with the first message 66 // this is to support clients that have not yet (properly) use gov/v1 endpoints 67 // https://github.com/cosmos/cosmos-sdk/issues/14334 68 // VerifyBasic assures that we have at least one message. 69 legacyProposal.Content, err = codectypes.NewAnyWithValue(msgs[0]) 70 71 return legacyProposal, err 72 } 73 74 func ConvertToLegacyTallyResult(tally *v1.TallyResult) (v1beta1.TallyResult, error) { 75 yes, ok := math.NewIntFromString(tally.YesCount) 76 if !ok { 77 return v1beta1.TallyResult{}, fmt.Errorf("unable to convert yes tally string (%s) to int", tally.YesCount) 78 } 79 no, ok := math.NewIntFromString(tally.NoCount) 80 if !ok { 81 return v1beta1.TallyResult{}, fmt.Errorf("unable to convert no tally string (%s) to int", tally.NoCount) 82 } 83 veto, ok := math.NewIntFromString(tally.NoWithVetoCount) 84 if !ok { 85 return v1beta1.TallyResult{}, fmt.Errorf("unable to convert no with veto tally string (%s) to int", tally.NoWithVetoCount) 86 } 87 abstain, ok := math.NewIntFromString(tally.AbstainCount) 88 if !ok { 89 return v1beta1.TallyResult{}, fmt.Errorf("unable to convert abstain tally string (%s) to int", tally.AbstainCount) 90 } 91 92 return v1beta1.TallyResult{ 93 Yes: yes, 94 No: no, 95 NoWithVeto: veto, 96 Abstain: abstain, 97 }, nil 98 } 99 100 func ConvertToLegacyVote(vote v1.Vote) (v1beta1.Vote, error) { 101 options, err := ConvertToLegacyVoteOptions(vote.Options) 102 if err != nil { 103 return v1beta1.Vote{}, err 104 } 105 return v1beta1.Vote{ 106 ProposalId: vote.ProposalId, 107 Voter: vote.Voter, 108 Options: options, 109 }, nil 110 } 111 112 func ConvertToLegacyVoteOptions(voteOptions []*v1.WeightedVoteOption) ([]v1beta1.WeightedVoteOption, error) { 113 options := make([]v1beta1.WeightedVoteOption, len(voteOptions)) 114 for i, option := range voteOptions { 115 weight, err := math.LegacyNewDecFromStr(option.Weight) 116 if err != nil { 117 return options, err 118 } 119 options[i] = v1beta1.WeightedVoteOption{ 120 Option: v1beta1.VoteOption(option.Option), 121 Weight: weight, 122 } 123 } 124 return options, nil 125 } 126 127 func ConvertToLegacyDeposit(deposit *v1.Deposit) v1beta1.Deposit { 128 return v1beta1.Deposit{ 129 ProposalId: deposit.ProposalId, 130 Depositor: deposit.Depositor, 131 Amount: types.NewCoins(deposit.Amount...), 132 } 133 } 134 135 func convertToNewDeposits(oldDeps v1beta1.Deposits) v1.Deposits { 136 newDeps := make([]*v1.Deposit, len(oldDeps)) 137 for i, oldDep := range oldDeps { 138 newDeps[i] = &v1.Deposit{ 139 ProposalId: oldDep.ProposalId, 140 Depositor: oldDep.Depositor, 141 Amount: oldDep.Amount, 142 } 143 } 144 145 return newDeps 146 } 147 148 func convertToNewVotes(oldVotes v1beta1.Votes) (v1.Votes, error) { 149 newVotes := make([]*v1.Vote, len(oldVotes)) 150 for i, oldVote := range oldVotes { 151 var newWVOs []*v1.WeightedVoteOption 152 153 // We deprecated Vote.Option in v043. However, it might still be set. 154 // - if only Options is set, or both Option & Options are set, we read from Options, 155 // - if Options is not set, and Option is set, we read from Option, 156 // - if none are set, we throw error. 157 switch { 158 case oldVote.Options != nil: 159 newWVOs = make([]*v1.WeightedVoteOption, len(oldVote.Options)) 160 for j, oldWVO := range oldVote.Options { 161 newWVOs[j] = v1.NewWeightedVoteOption(v1.VoteOption(oldWVO.Option), oldWVO.Weight) 162 } 163 164 case oldVote.Option != v1beta1.OptionEmpty: 165 newWVOs = v1.NewNonSplitVoteOption(v1.VoteOption(oldVote.Option)) 166 167 default: 168 return nil, fmt.Errorf("vote does not have neither InterfaceRegistryOptions nor Option") 169 } 170 171 newVotes[i] = &v1.Vote{ 172 ProposalId: oldVote.ProposalId, 173 Voter: oldVote.Voter, 174 Options: newWVOs, 175 } 176 } 177 178 return newVotes, nil 179 } 180 181 func convertToNewDepParams(oldDepParams v1beta1.DepositParams) v1.DepositParams { 182 return v1.DepositParams{ 183 MinDeposit: oldDepParams.MinDeposit, 184 MaxDepositPeriod: &oldDepParams.MaxDepositPeriod, 185 } 186 } 187 188 func convertToNewVotingParams(oldVoteParams v1beta1.VotingParams) v1.VotingParams { 189 return v1.VotingParams{ 190 VotingPeriod: &oldVoteParams.VotingPeriod, 191 } 192 } 193 194 func convertToNewTallyParams(oldTallyParams v1beta1.TallyParams) v1.TallyParams { 195 return v1.TallyParams{ 196 Quorum: oldTallyParams.Quorum.String(), 197 Threshold: oldTallyParams.Threshold.String(), 198 VetoThreshold: oldTallyParams.VetoThreshold.String(), 199 } 200 } 201 202 func convertToNewProposal(oldProp v1beta1.Proposal) (v1.Proposal, error) { 203 msg, err := v1.NewLegacyContent(oldProp.GetContent(), authtypes.NewModuleAddress(ModuleName).String()) 204 if err != nil { 205 return v1.Proposal{}, err 206 } 207 msgAny, err := codectypes.NewAnyWithValue(msg) 208 if err != nil { 209 return v1.Proposal{}, err 210 } 211 212 return v1.Proposal{ 213 Id: oldProp.ProposalId, 214 Messages: []*codectypes.Any{msgAny}, 215 Status: v1.ProposalStatus(oldProp.Status), 216 FinalTallyResult: &v1.TallyResult{ 217 YesCount: oldProp.FinalTallyResult.Yes.String(), 218 NoCount: oldProp.FinalTallyResult.No.String(), 219 AbstainCount: oldProp.FinalTallyResult.Abstain.String(), 220 NoWithVetoCount: oldProp.FinalTallyResult.NoWithVeto.String(), 221 }, 222 SubmitTime: &oldProp.SubmitTime, 223 DepositEndTime: &oldProp.DepositEndTime, 224 TotalDeposit: oldProp.TotalDeposit, 225 VotingStartTime: &oldProp.VotingStartTime, 226 VotingEndTime: &oldProp.VotingEndTime, 227 Title: oldProp.GetContent().GetTitle(), 228 Summary: oldProp.GetContent().GetDescription(), 229 }, nil 230 } 231 232 func convertToNewProposals(oldProps v1beta1.Proposals) (v1.Proposals, error) { 233 newProps := make([]*v1.Proposal, len(oldProps)) 234 for i, oldProp := range oldProps { 235 p, err := convertToNewProposal(oldProp) 236 if err != nil { 237 return nil, err 238 } 239 240 newProps[i] = &p 241 } 242 243 return newProps, nil 244 }