Skip to content

Commit

Permalink
feat: add bankplus function to restrict to send coin to inactive sm…
Browse files Browse the repository at this point in the history
…art contract. (#400)

* feat: add `bankplus` function to restrict to send coin to inactive smart contract.

* chore: add bypass codes of `bankplus`

* chore: apply sending restriction function to wasm module

* fix protobuf lint warning

* fix unittest error

* fix golang lint error

* fix golang lint error

* Add a unittest of bankplus.keeper

* fix typo

* fix lint warning

* chore: change `blockedAddr` of `bankplus` module to `inactiveAddr`

* fix wrong linking.

* chore: change the name of `block.go` to `inactive.go`

* chore: apply `bankplus` module to `simd`.

* chore: apply feedbacks

* fix: fix unittest failure.
  • Loading branch information
zemyblue authored Jan 10, 2022
1 parent dba5a45 commit cb1ad80
Show file tree
Hide file tree
Showing 16 changed files with 950 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* (x/feegrant) [\#380] (https://github.com/line/lbm-sdk/pull/380) Feegrant module
* (x/wasm) [\#395] (https://github.com/line/lbm-sdk/pull/395) Add the instantiate_permission in the CodeInfoResponse
* (x/consortium) [\#406] (https://github.com/line/lbm-sdk/pull/406) Add CreateValidator access control feature
* (x/bank) [\#400] (https://github.com/line/lbm-sdk/pull/400) add `bankplus` function to restrict to send coin to inactive smart contract.

### Improvements
* (slashing) [\#347](https://github.com/line/lbm-sdk/pull/347) Introduce VoterSetCounter
Expand Down
34 changes: 34 additions & 0 deletions docs/core/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,9 @@

- [Msg](#lbm.bank.v1.Msg)

- [lbm/bankplus/v1/bankplus.proto](#lbm/bankplus/v1/bankplus.proto)
- [InactiveAddr](#lbm.bankplus.v1.InactiveAddr)

- [lbm/base/abci/v1/abci.proto](#lbm/base/abci/v1/abci.proto)
- [ABCIMessageLog](#lbm.base.abci.v1.ABCIMessageLog)
- [Attribute](#lbm.base.abci.v1.Attribute)
Expand Down Expand Up @@ -4853,6 +4856,37 @@ Msg defines the bank Msg service.



<a name="lbm/bankplus/v1/bankplus.proto"></a>
<p align="right"><a href="#top">Top</a></p>

## lbm/bankplus/v1/bankplus.proto



<a name="lbm.bankplus.v1.InactiveAddr"></a>

### InactiveAddr
InactiveAddr models the blocked address for the bankplus module


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `address` | [string](#string) | | |





<!-- end messages -->

<!-- end enums -->

<!-- end HasExtensions -->

<!-- end services -->



<a name="lbm/base/abci/v1/abci.proto"></a>
<p align="right"><a href="#top">Top</a></p>

Expand Down
13 changes: 13 additions & 0 deletions proto/lbm/bankplus/v1/bankplus.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
syntax = "proto3";
package lbm.bankplus.v1;

import "gogoproto/gogo.proto";

option go_package = "github.com/line/lbm-sdk/x/bankplus/types";

// InactiveAddr models the blocked address for the bankplus module
message InactiveAddr {
option (gogoproto.equal) = true;

string address = 1;
}
30 changes: 25 additions & 5 deletions simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ import (
"github.com/line/lbm-sdk/x/bank"
bankkeeper "github.com/line/lbm-sdk/x/bank/keeper"
banktypes "github.com/line/lbm-sdk/x/bank/types"
"github.com/line/lbm-sdk/x/bankplus"
bankpluskeeper "github.com/line/lbm-sdk/x/bankplus/keeper"
"github.com/line/lbm-sdk/x/capability"
capabilitykeeper "github.com/line/lbm-sdk/x/capability/keeper"
capabilitytypes "github.com/line/lbm-sdk/x/capability/types"
Expand Down Expand Up @@ -146,6 +148,11 @@ var (
govtypes.ModuleName: {authtypes.Burner},
ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner},
}

// module accounts that are allowed to receive tokens
allowedReceivingModAcc = map[string]bool{
distrtypes.ModuleName: true,
}
)

var (
Expand Down Expand Up @@ -263,9 +270,8 @@ func NewSimApp(
app.AccountKeeper = authkeeper.NewAccountKeeper(
appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), authtypes.ProtoBaseAccount, maccPerms,
)
app.BankKeeper = bankkeeper.NewBaseKeeper(
appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.ModuleAccountAddrs(),
)
app.BankKeeper = bankpluskeeper.NewBaseKeeper(
appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.BlockedAddrs())
stakingKeeper := stakingkeeper.NewKeeper(
appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName),
)
Expand Down Expand Up @@ -352,7 +358,7 @@ func NewSimApp(
),
auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
bankplus.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants),
feegrant.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
Expand Down Expand Up @@ -405,7 +411,7 @@ func NewSimApp(
// transactions
app.sm = module.NewSimulationManager(
auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
bankplus.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
feegrant.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
Expand Down Expand Up @@ -450,6 +456,9 @@ func NewSimApp(
// `loadLatest` is set to true.
ctx := app.BaseApp.NewUncachedContext(true, ocproto.Header{})
app.CapabilityKeeper.InitializeAndSeal(ctx)

// Initialize the keeper of bankkeeper
app.BankKeeper.(bankpluskeeper.Keeper).InitializeBankPlus(ctx)
}

app.ScopedIBCKeeper = scopedIBCKeeper
Expand Down Expand Up @@ -508,6 +517,17 @@ func (app *SimApp) ModuleAccountAddrs() map[string]bool {
return modAccAddrs
}

// BlockedAddrs returns all the app's module account addresses that are not
// allowed to receive external tokens.
func (app *SimApp) BlockedAddrs() map[string]bool {
blockedAddrs := make(map[string]bool)
for acc := range maccPerms {
blockedAddrs[authtypes.NewModuleAddress(acc).String()] = !allowedReceivingModAcc[acc]
}

return blockedAddrs
}

// LegacyAmino returns SimApp's amino codec.
//
// NOTE: This is solely to be used for testing purposes as it may be desirable
Expand Down
8 changes: 4 additions & 4 deletions simapp/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ func TestSimAppExportAndBlockedAddrs(t *testing.T) {
app := NewSimApp(log.NewOCLogger(log.NewSyncWriter(os.Stdout)), db, nil, true, map[int64]bool{}, DefaultNodeHome, 0, encCfg, EmptyAppOptions{})

for acc := range maccPerms {
require.True(
t,
ex, _ := allowedReceivingModAcc[acc]
require.Equal(t,
!ex,
app.BankKeeper.BlockedAddr(app.AccountKeeper.GetModuleAddress(acc)),
"ensure that blocked addresses are properly set in bank keeper",
)
"ensure that blocked addresses are properly set in bank keeper")
}

genesisState := NewDefaultGenesisState(encCfg.Marshaler)
Expand Down
52 changes: 52 additions & 0 deletions x/bankplus/keeper/inactive.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package keeper

import (
sdk "github.com/line/lbm-sdk/types"
"github.com/line/lbm-sdk/x/bankplus/types"
)

// Keys for bankplus store but this prefix must not be overlap with bank key prefix.
var inactiveAddrsKeyPrefix = []byte{0xa0}

// inactiveAddrKey key of a specific inactiveAddr from store
func inactiveAddrKey(addr sdk.AccAddress) []byte {
return append(inactiveAddrsKeyPrefix, addr.Bytes()...)
}

//nolint:deadcode,unused
// isStoredInactiveAddr checks if the address is stored or not as blocked address
func (keeper BaseKeeper) isStoredInactiveAddr(ctx sdk.Context, address sdk.AccAddress) bool {
store := ctx.KVStore(keeper.storeKey)
bz := store.Get(inactiveAddrKey(address))
return bz != nil
}

// addToInactiveAddr adds a blocked address to the store.
func (keeper BaseKeeper) addToInactiveAddr(ctx sdk.Context, address sdk.AccAddress) {
store := ctx.KVStore(keeper.storeKey)
blockedCAddr := types.InactiveAddr{Address: address.String()}
bz := keeper.cdc.MustMarshalBinaryBare(&blockedCAddr)
store.Set(inactiveAddrKey(address), bz)
}

// deleteFromInactiveAddr deletes blocked address from store
func (keeper BaseKeeper) deleteFromInactiveAddr(ctx sdk.Context, address sdk.AccAddress) {
store := ctx.KVStore(keeper.storeKey)
store.Delete(inactiveAddrKey(address))
}

// loadAllInactiveAddrs loads all blocked address and set to `inactiveAddr`.
// This function is executed when the app is initiated and save all inactive address in caches
// in order to prevent to query to store in every time to send
func (keeper BaseKeeper) loadAllInactiveAddrs(ctx sdk.Context) {
store := ctx.KVStore(keeper.storeKey)
iterator := sdk.KVStorePrefixIterator(store, inactiveAddrsKeyPrefix)

defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
var bAddr types.InactiveAddr
keeper.cdc.MustUnmarshalBinaryBare(iterator.Value(), &bAddr)

keeper.inactiveAddrs[bAddr.Address] = true
}
}
79 changes: 79 additions & 0 deletions x/bankplus/keeper/inactive_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package keeper

import (
"github.com/line/lbm-sdk/codec"
codectypes "github.com/line/lbm-sdk/codec/types"
"github.com/line/lbm-sdk/store"
sdk "github.com/line/lbm-sdk/types"
accountkeeper "github.com/line/lbm-sdk/x/auth/keeper"
accounttypes "github.com/line/lbm-sdk/x/auth/types"
banktypes "github.com/line/lbm-sdk/x/bank/types"
paramtypes "github.com/line/lbm-sdk/x/params/types"
"github.com/line/ostracon/libs/log"
ostproto "github.com/line/ostracon/proto/ostracon/types"
"github.com/line/tm-db/v2/memdb"
"github.com/stretchr/testify/require"
"math/rand"
"testing"
)

func genAddress() sdk.AccAddress {
b := make([]byte, 20)
rand.Read(b)
return sdk.BytesToAccAddress(b)
}

func setupKeeper(storeKey *sdk.KVStoreKey) BaseKeeper {
registry := codectypes.NewInterfaceRegistry()
cdc := codec.NewProtoCodec(registry)
amino := codec.NewLegacyAmino()

accountStoreKey := sdk.NewKVStoreKey(accounttypes.StoreKey)
accountSubspace := paramtypes.NewSubspace(cdc, amino, accountStoreKey, accounttypes.ModuleName)
accountKeeper := accountkeeper.NewAccountKeeper(cdc, accountStoreKey, accountSubspace, accounttypes.ProtoBaseAccount, nil)

bankSubspace := paramtypes.NewSubspace(cdc, amino, storeKey, banktypes.StoreKey)
return NewBaseKeeper(cdc, storeKey, accountKeeper, bankSubspace, nil)
}

func setupContext(t *testing.T, storeKey *sdk.KVStoreKey) sdk.Context {
db := memdb.NewDB()
stateStore := store.NewCommitMultiStore(db)
stateStore.MountStoreWithDB(storeKey, sdk.StoreTypeIAVL, db)
require.NoError(t, stateStore.LoadLatestVersion())

return sdk.NewContext(stateStore, ostproto.Header{}, false, log.NewNopLogger())
}

func TestInactiveAddr(t *testing.T) {
storeKey := sdk.NewKVStoreKey(banktypes.StoreKey)
bankKeeper := setupKeeper(storeKey)
ctx := setupContext(t, storeKey)

addr := genAddress()

require.Equal(t, 0, len(bankKeeper.inactiveAddrs))

bankKeeper.addToInactiveAddr(ctx, addr)
require.True(t, bankKeeper.isStoredInactiveAddr(ctx, addr))

// duplicate addition, no error expects.
bankKeeper.addToInactiveAddr(ctx, addr)
require.True(t, bankKeeper.isStoredInactiveAddr(ctx, addr))

bankKeeper.deleteFromInactiveAddr(ctx, addr)
require.False(t, bankKeeper.isStoredInactiveAddr(ctx, addr))

addr2 := genAddress()
require.False(t, bankKeeper.isStoredInactiveAddr(ctx, addr2))

// expect no error
bankKeeper.deleteFromInactiveAddr(ctx, addr2)

// test loadAllInactiveAddrs
bankKeeper.addToInactiveAddr(ctx, addr)
bankKeeper.addToInactiveAddr(ctx, addr2)
require.Equal(t, 0, len(bankKeeper.inactiveAddrs))
bankKeeper.loadAllInactiveAddrs(ctx)
require.Equal(t, 2, len(bankKeeper.inactiveAddrs))
}
Loading

0 comments on commit cb1ad80

Please sign in to comment.