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  }