github.com/cosmos/cosmos-sdk@v0.50.10/x/gov/keeper/keeper.go (about) 1 package keeper 2 3 import ( 4 "context" 5 "fmt" 6 "time" 7 8 "cosmossdk.io/collections" 9 corestoretypes "cosmossdk.io/core/store" 10 "cosmossdk.io/log" 11 12 "github.com/cosmos/cosmos-sdk/baseapp" 13 "github.com/cosmos/cosmos-sdk/codec" 14 sdk "github.com/cosmos/cosmos-sdk/types" 15 "github.com/cosmos/cosmos-sdk/x/gov/types" 16 v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" 17 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" 18 ) 19 20 // Keeper defines the governance module Keeper 21 type Keeper struct { 22 authKeeper types.AccountKeeper 23 bankKeeper types.BankKeeper 24 distrKeeper types.DistributionKeeper 25 26 // The reference to the DelegationSet and ValidatorSet to get information about validators and delegators 27 sk types.StakingKeeper 28 29 // GovHooks 30 hooks types.GovHooks 31 32 // The (unexposed) keys used to access the stores from the Context. 33 storeService corestoretypes.KVStoreService 34 35 // The codec for binary encoding/decoding. 36 cdc codec.Codec 37 38 // Legacy Proposal router 39 legacyRouter v1beta1.Router 40 41 // Msg server router 42 router baseapp.MessageRouter 43 44 config types.Config 45 46 // the address capable of executing a MsgUpdateParams message. Typically, this 47 // should be the x/gov module account. 48 authority string 49 50 Schema collections.Schema 51 Constitution collections.Item[string] 52 Params collections.Item[v1.Params] 53 Deposits collections.Map[collections.Pair[uint64, sdk.AccAddress], v1.Deposit] 54 Votes collections.Map[collections.Pair[uint64, sdk.AccAddress], v1.Vote] 55 ProposalID collections.Sequence 56 Proposals collections.Map[uint64, v1.Proposal] 57 ActiveProposalsQueue collections.Map[collections.Pair[time.Time, uint64], uint64] // TODO(tip): this should be simplified and go into an index. 58 InactiveProposalsQueue collections.Map[collections.Pair[time.Time, uint64], uint64] // TODO(tip): this should be simplified and go into an index. 59 VotingPeriodProposals collections.Map[uint64, []byte] // TODO(tip): this could be a keyset or index. 60 } 61 62 // GetAuthority returns the x/gov module's authority. 63 func (k Keeper) GetAuthority() string { 64 return k.authority 65 } 66 67 // NewKeeper returns a governance keeper. It handles: 68 // - submitting governance proposals 69 // - depositing funds into proposals, and activating upon sufficient funds being deposited 70 // - users voting on proposals, with weight proportional to stake in the system 71 // - and tallying the result of the vote. 72 // 73 // CONTRACT: the parameter Subspace must have the param key table already initialized 74 func NewKeeper( 75 cdc codec.Codec, storeService corestoretypes.KVStoreService, authKeeper types.AccountKeeper, 76 bankKeeper types.BankKeeper, sk types.StakingKeeper, distrKeeper types.DistributionKeeper, 77 router baseapp.MessageRouter, config types.Config, authority string, 78 ) *Keeper { 79 // ensure governance module account is set 80 if addr := authKeeper.GetModuleAddress(types.ModuleName); addr == nil { 81 panic(fmt.Sprintf("%s module account has not been set", types.ModuleName)) 82 } 83 84 if _, err := authKeeper.AddressCodec().StringToBytes(authority); err != nil { 85 panic(fmt.Sprintf("invalid authority address: %s", authority)) 86 } 87 88 // If MaxMetadataLen not set by app developer, set to default value. 89 if config.MaxMetadataLen == 0 { 90 config.MaxMetadataLen = types.DefaultConfig().MaxMetadataLen 91 } 92 93 sb := collections.NewSchemaBuilder(storeService) 94 k := &Keeper{ 95 storeService: storeService, 96 authKeeper: authKeeper, 97 bankKeeper: bankKeeper, 98 distrKeeper: distrKeeper, 99 sk: sk, 100 cdc: cdc, 101 router: router, 102 config: config, 103 authority: authority, 104 Constitution: collections.NewItem(sb, types.ConstitutionKey, "constitution", collections.StringValue), 105 Params: collections.NewItem(sb, types.ParamsKey, "params", codec.CollValue[v1.Params](cdc)), 106 Deposits: collections.NewMap(sb, types.DepositsKeyPrefix, "deposits", collections.PairKeyCodec(collections.Uint64Key, sdk.LengthPrefixedAddressKey(sdk.AccAddressKey)), codec.CollValue[v1.Deposit](cdc)), // nolint: staticcheck // sdk.LengthPrefixedAddressKey is needed to retain state compatibility 107 Votes: collections.NewMap(sb, types.VotesKeyPrefix, "votes", collections.PairKeyCodec(collections.Uint64Key, sdk.LengthPrefixedAddressKey(sdk.AccAddressKey)), codec.CollValue[v1.Vote](cdc)), // nolint: staticcheck // sdk.LengthPrefixedAddressKey is needed to retain state compatibility 108 ProposalID: collections.NewSequence(sb, types.ProposalIDKey, "proposal_id"), 109 Proposals: collections.NewMap(sb, types.ProposalsKeyPrefix, "proposals", collections.Uint64Key, codec.CollValue[v1.Proposal](cdc)), 110 ActiveProposalsQueue: collections.NewMap(sb, types.ActiveProposalQueuePrefix, "active_proposals_queue", collections.PairKeyCodec(sdk.TimeKey, collections.Uint64Key), collections.Uint64Value), // sdk.TimeKey is needed to retain state compatibility 111 InactiveProposalsQueue: collections.NewMap(sb, types.InactiveProposalQueuePrefix, "inactive_proposals_queue", collections.PairKeyCodec(sdk.TimeKey, collections.Uint64Key), collections.Uint64Value), // sdk.TimeKey is needed to retain state compatibility 112 VotingPeriodProposals: collections.NewMap(sb, types.VotingPeriodProposalKeyPrefix, "voting_period_proposals", collections.Uint64Key, collections.BytesValue), 113 } 114 schema, err := sb.Build() 115 if err != nil { 116 panic(err) 117 } 118 k.Schema = schema 119 return k 120 } 121 122 // Hooks gets the hooks for governance *Keeper { 123 func (k *Keeper) Hooks() types.GovHooks { 124 if k.hooks == nil { 125 // return a no-op implementation if no hooks are set 126 return types.MultiGovHooks{} 127 } 128 129 return k.hooks 130 } 131 132 // SetHooks sets the hooks for governance 133 func (k *Keeper) SetHooks(gh types.GovHooks) *Keeper { 134 if k.hooks != nil { 135 panic("cannot set governance hooks twice") 136 } 137 138 k.hooks = gh 139 140 return k 141 } 142 143 // SetLegacyRouter sets the legacy router for governance 144 func (k *Keeper) SetLegacyRouter(router v1beta1.Router) { 145 // It is vital to seal the governance proposal router here as to not allow 146 // further handlers to be registered after the keeper is created since this 147 // could create invalid or non-deterministic behavior. 148 router.Seal() 149 k.legacyRouter = router 150 } 151 152 // Logger returns a module-specific logger. 153 func (k Keeper) Logger(ctx context.Context) log.Logger { 154 sdkCtx := sdk.UnwrapSDKContext(ctx) 155 return sdkCtx.Logger().With("module", "x/"+types.ModuleName) 156 } 157 158 // Router returns the gov keeper's router 159 func (k Keeper) Router() baseapp.MessageRouter { 160 return k.router 161 } 162 163 // LegacyRouter returns the gov keeper's legacy router 164 func (k Keeper) LegacyRouter() v1beta1.Router { 165 return k.legacyRouter 166 } 167 168 // GetGovernanceAccount returns the governance ModuleAccount 169 func (k Keeper) GetGovernanceAccount(ctx context.Context) sdk.ModuleAccountI { 170 return k.authKeeper.GetModuleAccount(ctx, types.ModuleName) 171 } 172 173 // ModuleAccountAddress returns gov module account address 174 func (k Keeper) ModuleAccountAddress() sdk.AccAddress { 175 return k.authKeeper.GetModuleAddress(types.ModuleName) 176 } 177 178 // assertMetadataLength returns an error if given metadata length 179 // is greater than a pre-defined MaxMetadataLen. 180 func (k Keeper) assertMetadataLength(metadata string) error { 181 if metadata != "" && uint64(len(metadata)) > k.config.MaxMetadataLen { 182 return types.ErrMetadataTooLong.Wrapf("got metadata with length %d", len(metadata)) 183 } 184 return nil 185 } 186 187 // assertSummaryLength returns an error if given summary length 188 // is greater than a pre-defined 40*MaxMetadataLen. 189 func (k Keeper) assertSummaryLength(summary string) error { 190 if summary != "" && uint64(len(summary)) > 40*k.config.MaxMetadataLen { 191 return types.ErrSummaryTooLong.Wrapf("got summary with length %d", len(summary)) 192 } 193 return nil 194 }