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  }