github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/auth/keeper/account.go (about) 1 package keeper 2 3 import ( 4 "sync" 5 6 ethcmn "github.com/ethereum/go-ethereum/common" 7 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/store/mpt" 8 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 9 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/exported" 10 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/types" 11 tmtypes "github.com/fibonacci-chain/fbc/libs/tendermint/types" 12 "github.com/tendermint/go-amino" 13 ) 14 15 // NewAccountWithAddress implements sdk.AccountKeeper. 16 func (ak AccountKeeper) NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) exported.Account { 17 acc := ak.proto() 18 err := acc.SetAddress(addr) 19 if err != nil { 20 panic(err) 21 } 22 return ak.NewAccount(ctx, acc) 23 } 24 25 // NewAccount sets the next account number to a given account interface 26 func (ak AccountKeeper) NewAccount(ctx sdk.Context, acc exported.Account) exported.Account { 27 if err := acc.SetAccountNumber(ak.GetNextAccountNumber(ctx)); err != nil { 28 panic(err) 29 } 30 return acc 31 } 32 33 var addrStoreKeyPool = &sync.Pool{ 34 New: func() interface{} { 35 return &[33]byte{} 36 }, 37 } 38 39 // GetAccount implements sdk.AccountKeeper. 40 func (ak AccountKeeper) GetAccount(ctx sdk.Context, addr sdk.AccAddress) exported.Account { 41 if data, gas, ok := ctx.Cache().GetAccount(ethcmn.BytesToAddress(addr)); ok { 42 ctx.GasMeter().ConsumeGas(gas, "x/auth/keeper/account.go/GetAccount") 43 if data == nil { 44 return nil 45 } 46 47 return data.Copy() 48 } 49 50 var key sdk.StoreKey 51 if tmtypes.HigherThanMars(ctx.BlockHeight()) { 52 key = ak.mptKey 53 } else { 54 key = ak.key 55 } 56 57 store := ctx.GetReusableKVStore(key) 58 keyTarget := addrStoreKeyPool.Get().(*[33]byte) 59 defer func() { 60 addrStoreKeyPool.Put(keyTarget) 61 ctx.ReturnKVStore(store) 62 }() 63 64 bz := store.Get(types.MakeAddressStoreKey(addr, keyTarget[:0])) 65 if bz == nil { 66 ctx.Cache().UpdateAccount(addr, nil, len(bz), false) 67 return nil 68 } 69 acc := ak.decodeAccount(bz) 70 71 if ctx.Cache().IsEnabled() { 72 ctx.Cache().UpdateAccount(addr, acc.Copy(), len(bz), false) 73 } 74 75 return acc 76 } 77 78 // LoadAccount load account from store without return, only used in pre deliver tx 79 func (ak AccountKeeper) LoadAccount(ctx sdk.Context, addr sdk.AccAddress) { 80 if _, gas, ok := ctx.Cache().GetAccount(ethcmn.BytesToAddress(addr)); ok { 81 ctx.GasMeter().ConsumeGas(gas, "x/auth/keeper/account.go/GetAccount") 82 return 83 } 84 85 var key sdk.StoreKey 86 if tmtypes.HigherThanMars(ctx.BlockHeight()) { 87 key = ak.mptKey 88 } else { 89 key = ak.key 90 } 91 store := ctx.GetReusableKVStore(key) 92 keyTarget := addrStoreKeyPool.Get().(*[33]byte) 93 defer func() { 94 addrStoreKeyPool.Put(keyTarget) 95 ctx.ReturnKVStore(store) 96 }() 97 98 bz := store.Get(types.MakeAddressStoreKey(addr, keyTarget[:0])) 99 var acc exported.Account 100 if bz != nil { 101 acc = ak.decodeAccount(bz) 102 } 103 ctx.Cache().UpdateAccount(addr, acc, len(bz), false) 104 return 105 } 106 107 // GetAllAccounts returns all accounts in the accountKeeper. 108 func (ak AccountKeeper) GetAllAccounts(ctx sdk.Context) (accounts []exported.Account) { 109 ak.IterateAccounts(ctx, 110 func(acc exported.Account) (stop bool) { 111 accounts = append(accounts, acc) 112 return false 113 }) 114 return accounts 115 } 116 117 // SetAccount implements sdk.AccountKeeper. 118 func (ak AccountKeeper) SetAccount(ctx sdk.Context, acc exported.Account) { 119 addr := acc.GetAddress() 120 121 var key sdk.StoreKey 122 if tmtypes.HigherThanMars(ctx.BlockHeight()) { 123 key = ak.mptKey 124 } else { 125 key = ak.key 126 } 127 store := ctx.GetReusableKVStore(key) 128 defer ctx.ReturnKVStore(store) 129 130 bz := ak.encodeAccount(acc) 131 132 storeAccKey := types.AddressStoreKey(addr) 133 store.Set(storeAccKey, bz) 134 if !tmtypes.HigherThanMars(ctx.BlockHeight()) && mpt.TrieWriteAhead { 135 ctx.MultiStore().GetKVStore(ak.mptKey).Set(storeAccKey, bz) 136 } 137 if ctx.Cache().IsEnabled() { 138 ctx.Cache().UpdateAccount(addr, acc.Copy(), len(bz), true) 139 } 140 141 if ctx.IsDeliver() && (tmtypes.HigherThanMars(ctx.BlockHeight()) || mpt.TrieWriteAhead) { 142 mpt.GAccToPrefetchChannel <- [][]byte{storeAccKey} 143 } 144 145 if !ctx.IsCheckTx() && !ctx.IsReCheckTx() { 146 if ak.observers != nil { 147 for _, observer := range ak.observers { 148 if observer != nil { 149 observer.OnAccountUpdated(acc) 150 } 151 } 152 } 153 } 154 } 155 156 func (ak *AccountKeeper) encodeAccount(acc exported.Account) (bz []byte) { 157 var err error 158 if accSizer, ok := acc.(amino.MarshalBufferSizer); ok { 159 bz, err = ak.cdc.MarshalBinaryWithSizer(accSizer, false) 160 if err == nil { 161 return bz 162 } 163 } 164 165 bz, err = ak.cdc.MarshalBinaryBareWithRegisteredMarshaller(acc) 166 if err != nil { 167 bz, err = ak.cdc.MarshalBinaryBare(acc) 168 } 169 if err != nil { 170 panic(err) 171 } 172 return bz 173 } 174 175 // RemoveAccount removes an account for the account mapper store. 176 // NOTE: this will cause supply invariant violation if called 177 func (ak AccountKeeper) RemoveAccount(ctx sdk.Context, acc exported.Account) { 178 addr := acc.GetAddress() 179 var store sdk.KVStore 180 if tmtypes.HigherThanMars(ctx.BlockHeight()) { 181 store = ctx.KVStore(ak.mptKey) 182 } else { 183 store = ctx.KVStore(ak.key) 184 } 185 186 storeAccKey := types.AddressStoreKey(addr) 187 store.Delete(storeAccKey) 188 if !tmtypes.HigherThanMars(ctx.BlockHeight()) && mpt.TrieWriteAhead { 189 ctx.MultiStore().GetKVStore(ak.mptKey).Delete(storeAccKey) 190 } 191 192 if ctx.IsDeliver() && (tmtypes.HigherThanMars(ctx.BlockHeight()) || mpt.TrieWriteAhead) { 193 mpt.GAccToPrefetchChannel <- [][]byte{storeAccKey} 194 } 195 196 ctx.Cache().UpdateAccount(addr, nil, 0, true) 197 } 198 199 // IterateAccounts iterates over all the stored accounts and performs a callback function 200 func (ak AccountKeeper) IterateAccounts(ctx sdk.Context, cb func(account exported.Account) (stop bool)) { 201 var store sdk.KVStore 202 if tmtypes.HigherThanMars(ctx.BlockHeight()) { 203 store = ctx.KVStore(ak.mptKey) 204 } else { 205 store = ctx.KVStore(ak.key) 206 } 207 iterator := sdk.KVStorePrefixIterator(store, types.AddressStoreKeyPrefix) 208 209 defer iterator.Close() 210 for ; iterator.Valid(); iterator.Next() { 211 account := ak.decodeAccount(iterator.Value()) 212 213 if cb(account) { 214 break 215 } 216 } 217 } 218 219 // IterateAccounts iterates over all the stored accounts and performs a callback function 220 func (ak AccountKeeper) MigrateAccounts(ctx sdk.Context, cb func(account exported.Account, key, value []byte) (stop bool)) { 221 var store sdk.KVStore 222 if tmtypes.HigherThanMars(ctx.BlockHeight()) { 223 store = ctx.KVStore(ak.mptKey) 224 } else { 225 store = ctx.KVStore(ak.key) 226 } 227 iterator := sdk.KVStorePrefixIterator(store, types.AddressStoreKeyPrefix) 228 229 defer iterator.Close() 230 for ; iterator.Valid(); iterator.Next() { 231 account := ak.decodeAccount(iterator.Value()) 232 233 if cb(account, iterator.Key(), iterator.Value()) { 234 break 235 } 236 } 237 } 238 239 func (ak AccountKeeper) GetEncodedAccountSize(acc exported.Account) int { 240 if sizer, ok := acc.(amino.Sizer); ok { 241 // typeprefix + amino bytes 242 return 4 + sizer.AminoSize(ak.cdc) 243 } else { 244 return len(ak.cdc.MustMarshalBinaryBare(acc)) 245 } 246 }