github.com/cosmos/cosmos-sdk@v0.50.10/x/gov/types/v1/genesis.go (about)

     1  package v1
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"golang.org/x/sync/errgroup"
     8  
     9  	"github.com/cosmos/cosmos-sdk/codec/types"
    10  )
    11  
    12  // NewGenesisState creates a new genesis state for the governance module
    13  func NewGenesisState(startingProposalID uint64, params Params) *GenesisState {
    14  	return &GenesisState{
    15  		StartingProposalId: startingProposalID,
    16  		Params:             &params,
    17  	}
    18  }
    19  
    20  // DefaultGenesisState defines the default governance genesis state
    21  func DefaultGenesisState() *GenesisState {
    22  	return NewGenesisState(
    23  		DefaultStartingProposalID,
    24  		DefaultParams(),
    25  	)
    26  }
    27  
    28  // Empty returns true if a GenesisState is empty
    29  func (data GenesisState) Empty() bool {
    30  	return data.StartingProposalId == 0 || data.Params == nil
    31  }
    32  
    33  // ValidateGenesis checks if gov genesis state is valid ranges
    34  // It checks if params are in valid ranges
    35  // It also makes sure that the provided proposal IDs are unique and
    36  // that there are no duplicate deposit or vote records and no vote or deposits for non-existent proposals
    37  func ValidateGenesis(data *GenesisState) error {
    38  	if data.StartingProposalId == 0 {
    39  		return errors.New("starting proposal id must be greater than 0")
    40  	}
    41  
    42  	var errGroup errgroup.Group
    43  
    44  	// weed out duplicate proposals
    45  	proposalIds := make(map[uint64]struct{})
    46  	for _, p := range data.Proposals {
    47  		if _, ok := proposalIds[p.Id]; ok {
    48  			return fmt.Errorf("duplicate proposal id: %d", p.Id)
    49  		}
    50  
    51  		proposalIds[p.Id] = struct{}{}
    52  	}
    53  
    54  	// weed out duplicate deposits
    55  	errGroup.Go(func() error {
    56  		type depositKey struct {
    57  			ProposalId uint64 //nolint:revive // staying consistent with main and v0.47
    58  			Depositor  string
    59  		}
    60  		depositIds := make(map[depositKey]struct{})
    61  		for _, d := range data.Deposits {
    62  			if _, ok := proposalIds[d.ProposalId]; !ok {
    63  				return fmt.Errorf("deposit %v has non-existent proposal id: %d", d, d.ProposalId)
    64  			}
    65  
    66  			dk := depositKey{d.ProposalId, d.Depositor}
    67  			if _, ok := depositIds[dk]; ok {
    68  				return fmt.Errorf("duplicate deposit: %v", d)
    69  			}
    70  
    71  			depositIds[dk] = struct{}{}
    72  		}
    73  
    74  		return nil
    75  	})
    76  
    77  	// weed out duplicate votes
    78  	errGroup.Go(func() error {
    79  		type voteKey struct {
    80  			ProposalId uint64 //nolint:revive // staying consistent with main and v0.47
    81  			Voter      string
    82  		}
    83  		voteIds := make(map[voteKey]struct{})
    84  		for _, v := range data.Votes {
    85  			if _, ok := proposalIds[v.ProposalId]; !ok {
    86  				return fmt.Errorf("vote %v has non-existent proposal id: %d", v, v.ProposalId)
    87  			}
    88  
    89  			vk := voteKey{v.ProposalId, v.Voter}
    90  			if _, ok := voteIds[vk]; ok {
    91  				return fmt.Errorf("duplicate vote: %v", v)
    92  			}
    93  
    94  			voteIds[vk] = struct{}{}
    95  		}
    96  
    97  		return nil
    98  	})
    99  
   100  	// verify params
   101  	errGroup.Go(func() error {
   102  		return data.Params.ValidateBasic()
   103  	})
   104  
   105  	return errGroup.Wait()
   106  }
   107  
   108  var _ types.UnpackInterfacesMessage = GenesisState{}
   109  
   110  // UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
   111  func (data GenesisState) UnpackInterfaces(unpacker types.AnyUnpacker) error {
   112  	for _, p := range data.Proposals {
   113  		err := p.UnpackInterfaces(unpacker)
   114  		if err != nil {
   115  			return err
   116  		}
   117  	}
   118  	return nil
   119  }