github.com/Finschia/finschia-sdk@v0.48.1/x/foundation/genesis.go (about)

     1  package foundation
     2  
     3  import (
     4  	"github.com/gogo/protobuf/proto"
     5  
     6  	codectypes "github.com/Finschia/finschia-sdk/codec/types"
     7  	sdk "github.com/Finschia/finschia-sdk/types"
     8  	sdkerrors "github.com/Finschia/finschia-sdk/types/errors"
     9  	authtypes "github.com/Finschia/finschia-sdk/x/auth/types"
    10  )
    11  
    12  // DefaultGenesisState creates a default GenesisState object
    13  func DefaultGenesisState() *GenesisState {
    14  	return &GenesisState{
    15  		Params:     DefaultParams(),
    16  		Foundation: DefaultFoundation(),
    17  	}
    18  }
    19  
    20  func DefaultFoundation() FoundationInfo {
    21  	return *FoundationInfo{
    22  		Version:     1,
    23  		TotalWeight: sdk.ZeroDec(),
    24  	}.WithDecisionPolicy(DefaultDecisionPolicy())
    25  }
    26  
    27  func DefaultDecisionPolicy() DecisionPolicy {
    28  	return &OutsourcingDecisionPolicy{
    29  		Description: "using x/group",
    30  	}
    31  }
    32  
    33  func DefaultAuthority() sdk.AccAddress {
    34  	return authtypes.NewModuleAddress(ModuleName)
    35  }
    36  
    37  func DefaultParams() Params {
    38  	return Params{
    39  		FoundationTax: sdk.ZeroDec(),
    40  	}
    41  }
    42  
    43  func (data GenesisState) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
    44  	if err := data.Foundation.UnpackInterfaces(unpacker); err != nil {
    45  		return err
    46  	}
    47  
    48  	for _, p := range data.Proposals {
    49  		if err := p.UnpackInterfaces(unpacker); err != nil {
    50  			return err
    51  		}
    52  	}
    53  
    54  	for _, ga := range data.Authorizations {
    55  		if err := ga.UnpackInterfaces(unpacker); err != nil {
    56  			return err
    57  		}
    58  	}
    59  
    60  	return nil
    61  }
    62  
    63  func (i FoundationInfo) ValidateBasic() error {
    64  	if i.Version == 0 {
    65  		return sdkerrors.ErrInvalidVersion.Wrap("version must be > 0")
    66  	}
    67  
    68  	if i.TotalWeight.IsNil() || i.TotalWeight.IsNegative() {
    69  		return sdkerrors.ErrInvalidRequest.Wrap("total weight must be >= 0")
    70  	}
    71  
    72  	policy := i.GetDecisionPolicy()
    73  	if policy == nil {
    74  		return sdkerrors.ErrInvalidRequest.Wrap("must provide decision policy")
    75  	}
    76  	if err := policy.ValidateBasic(); err != nil {
    77  		return err
    78  	}
    79  
    80  	// Is foundation outsourcing the proposal feature
    81  	_, isOutsourcing := i.GetDecisionPolicy().(*OutsourcingDecisionPolicy)
    82  	memberNotExists := i.TotalWeight.IsZero()
    83  	if isOutsourcing && !memberNotExists {
    84  		return sdkerrors.ErrInvalidRequest.Wrap("outsourcing policy not allows members")
    85  	}
    86  	if !isOutsourcing && memberNotExists {
    87  		return sdkerrors.ErrInvalidRequest.Wrap("one member must exist at least")
    88  	}
    89  
    90  	return nil
    91  }
    92  
    93  // ValidateGenesis validates the provided genesis state to ensure the
    94  // expected invariants holds.
    95  func ValidateGenesis(data GenesisState) error {
    96  	if err := data.Params.ValidateBasic(); err != nil {
    97  		return err
    98  	}
    99  
   100  	info := data.Foundation
   101  	if err := info.ValidateBasic(); err != nil {
   102  		return err
   103  	}
   104  	// Is x/foundation outsourcing the proposal feature
   105  	isOutsourcing := info.TotalWeight.IsZero()
   106  
   107  	if realWeight := sdk.NewDec(int64(len(data.Members))); !info.TotalWeight.Equal(realWeight) {
   108  		return sdkerrors.ErrInvalidRequest.Wrapf("total weight not match, %s != %s", info.TotalWeight, realWeight)
   109  	}
   110  	members := Members{Members: data.Members}
   111  	if err := members.ValidateBasic(); err != nil {
   112  		return err
   113  	}
   114  
   115  	if isOutsourcing && len(data.Proposals) != 0 {
   116  		return sdkerrors.ErrInvalidRequest.Wrap("outsourcing policy not allows proposals")
   117  	}
   118  	proposalIDs := map[uint64]bool{}
   119  	for _, proposal := range data.Proposals {
   120  		id := proposal.Id
   121  		if id > data.PreviousProposalId {
   122  			return sdkerrors.ErrInvalidRequest.Wrapf("proposal %d has not yet been submitted", id)
   123  		}
   124  		if proposalIDs[id] {
   125  			return sdkerrors.ErrInvalidRequest.Wrapf("duplicated proposal id of %d", id)
   126  		}
   127  		proposalIDs[id] = true
   128  
   129  		if err := proposal.ValidateBasic(); err != nil {
   130  			return err
   131  		}
   132  
   133  		if proposal.FoundationVersion > info.Version {
   134  			return sdkerrors.ErrInvalidRequest.Wrapf("invalid foundation version of proposal %d", id)
   135  		}
   136  	}
   137  
   138  	for _, vote := range data.Votes {
   139  		if !proposalIDs[vote.ProposalId] {
   140  			return sdkerrors.ErrInvalidRequest.Wrapf("vote for a proposal which does not exist: id %d", vote.ProposalId)
   141  		}
   142  
   143  		if _, err := sdk.AccAddressFromBech32(vote.Voter); err != nil {
   144  			return sdkerrors.ErrInvalidAddress.Wrapf("invalid voter address: %s", vote.Voter)
   145  		}
   146  
   147  		if err := validateVoteOption(vote.Option); err != nil {
   148  			return err
   149  		}
   150  	}
   151  
   152  	seenURLs := map[string]bool{}
   153  	for _, censorship := range data.Censorships {
   154  		if err := censorship.ValidateBasic(); err != nil {
   155  			return err
   156  		}
   157  		if censorship.Authority == CensorshipAuthorityUnspecified {
   158  			return sdkerrors.ErrInvalidRequest.Wrap("authority unspecified")
   159  		}
   160  
   161  		url := censorship.MsgTypeUrl
   162  		if seenURLs[url] {
   163  			return sdkerrors.ErrInvalidRequest.Wrapf("duplicate censorship over %s", url)
   164  		}
   165  		seenURLs[url] = true
   166  	}
   167  
   168  	for _, ga := range data.Authorizations {
   169  		auth := ga.GetAuthorization()
   170  		if auth == nil {
   171  			return sdkerrors.ErrInvalidType.Wrap("invalid authorization")
   172  		}
   173  
   174  		url := auth.MsgTypeURL()
   175  		if !seenURLs[url] {
   176  			return sdkerrors.ErrInvalidRequest.Wrapf("no censorship over %s", url)
   177  		}
   178  
   179  		if _, err := sdk.AccAddressFromBech32(ga.Grantee); err != nil {
   180  			return err
   181  		}
   182  	}
   183  
   184  	if err := data.Pool.ValidateBasic(); err != nil {
   185  		return err
   186  	}
   187  
   188  	return nil
   189  }
   190  
   191  func (g GrantAuthorization) GetAuthorization() Authorization {
   192  	if g.Authorization == nil {
   193  		return nil
   194  	}
   195  
   196  	a, ok := g.Authorization.GetCachedValue().(Authorization)
   197  	if !ok {
   198  		return nil
   199  	}
   200  	return a
   201  }
   202  
   203  func (g *GrantAuthorization) SetAuthorization(a Authorization) error {
   204  	msg, ok := a.(proto.Message)
   205  	if !ok {
   206  		return sdkerrors.ErrInvalidType.Wrapf("can't proto marshal %T", msg)
   207  	}
   208  
   209  	any, err := codectypes.NewAnyWithValue(msg)
   210  	if err != nil {
   211  		return err
   212  	}
   213  	g.Authorization = any
   214  
   215  	return nil
   216  }
   217  
   218  // for the tests
   219  func (g GrantAuthorization) WithAuthorization(authorization Authorization) *GrantAuthorization {
   220  	grant := g
   221  	if err := grant.SetAuthorization(authorization); err != nil {
   222  		return nil
   223  	}
   224  	return &grant
   225  }
   226  
   227  func (g GrantAuthorization) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
   228  	var authorization Authorization
   229  	return unpacker.UnpackAny(g.Authorization, &authorization)
   230  }