From 7273bd39e713be8c9dd17bae71b85df495b98be0 Mon Sep 17 00:00:00 2001 From: Dev Ojha Date: Tue, 31 Aug 2021 01:07:31 -0400 Subject: [PATCH] perf!: Add HasAccount to the AuthKeeper to save protobuf decoding time (#10022) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add HasAccount to the AuthKeeper to save protobuf decoding time We found in the Osmosis epoch time, the many accesses to GetAccount's proto unmarshalling was a significant slowdown. This adds a HasAccount method to the AuthKeeper, and fixes one unnecessary spot that it appears within in SendCoins * Update Spec * Add Changelog entry * Fix lint & use speedup in SendCoins * Update x/auth/keeper/account.go Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> --- CHANGELOG.md | 2 ++ x/auth/keeper/account.go | 6 ++++++ x/auth/keeper/keeper.go | 3 +++ x/auth/spec/04_keepers.md | 3 +++ x/bank/keeper/send.go | 8 ++++---- x/bank/types/expected_keepers.go | 1 + 6 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3ee0f67b..62f0ae124 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### API Breaking Changes +* [\#10022](https://github.com/cosmos/cosmos-sdk/pull/10022) `AuthKeeper` interface in `x/auth` now includes a function `HasAccount`. * [\#9759](https://github.com/cosmos/cosmos-sdk/pull/9759) `NewAccountKeeeper` in `x/auth` now takes an additional `bech32Prefix` argument that represents `sdk.Bech32MainPrefix`. * [\#9628](https://github.com/cosmos/cosmos-sdk/pull/9628) Rename `x/{mod}/legacy` to `x/{mod}/migrations`. * [\#9571](https://github.com/cosmos/cosmos-sdk/pull/9571) Implemented error handling for staking hooks, which now return an error on failure. @@ -85,6 +86,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (x/bank) [\#10022](https://github.com/cosmos/cosmos-sdk/pull/10022) `BankKeeper.SendCoins` now takes less execution time. * (deps) [\#9956](https://github.com/cosmos/cosmos-sdk/pull/9956) Bump Tendermint to [v0.34.12](https://github.com/tendermint/tendermint/releases/tag/v0.34.12). * (cli) [\#9856](https://github.com/cosmos/cosmos-sdk/pull/9856) Overwrite `--sequence` and `--account-number` flags with default flag values when used with `offline=false` in `sign-batch` command. diff --git a/x/auth/keeper/account.go b/x/auth/keeper/account.go index a26ea6427..7474e93a5 100644 --- a/x/auth/keeper/account.go +++ b/x/auth/keeper/account.go @@ -25,6 +25,12 @@ func (ak AccountKeeper) NewAccount(ctx sdk.Context, acc types.AccountI) types.Ac return acc } +// HasAccount implements AccountKeeperI. +func (ak AccountKeeper) HasAccount(ctx sdk.Context, addr sdk.AccAddress) bool { + store := ctx.KVStore(ak.key) + return store.Has(types.AddressStoreKey(addr)) +} + // GetAccount implements AccountKeeperI. func (ak AccountKeeper) GetAccount(ctx sdk.Context, addr sdk.AccAddress) types.AccountI { store := ctx.KVStore(ak.key) diff --git a/x/auth/keeper/keeper.go b/x/auth/keeper/keeper.go index 8b8ba835c..10ce4f0be 100644 --- a/x/auth/keeper/keeper.go +++ b/x/auth/keeper/keeper.go @@ -25,6 +25,9 @@ type AccountKeeperI interface { // Return a new account with the next account number. Does not save the new account to the store. NewAccount(sdk.Context, types.AccountI) types.AccountI + // Check if an account exists in the store. + HasAccount(sdk.Context, sdk.AccAddress) bool + // Retrieve an account from the store. GetAccount(sdk.Context, sdk.AccAddress) types.AccountI diff --git a/x/auth/spec/04_keepers.md b/x/auth/spec/04_keepers.md index 40882e24e..268ced5c3 100644 --- a/x/auth/spec/04_keepers.md +++ b/x/auth/spec/04_keepers.md @@ -20,6 +20,9 @@ type AccountKeeperI interface { // Return a new account with the next account number. Does not save the new account to the store. NewAccount(sdk.Context, types.AccountI) types.AccountI + // Check if an account exists in the store. + HasAccount(sdk.Context, sdk.AccAddress) bool + // Retrieve an account from the store. GetAccount(sdk.Context, sdk.AccAddress) types.AccountI diff --git a/x/bank/keeper/send.go b/x/bank/keeper/send.go index 17427cabb..b0c38a320 100644 --- a/x/bank/keeper/send.go +++ b/x/bank/keeper/send.go @@ -120,8 +120,8 @@ func (k BaseSendKeeper) InputOutputCoins(ctx sdk.Context, inputs []types.Input, // // NOTE: This should ultimately be removed in favor a more flexible approach // such as delegated fee messages. - acc := k.ak.GetAccount(ctx, outAddress) - if acc == nil { + accExists := k.ak.HasAccount(ctx, outAddress) + if !accExists { defer telemetry.IncrCounter(1, "new", "account") k.ak.SetAccount(ctx, k.ak.NewAccountWithAddress(ctx, outAddress)) } @@ -147,8 +147,8 @@ func (k BaseSendKeeper) SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAd // // NOTE: This should ultimately be removed in favor a more flexible approach // such as delegated fee messages. - acc := k.ak.GetAccount(ctx, toAddr) - if acc == nil { + accExists := k.ak.HasAccount(ctx, toAddr) + if !accExists { defer telemetry.IncrCounter(1, "new", "account") k.ak.SetAccount(ctx, k.ak.NewAccountWithAddress(ctx, toAddr)) } diff --git a/x/bank/types/expected_keepers.go b/x/bank/types/expected_keepers.go index 7307864b8..23ca020a3 100644 --- a/x/bank/types/expected_keepers.go +++ b/x/bank/types/expected_keepers.go @@ -13,6 +13,7 @@ type AccountKeeper interface { GetAccount(ctx sdk.Context, addr sdk.AccAddress) types.AccountI GetAllAccounts(ctx sdk.Context) []types.AccountI + HasAccount(ctx sdk.Context, addr sdk.AccAddress) bool SetAccount(ctx sdk.Context, acc types.AccountI) IterateAccounts(ctx sdk.Context, process func(types.AccountI) bool)