/
convert.go
237 lines (208 loc) · 7.41 KB
/
convert.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
package v046
import (
"fmt"
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"
)
// 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{
ProposalId: proposal.Id,
Status: v1beta1.ProposalStatus(proposal.Status),
TotalDeposit: types.NewCoins(proposal.TotalDeposit...),
}
legacyProposal.FinalTallyResult, err = ConvertToLegacyTallyResult(proposal.FinalTallyResult)
if err != nil {
return v1beta1.Proposal{}, err
}
if proposal.VotingStartTime != nil {
legacyProposal.VotingStartTime = *proposal.VotingStartTime
}
if proposal.VotingEndTime != nil {
legacyProposal.VotingEndTime = *proposal.VotingEndTime
}
if proposal.SubmitTime != nil {
legacyProposal.SubmitTime = *proposal.SubmitTime
}
if proposal.DepositEndTime != nil {
legacyProposal.DepositEndTime = *proposal.DepositEndTime
}
msgs, err := proposal.GetMsgs()
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")
}
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
// 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) {
yes, ok := types.NewIntFromString(tally.YesCount)
if !ok {
return v1beta1.TallyResult{}, fmt.Errorf("unable to convert yes tally string (%s) to int", tally.YesCount)
}
no, ok := types.NewIntFromString(tally.NoCount)
if !ok {
return v1beta1.TallyResult{}, fmt.Errorf("unable to convert no tally string (%s) to int", tally.NoCount)
}
veto, ok := types.NewIntFromString(tally.NoWithVetoCount)
if !ok {
return v1beta1.TallyResult{}, fmt.Errorf("unable to convert no with veto tally string (%s) to int", tally.NoWithVetoCount)
}
abstain, ok := types.NewIntFromString(tally.AbstainCount)
if !ok {
return v1beta1.TallyResult{}, fmt.Errorf("unable to convert abstain tally string (%s) to int", tally.AbstainCount)
}
return v1beta1.TallyResult{
Yes: yes,
No: no,
NoWithVeto: veto,
Abstain: abstain,
}, nil
}
func ConvertToLegacyVote(vote v1.Vote) (v1beta1.Vote, error) {
options, err := ConvertToLegacyVoteOptions(vote.Options)
if err != nil {
return v1beta1.Vote{}, err
}
return v1beta1.Vote{
ProposalId: vote.ProposalId,
Voter: vote.Voter,
Options: options,
}, nil
}
func ConvertToLegacyVoteOptions(voteOptions []*v1.WeightedVoteOption) ([]v1beta1.WeightedVoteOption, error) {
options := make([]v1beta1.WeightedVoteOption, len(voteOptions))
for i, option := range voteOptions {
weight, err := types.NewDecFromStr(option.Weight)
if err != nil {
return options, err
}
options[i] = v1beta1.WeightedVoteOption{
Option: v1beta1.VoteOption(option.Option),
Weight: weight,
}
}
return options, nil
}
func ConvertToLegacyDeposit(deposit *v1.Deposit) v1beta1.Deposit {
return v1beta1.Deposit{
ProposalId: deposit.ProposalId,
Depositor: deposit.Depositor,
Amount: types.NewCoins(deposit.Amount...),
}
}
func convertToNewDeposits(oldDeps v1beta1.Deposits) v1.Deposits {
newDeps := make([]*v1.Deposit, len(oldDeps))
for i, oldDep := range oldDeps {
newDeps[i] = &v1.Deposit{
ProposalId: oldDep.ProposalId,
Depositor: oldDep.Depositor,
Amount: oldDep.Amount,
}
}
return newDeps
}
func convertToNewVotes(oldVotes v1beta1.Votes) (v1.Votes, error) {
newVotes := make([]*v1.Vote, len(oldVotes))
for i, oldVote := range oldVotes {
var newWVOs []*v1.WeightedVoteOption
// We deprecated Vote.Option in v043. However, it might still be set.
// - if only Options is set, or both Option & Options are set, we read from Options,
// - if Options is not set, and Option is set, we read from Option,
// - if none are set, we throw error.
if oldVote.Options != nil { //nolint:gocritic // should be rewritten to a switch statement
newWVOs = make([]*v1.WeightedVoteOption, len(oldVote.Options))
for j, oldWVO := range oldVote.Options {
newWVOs[j] = v1.NewWeightedVoteOption(v1.VoteOption(oldWVO.Option), oldWVO.Weight)
}
} else if oldVote.Option != v1beta1.OptionEmpty {
newWVOs = v1.NewNonSplitVoteOption(v1.VoteOption(oldVote.Option))
} else {
return nil, fmt.Errorf("vote does not have neither Options nor Option")
}
newVotes[i] = &v1.Vote{
ProposalId: oldVote.ProposalId,
Voter: oldVote.Voter,
Options: newWVOs,
}
}
return newVotes, nil
}
func convertToNewDepParams(oldDepParams v1beta1.DepositParams) v1.DepositParams {
return v1.DepositParams{
MinDeposit: oldDepParams.MinDeposit,
MaxDepositPeriod: &oldDepParams.MaxDepositPeriod,
}
}
func convertToNewVotingParams(oldVoteParams v1beta1.VotingParams) v1.VotingParams {
return v1.VotingParams{
VotingPeriod: &oldVoteParams.VotingPeriod,
}
}
func convertToNewTallyParams(oldTallyParams v1beta1.TallyParams) v1.TallyParams {
return v1.TallyParams{
Quorum: oldTallyParams.Quorum.String(),
Threshold: oldTallyParams.Threshold.String(),
VetoThreshold: oldTallyParams.VetoThreshold.String(),
}
}
func convertToNewProposal(oldProp v1beta1.Proposal) (v1.Proposal, error) {
msg, err := v1.NewLegacyContent(oldProp.GetContent(), authtypes.NewModuleAddress(ModuleName).String())
if err != nil {
return v1.Proposal{}, err
}
msgAny, err := codectypes.NewAnyWithValue(msg)
if err != nil {
return v1.Proposal{}, err
}
return v1.Proposal{
Id: oldProp.ProposalId,
Messages: []*codectypes.Any{msgAny},
Status: v1.ProposalStatus(oldProp.Status),
FinalTallyResult: &v1.TallyResult{
YesCount: oldProp.FinalTallyResult.Yes.String(),
NoCount: oldProp.FinalTallyResult.No.String(),
AbstainCount: oldProp.FinalTallyResult.Abstain.String(),
NoWithVetoCount: oldProp.FinalTallyResult.NoWithVeto.String(),
},
SubmitTime: &oldProp.SubmitTime,
DepositEndTime: &oldProp.DepositEndTime,
TotalDeposit: oldProp.TotalDeposit,
VotingStartTime: &oldProp.VotingStartTime,
VotingEndTime: &oldProp.VotingEndTime,
}, nil
}
func convertToNewProposals(oldProps v1beta1.Proposals) (v1.Proposals, error) {
newProps := make([]*v1.Proposal, len(oldProps))
for i, oldProp := range oldProps {
p, err := convertToNewProposal(oldProp)
if err != nil {
return nil, err
}
newProps[i] = &p
}
return newProps, nil
}