github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/sdk/auth/keeper.go (about) 1 package auth 2 3 import ( 4 "fmt" 5 "log/slog" 6 7 "github.com/gnolang/gno/tm2/pkg/amino" 8 "github.com/gnolang/gno/tm2/pkg/crypto" 9 "github.com/gnolang/gno/tm2/pkg/sdk" 10 "github.com/gnolang/gno/tm2/pkg/std" 11 "github.com/gnolang/gno/tm2/pkg/store" 12 ) 13 14 // Concrete implementation of AccountKeeper. 15 type AccountKeeper struct { 16 // The (unexposed) key used to access the store from the Context. 17 key store.StoreKey 18 19 // The prototypical Account constructor. 20 proto func() std.Account 21 } 22 23 // NewAccountKeeper returns a new AccountKeeper that uses go-amino to 24 // (binary) encode and decode concrete std.Accounts. 25 func NewAccountKeeper( 26 key store.StoreKey, proto func() std.Account, 27 ) AccountKeeper { 28 return AccountKeeper{ 29 key: key, 30 proto: proto, 31 } 32 } 33 34 // Logger returns a module-specific logger. 35 func (ak AccountKeeper) Logger(ctx sdk.Context) *slog.Logger { 36 return ctx.Logger().With("module", fmt.Sprintf("auth")) 37 } 38 39 // NewAccountWithAddress implements AccountKeeper. 40 func (ak AccountKeeper) NewAccountWithAddress(ctx sdk.Context, addr crypto.Address) std.Account { 41 acc := ak.proto() 42 // acc.SetSequence(0) // start with 0. 43 err := acc.SetAddress(addr) 44 if err != nil { 45 // Handle w/ #870 46 panic(err) 47 } 48 err = acc.SetAccountNumber(ak.GetNextAccountNumber(ctx)) 49 if err != nil { 50 // Handle w/ #870 51 panic(err) 52 } 53 return acc 54 } 55 56 // GetAccount implements AccountKeeper. 57 func (ak AccountKeeper) GetAccount(ctx sdk.Context, addr crypto.Address) std.Account { 58 stor := ctx.Store(ak.key) 59 bz := stor.Get(AddressStoreKey(addr)) 60 if bz == nil { 61 return nil 62 } 63 acc := ak.decodeAccount(bz) 64 return acc 65 } 66 67 // GetAllAccounts returns all accounts in the AccountKeeper. 68 func (ak AccountKeeper) GetAllAccounts(ctx sdk.Context) []std.Account { 69 accounts := []std.Account{} 70 appendAccount := func(acc std.Account) (stop bool) { 71 accounts = append(accounts, acc) 72 return false 73 } 74 ak.IterateAccounts(ctx, appendAccount) 75 return accounts 76 } 77 78 // SetAccount implements AccountKeeper. 79 func (ak AccountKeeper) SetAccount(ctx sdk.Context, acc std.Account) { 80 addr := acc.GetAddress() 81 stor := ctx.Store(ak.key) 82 bz, err := amino.MarshalAny(acc) 83 if err != nil { 84 panic(err) 85 } 86 stor.Set(AddressStoreKey(addr), bz) 87 } 88 89 // RemoveAccount removes an account for the account mapper store. 90 // NOTE: this will cause supply invariant violation if called 91 func (ak AccountKeeper) RemoveAccount(ctx sdk.Context, acc std.Account) { 92 addr := acc.GetAddress() 93 stor := ctx.Store(ak.key) 94 stor.Delete(AddressStoreKey(addr)) 95 } 96 97 // IterateAccounts implements AccountKeeper. 98 func (ak AccountKeeper) IterateAccounts(ctx sdk.Context, process func(std.Account) (stop bool)) { 99 stor := ctx.Store(ak.key) 100 iter := store.PrefixIterator(stor, []byte(AddressStoreKeyPrefix)) 101 defer iter.Close() 102 for { 103 if !iter.Valid() { 104 return 105 } 106 val := iter.Value() 107 acc := ak.decodeAccount(val) 108 if process(acc) { 109 return 110 } 111 iter.Next() 112 } 113 } 114 115 // GetPubKey Returns the PubKey of the account at address 116 func (ak AccountKeeper) GetPubKey(ctx sdk.Context, addr crypto.Address) (crypto.PubKey, error) { 117 acc := ak.GetAccount(ctx, addr) 118 if acc == nil { 119 return nil, std.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", addr)) 120 } 121 return acc.GetPubKey(), nil 122 } 123 124 // GetSequence Returns the Sequence of the account at address 125 func (ak AccountKeeper) GetSequence(ctx sdk.Context, addr crypto.Address) (uint64, error) { 126 acc := ak.GetAccount(ctx, addr) 127 if acc == nil { 128 return 0, std.ErrUnknownAddress(fmt.Sprintf("account %s does not exist", addr)) 129 } 130 return acc.GetSequence(), nil 131 } 132 133 // GetNextAccountNumber Returns and increments the global account number counter 134 func (ak AccountKeeper) GetNextAccountNumber(ctx sdk.Context) uint64 { 135 var accNumber uint64 136 stor := ctx.Store(ak.key) 137 bz := stor.Get([]byte(GlobalAccountNumberKey)) 138 if bz == nil { 139 accNumber = 0 // start with 0. 140 } else { 141 err := amino.Unmarshal(bz, &accNumber) 142 if err != nil { 143 panic(err) 144 } 145 } 146 147 bz = amino.MustMarshal(accNumber + 1) 148 stor.Set([]byte(GlobalAccountNumberKey), bz) 149 150 return accNumber 151 } 152 153 // ----------------------------------------------------------------------------- 154 // Misc. 155 156 func (ak AccountKeeper) decodeAccount(bz []byte) (acc std.Account) { 157 err := amino.Unmarshal(bz, &acc) 158 if err != nil { 159 panic(err) 160 } 161 return 162 }