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  }