github.com/cosmos/cosmos-sdk@v0.50.10/x/auth/types/account.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "strings" 9 10 "github.com/cometbft/cometbft/crypto" 11 12 codectypes "github.com/cosmos/cosmos-sdk/codec/types" 13 cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" 14 sdk "github.com/cosmos/cosmos-sdk/types" 15 "github.com/cosmos/cosmos-sdk/types/address" 16 ) 17 18 var ( 19 _ sdk.AccountI = (*BaseAccount)(nil) 20 _ GenesisAccount = (*BaseAccount)(nil) 21 _ codectypes.UnpackInterfacesMessage = (*BaseAccount)(nil) 22 _ GenesisAccount = (*ModuleAccount)(nil) 23 _ sdk.ModuleAccountI = (*ModuleAccount)(nil) 24 ) 25 26 // NewBaseAccount creates a new BaseAccount object. 27 func NewBaseAccount(address sdk.AccAddress, pubKey cryptotypes.PubKey, accountNumber, sequence uint64) *BaseAccount { 28 acc := &BaseAccount{ 29 Address: address.String(), 30 AccountNumber: accountNumber, 31 Sequence: sequence, 32 } 33 34 err := acc.SetPubKey(pubKey) 35 if err != nil { 36 panic(err) 37 } 38 39 return acc 40 } 41 42 // ProtoBaseAccount - a prototype function for BaseAccount 43 func ProtoBaseAccount() sdk.AccountI { 44 return &BaseAccount{} 45 } 46 47 // NewBaseAccountWithAddress - returns a new base account with a given address 48 // leaving AccountNumber and Sequence to zero. 49 func NewBaseAccountWithAddress(addr sdk.AccAddress) *BaseAccount { 50 return &BaseAccount{ 51 Address: addr.String(), 52 } 53 } 54 55 // GetAddress - Implements sdk.AccountI. 56 func (acc BaseAccount) GetAddress() sdk.AccAddress { 57 addr, _ := sdk.AccAddressFromBech32(acc.Address) 58 return addr 59 } 60 61 // SetAddress - Implements sdk.AccountI. 62 func (acc *BaseAccount) SetAddress(addr sdk.AccAddress) error { 63 if len(acc.Address) != 0 { 64 return errors.New("cannot override BaseAccount address") 65 } 66 67 acc.Address = addr.String() 68 return nil 69 } 70 71 // GetPubKey - Implements sdk.AccountI. 72 func (acc BaseAccount) GetPubKey() (pk cryptotypes.PubKey) { 73 if acc.PubKey == nil { 74 return nil 75 } 76 content, ok := acc.PubKey.GetCachedValue().(cryptotypes.PubKey) 77 if !ok { 78 return nil 79 } 80 return content 81 } 82 83 // SetPubKey - Implements sdk.AccountI. 84 func (acc *BaseAccount) SetPubKey(pubKey cryptotypes.PubKey) error { 85 if pubKey == nil { 86 acc.PubKey = nil 87 return nil 88 } 89 any, err := codectypes.NewAnyWithValue(pubKey) 90 if err == nil { 91 acc.PubKey = any 92 } 93 return err 94 } 95 96 // GetAccountNumber - Implements AccountI 97 func (acc BaseAccount) GetAccountNumber() uint64 { 98 return acc.AccountNumber 99 } 100 101 // SetAccountNumber - Implements AccountI 102 func (acc *BaseAccount) SetAccountNumber(accNumber uint64) error { 103 acc.AccountNumber = accNumber 104 return nil 105 } 106 107 // GetSequence - Implements sdk.AccountI. 108 func (acc BaseAccount) GetSequence() uint64 { 109 return acc.Sequence 110 } 111 112 // SetSequence - Implements sdk.AccountI. 113 func (acc *BaseAccount) SetSequence(seq uint64) error { 114 acc.Sequence = seq 115 return nil 116 } 117 118 // Validate checks for errors on the account fields 119 func (acc BaseAccount) Validate() error { 120 if acc.Address == "" || acc.PubKey == nil { 121 return nil 122 } 123 124 accAddr, err := sdk.AccAddressFromBech32(acc.Address) 125 if err != nil { 126 return err 127 } 128 129 if !bytes.Equal(acc.GetPubKey().Address().Bytes(), accAddr.Bytes()) { 130 return errors.New("account address and pubkey address do not match") 131 } 132 133 return nil 134 } 135 136 // UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces 137 func (acc BaseAccount) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { 138 if acc.PubKey == nil { 139 return nil 140 } 141 var pubKey cryptotypes.PubKey 142 return unpacker.UnpackAny(acc.PubKey, &pubKey) 143 } 144 145 // NewModuleAddressOrAddress gets an input string and returns an AccAddress. 146 // If the input is a valid address, it returns the address. 147 // If the input is a module name, it returns the module address. 148 func NewModuleAddressOrBech32Address(input string) sdk.AccAddress { 149 if addr, err := sdk.AccAddressFromBech32(input); err == nil { 150 return addr 151 } 152 153 return NewModuleAddress(input) 154 } 155 156 // NewModuleAddress creates an AccAddress from the hash of the module's name 157 func NewModuleAddress(name string) sdk.AccAddress { 158 return address.Module(name) 159 } 160 161 // NewEmptyModuleAccount creates a empty ModuleAccount from a string 162 func NewEmptyModuleAccount(name string, permissions ...string) *ModuleAccount { 163 moduleAddress := NewModuleAddress(name) 164 baseAcc := NewBaseAccountWithAddress(moduleAddress) 165 166 if err := validatePermissions(permissions...); err != nil { 167 panic(err) 168 } 169 170 return &ModuleAccount{ 171 BaseAccount: baseAcc, 172 Name: name, 173 Permissions: permissions, 174 } 175 } 176 177 // NewModuleAccount creates a new ModuleAccount instance 178 func NewModuleAccount(ba *BaseAccount, name string, permissions ...string) *ModuleAccount { 179 if err := validatePermissions(permissions...); err != nil { 180 panic(err) 181 } 182 183 return &ModuleAccount{ 184 BaseAccount: ba, 185 Name: name, 186 Permissions: permissions, 187 } 188 } 189 190 // HasPermission returns whether or not the module account has permission. 191 func (ma ModuleAccount) HasPermission(permission string) bool { 192 for _, perm := range ma.Permissions { 193 if perm == permission { 194 return true 195 } 196 } 197 return false 198 } 199 200 // GetName returns the name of the holder's module 201 func (ma ModuleAccount) GetName() string { 202 return ma.Name 203 } 204 205 // GetPermissions returns permissions granted to the module account 206 func (ma ModuleAccount) GetPermissions() []string { 207 return ma.Permissions 208 } 209 210 // SetPubKey - Implements AccountI 211 func (ma ModuleAccount) SetPubKey(pubKey cryptotypes.PubKey) error { 212 return fmt.Errorf("not supported for module accounts") 213 } 214 215 // Validate checks for errors on the account fields 216 func (ma ModuleAccount) Validate() error { 217 if strings.TrimSpace(ma.Name) == "" { 218 return errors.New("module account name cannot be blank") 219 } 220 221 if ma.BaseAccount == nil { 222 return errors.New("uninitialized ModuleAccount: BaseAccount is nil") 223 } 224 225 if ma.Address != sdk.AccAddress(crypto.AddressHash([]byte(ma.Name))).String() { 226 return fmt.Errorf("address %s cannot be derived from the module name '%s'", ma.Address, ma.Name) 227 } 228 229 return ma.BaseAccount.Validate() 230 } 231 232 type moduleAccountPretty struct { 233 Address sdk.AccAddress `json:"address"` 234 PubKey string `json:"public_key"` 235 AccountNumber uint64 `json:"account_number"` 236 Sequence uint64 `json:"sequence"` 237 Name string `json:"name"` 238 Permissions []string `json:"permissions"` 239 } 240 241 // MarshalJSON returns the JSON representation of a ModuleAccount. 242 func (ma ModuleAccount) MarshalJSON() ([]byte, error) { 243 accAddr, err := sdk.AccAddressFromBech32(ma.Address) 244 if err != nil { 245 return nil, err 246 } 247 248 return json.Marshal(moduleAccountPretty{ 249 Address: accAddr, 250 PubKey: "", 251 AccountNumber: ma.AccountNumber, 252 Sequence: ma.Sequence, 253 Name: ma.Name, 254 Permissions: ma.Permissions, 255 }) 256 } 257 258 // UnmarshalJSON unmarshals raw JSON bytes into a ModuleAccount. 259 func (ma *ModuleAccount) UnmarshalJSON(bz []byte) error { 260 var alias moduleAccountPretty 261 if err := json.Unmarshal(bz, &alias); err != nil { 262 return err 263 } 264 265 ma.BaseAccount = NewBaseAccount(alias.Address, nil, alias.AccountNumber, alias.Sequence) 266 ma.Name = alias.Name 267 ma.Permissions = alias.Permissions 268 269 return nil 270 } 271 272 // AccountI is an interface used to store coins at a given address within state. 273 // It presumes a notion of sequence numbers for replay protection, 274 // a notion of account numbers for replay protection for previously pruned accounts, 275 // and a pubkey for authentication purposes. 276 // 277 // Many complex conditions can be used in the concrete struct which implements AccountI. 278 // 279 // Deprecated: Use `AccountI` from types package instead. 280 type AccountI interface { 281 sdk.AccountI 282 } 283 284 // ModuleAccountI defines an account interface for modules that hold tokens in 285 // an escrow. 286 // 287 // Deprecated: Use `ModuleAccountI` from types package instead. 288 type ModuleAccountI interface { 289 sdk.ModuleAccountI 290 } 291 292 // GenesisAccounts defines a slice of GenesisAccount objects 293 type GenesisAccounts []GenesisAccount 294 295 // Contains returns true if the given address exists in a slice of GenesisAccount 296 // objects. 297 func (ga GenesisAccounts) Contains(addr sdk.Address) bool { 298 for _, acc := range ga { 299 if acc.GetAddress().Equals(addr) { 300 return true 301 } 302 } 303 304 return false 305 } 306 307 // GenesisAccount defines a genesis account that embeds an AccountI with validation capabilities. 308 type GenesisAccount interface { 309 sdk.AccountI 310 311 Validate() error 312 }