Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/bank/types: fix AddressFromBalancesStore panics with invalid keys #9061

Merged
merged 1 commit into from
Apr 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (client) [\#8926](https://github.com/cosmos/cosmos-sdk/pull/8926) `client/tx.PrepareFactory` has been converted to a private function, as it's only used internally.
* (auth/tx) [\#8926](https://github.com/cosmos/cosmos-sdk/pull/8926) The `ProtoTxProvider` interface used as a workaround for transaction simulation has been removed.
* (x/bank) [\#8798](https://github.com/cosmos/cosmos-sdk/pull/8798) `GetTotalSupply` is removed in favour of `GetPaginatedTotalSupply`
* (x/bank/types) [\#9061](https://github.com/cosmos/cosmos-sdk/pull/9061) `AddressFromBalancesStore` now returns an error for invalid key instead of panic.

### State Machine Breaking

Expand Down
8 changes: 7 additions & 1 deletion x/bank/keeper/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,13 @@ func (k BaseViewKeeper) IterateAllBalances(ctx sdk.Context, cb func(sdk.AccAddre
defer iterator.Close()

for ; iterator.Valid(); iterator.Next() {
address := types.AddressFromBalancesStore(iterator.Key())
address, err := types.AddressFromBalancesStore(iterator.Key())
if err != nil {
k.Logger(ctx).With("key", iterator.Key(), "err", err).Error("failed to get address from balances store")
// TODO: revisit, for now, panic here to keep same behavior as in 0.42
cuonglm marked this conversation as resolved.
Show resolved Hide resolved
// ref: https://github.com/cosmos/cosmos-sdk/issues/7409
panic(err)
}

var balance sdk.Coin
k.cdc.MustUnmarshalBinaryBare(iterator.Value(), &balance)
Expand Down
1 change: 1 addition & 0 deletions x/bank/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ var (
ErrInputOutputMismatch = sdkerrors.Register(ModuleName, 4, "sum inputs != sum outputs")
ErrSendDisabled = sdkerrors.Register(ModuleName, 5, "send transactions are disabled")
ErrDenomMetadataNotFound = sdkerrors.Register(ModuleName, 6, "client denom metadata not found")
ErrInvalidKey = sdkerrors.Register(ModuleName, 7, "invalid key")
)
12 changes: 10 additions & 2 deletions x/bank/types/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,19 @@ func DenomMetadataKey(denom string) []byte {
// AddressFromBalancesStore returns an account address from a balances prefix
// store. The key must not contain the perfix BalancesPrefix as the prefix store
// iterator discards the actual prefix.
func AddressFromBalancesStore(key []byte) sdk.AccAddress {
//
// If invalid key is passed, AddressFromBalancesStore returns ErrInvalidKey.
func AddressFromBalancesStore(key []byte) (sdk.AccAddress, error) {
if len(key) == 0 {
return nil, ErrInvalidKey
}
addrLen := key[0]
if len(key[1:]) < int(addrLen) {
return nil, ErrInvalidKey
}
addr := key[1 : addrLen+1]

return sdk.AccAddress(addr)
return sdk.AccAddress(addr), nil
}

// CreateAccountBalancesPrefix creates the prefix for an account's balances.
Expand Down
25 changes: 24 additions & 1 deletion x/bank/types/key_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package types_test

import (
"errors"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -24,6 +26,27 @@ func TestAddressFromBalancesStore(t *testing.T) {
require.Equal(t, 20, addrLen)

key := cloneAppend(address.MustLengthPrefix(addr), []byte("stake"))
res := types.AddressFromBalancesStore(key)
res, err := types.AddressFromBalancesStore(key)
require.NoError(t, err)
require.Equal(t, res, addr)
}

func TestInvalidAddressFromBalancesStore(t *testing.T) {
tests := []struct {
name string
key []byte
}{
{"empty", []byte("")},
{"invalid", []byte("3AA")},
}

for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
_, err := types.AddressFromBalancesStore(tc.key)
assert.Error(t, err)
assert.True(t, errors.Is(types.ErrInvalidKey, err))
})
}
}