Skip to content

Commit

Permalink
Problem: no efficient way to collect fee
Browse files Browse the repository at this point in the history
Solution:
- support an idea of virtual account in bank module, where the incoming
  coins are accumulated in a per-tx object store first, then accumulate
  and credit to the real account at end blocker.

  it's nesserary to support parallel tx execution, where we try not to
  access shared states.

more efficient sum

support SendCoinsFromModuleToAccountVirtual

fix test

fix test

fix lint

fix test

fix test

fix test

fix test

fix test

fix mock keeper

try fix lint

try fix lint

reuse code

try fix linter

Update x/bank/keeper/send.go

Signed-off-by: yihuang <[email protected]>

algin panic call

fix error handling

try fix lint

nolintlint generate falst postiive
  • Loading branch information
yihuang committed Mar 28, 2024
1 parent 4d32911 commit f04a9c9
Show file tree
Hide file tree
Showing 24 changed files with 353 additions and 19 deletions.
1 change: 0 additions & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ linters:
- ineffassign
- misspell
- nakedret
- nolintlint
- staticcheck
- revive
- stylecheck
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Features

* (baseapp) [#205](https://github.com/crypto-org-chain/cosmos-sdk/pull/205) Add `TxExecutor` baseapp option, add `TxIndex`/`TxCount`/`MsgIndex`/`BlockGasUsed` fields to `Context, to support tx parallel execution.
* (baseapp) [#205](https://github.com/crypto-org-chain/cosmos-sdk/pull/205) Support mount object store in baseapp, add `ObjectStore` api in context..
* (baseapp) [#206](https://github.com/crypto-org-chain/cosmos-sdk/pull/206) Support mount object store in baseapp, add `ObjectStore` api in context..
* (bank) [#237](https://github.com/crypto-org-chain/cosmos-sdk/pull/237) Support virtual accounts in sending coins.

## [Unreleased-Upstream]

Expand Down
3 changes: 3 additions & 0 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,9 @@ func (app *BaseApp) MountStores(keys ...storetypes.StoreKey) {
case *storetypes.MemoryStoreKey:
app.MountStore(key, storetypes.StoreTypeMemory)

case *storetypes.ObjectStoreKey:
app.MountStore(key, storetypes.StoreTypeObject)

default:
panic(fmt.Sprintf("Unrecognized store key type :%T", key))
}
Expand Down
7 changes: 7 additions & 0 deletions runtime/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func init() {
ProvideKVStoreKey,
ProvideTransientStoreKey,
ProvideMemoryStoreKey,
ProvideObjectStoreKey,
ProvideGenesisTxHandler,
ProvideKVStoreService,
ProvideMemoryStoreService,
Expand Down Expand Up @@ -222,6 +223,12 @@ func ProvideMemoryStoreKey(key depinject.ModuleKey, app *AppBuilder) *storetypes
return storeKey
}

func ProvideObjectStoreKey(key depinject.ModuleKey, app *AppBuilder) *storetypes.ObjectStoreKey {
storeKey := storetypes.NewObjectStoreKey(fmt.Sprintf("object:%s", key.Name()))
registerStoreKey(app, storeKey)
return storeKey
}

func ProvideGenesisTxHandler(appBuilder *AppBuilder) genesis.TxHandler {
return appBuilder.app
}
Expand Down
6 changes: 6 additions & 0 deletions simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ type SimApp struct {
// keys to access the substores
keys map[string]*storetypes.KVStoreKey
tkeys map[string]*storetypes.TransientStoreKey
okeys map[string]*storetypes.ObjectStoreKey

// keepers
AccountKeeper authkeeper.AccountKeeper
Expand Down Expand Up @@ -266,6 +267,7 @@ func NewSimApp(
}

tkeys := storetypes.NewTransientStoreKeys(paramstypes.TStoreKey)
okeys := storetypes.NewObjectStoreKeys(banktypes.ObjectStoreKey)
app := &SimApp{
BaseApp: bApp,
legacyAmino: legacyAmino,
Expand All @@ -274,6 +276,7 @@ func NewSimApp(
interfaceRegistry: interfaceRegistry,
keys: keys,
tkeys: tkeys,
okeys: okeys,
}

app.ParamsKeeper = initParamsKeeper(appCodec, legacyAmino, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])
Expand All @@ -288,6 +291,7 @@ func NewSimApp(
app.BankKeeper = bankkeeper.NewBaseKeeper(
appCodec,
runtime.NewKVStoreService(keys[banktypes.StoreKey]),
okeys[banktypes.ObjectStoreKey],
app.AccountKeeper,
BlockedAddresses(),
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
Expand Down Expand Up @@ -456,6 +460,7 @@ func NewSimApp(
authz.ModuleName,
)
app.ModuleManager.SetOrderEndBlockers(
banktypes.ModuleName,
crisistypes.ModuleName,
govtypes.ModuleName,
stakingtypes.ModuleName,
Expand Down Expand Up @@ -516,6 +521,7 @@ func NewSimApp(
// initialize stores
app.MountKVStores(keys)
app.MountTransientStores(tkeys)
app.MountObjectStores(okeys)

// initialize BaseApp
app.SetInitChainer(app.InitChainer)
Expand Down
1 change: 1 addition & 0 deletions simapp/app_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ var (
authz.ModuleName,
},
EndBlockers: []string{
banktypes.ModuleName,
crisistypes.ModuleName,
govtypes.ModuleName,
stakingtypes.ModuleName,
Expand Down
4 changes: 3 additions & 1 deletion tests/integration/bank/keeper/deterministic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,11 @@ type deterministicFixture struct {

func initDeterministicFixture(t *testing.T) *deterministicFixture {
keys := storetypes.NewKVStoreKeys(authtypes.StoreKey, banktypes.StoreKey)
okeys := storetypes.NewObjectStoreKeys(banktypes.ObjectStoreKey)
cdc := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, bank.AppModuleBasic{}).Codec

logger := log.NewTestLogger(t)
cms := integration.CreateMultiStore(keys, logger)
cms := integration.CreateMultiStore(keys, okeys, logger)

newCtx := sdk.NewContext(cms, cmtproto.Header{}, true, logger)

Expand All @@ -93,6 +94,7 @@ func initDeterministicFixture(t *testing.T) *deterministicFixture {
bankKeeper := keeper.NewBaseKeeper(
cdc,
runtime.NewKVStoreService(keys[banktypes.StoreKey]),
okeys[banktypes.ObjectStoreKey],
accountKeeper,
blockedAddresses,
authority.String(),
Expand Down
6 changes: 5 additions & 1 deletion tests/integration/distribution/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,13 @@ func initFixture(t testing.TB) *fixture {
keys := storetypes.NewKVStoreKeys(
authtypes.StoreKey, banktypes.StoreKey, distrtypes.StoreKey, stakingtypes.StoreKey,
)
okeys := storetypes.NewObjectStoreKeys(
banktypes.ObjectStoreKey,
)
cdc := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, distribution.AppModuleBasic{}).Codec

logger := log.NewTestLogger(t)
cms := integration.CreateMultiStore(keys, logger)
cms := integration.CreateMultiStore(keys, okeys, logger)

newCtx := sdk.NewContext(cms, types.Header{}, true, logger)

Expand Down Expand Up @@ -92,6 +95,7 @@ func initFixture(t testing.TB) *fixture {
bankKeeper := bankkeeper.NewBaseKeeper(
cdc,
runtime.NewKVStoreService(keys[banktypes.StoreKey]),
okeys[banktypes.ObjectStoreKey],
accountKeeper,
blockedAddresses,
authority.String(),
Expand Down
6 changes: 5 additions & 1 deletion tests/integration/evidence/keeper/infraction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,13 @@ func initFixture(t testing.TB) *fixture {
keys := storetypes.NewKVStoreKeys(
authtypes.StoreKey, banktypes.StoreKey, paramtypes.StoreKey, consensusparamtypes.StoreKey, evidencetypes.StoreKey, stakingtypes.StoreKey, slashingtypes.StoreKey,
)
okeys := storetypes.NewObjectStoreKeys(
banktypes.ObjectStoreKey,
)
cdc := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, evidence.AppModuleBasic{}).Codec

logger := log.NewTestLogger(t)
cms := integration.CreateMultiStore(keys, logger)
cms := integration.CreateMultiStore(keys, okeys, logger)

newCtx := sdk.NewContext(cms, cmtproto.Header{}, true, logger)

Expand Down Expand Up @@ -114,6 +117,7 @@ func initFixture(t testing.TB) *fixture {
bankKeeper := bankkeeper.NewBaseKeeper(
cdc,
runtime.NewKVStoreService(keys[banktypes.StoreKey]),
okeys[banktypes.ObjectStoreKey],
accountKeeper,
blockedAddresses,
authority.String(),
Expand Down
6 changes: 5 additions & 1 deletion tests/integration/gov/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,13 @@ func initFixture(t testing.TB) *fixture {
keys := storetypes.NewKVStoreKeys(
authtypes.StoreKey, banktypes.StoreKey, distrtypes.StoreKey, stakingtypes.StoreKey, types.StoreKey,
)
okeys := storetypes.NewObjectStoreKeys(
banktypes.ObjectStoreKey,
)
cdc := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, bank.AppModuleBasic{}, gov.AppModuleBasic{}).Codec

logger := log.NewTestLogger(t)
cms := integration.CreateMultiStore(keys, logger)
cms := integration.CreateMultiStore(keys, okeys, logger)

newCtx := sdk.NewContext(cms, cmtproto.Header{}, true, logger)

Expand Down Expand Up @@ -85,6 +88,7 @@ func initFixture(t testing.TB) *fixture {
bankKeeper := bankkeeper.NewBaseKeeper(
cdc,
runtime.NewKVStoreService(keys[banktypes.StoreKey]),
okeys[banktypes.ObjectStoreKey],
accountKeeper,
blockedAddresses,
authority.String(),
Expand Down
4 changes: 3 additions & 1 deletion tests/integration/slashing/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,11 @@ func initFixture(t testing.TB) *fixture {
keys := storetypes.NewKVStoreKeys(
authtypes.StoreKey, banktypes.StoreKey, slashingtypes.StoreKey, stakingtypes.StoreKey,
)
okeys := storetypes.NewObjectStoreKeys(banktypes.ObjectStoreKey)
cdc := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}).Codec

logger := log.NewTestLogger(t)
cms := integration.CreateMultiStore(keys, logger)
cms := integration.CreateMultiStore(keys, okeys, logger)

newCtx := sdk.NewContext(cms, cmtproto.Header{}, true, logger)

Expand Down Expand Up @@ -85,6 +86,7 @@ func initFixture(t testing.TB) *fixture {
bankKeeper := bankkeeper.NewBaseKeeper(
cdc,
runtime.NewKVStoreService(keys[banktypes.StoreKey]),
okeys[banktypes.ObjectStoreKey],
accountKeeper,
blockedAddresses,
authority.String(),
Expand Down
6 changes: 5 additions & 1 deletion tests/integration/staking/keeper/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,13 @@ func initFixture(t testing.TB) *fixture {
keys := storetypes.NewKVStoreKeys(
authtypes.StoreKey, banktypes.StoreKey, types.StoreKey,
)
okeys := storetypes.NewObjectStoreKeys(
banktypes.ObjectStoreKey,
)
cdc := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, staking.AppModuleBasic{}).Codec

logger := log.NewTestLogger(t)
cms := integration.CreateMultiStore(keys, logger)
cms := integration.CreateMultiStore(keys, okeys, logger)

newCtx := sdk.NewContext(cms, cmtprototypes.Header{}, true, logger)

Expand Down Expand Up @@ -127,6 +130,7 @@ func initFixture(t testing.TB) *fixture {
bankKeeper := bankkeeper.NewBaseKeeper(
cdc,
runtime.NewKVStoreService(keys[banktypes.StoreKey]),
okeys[banktypes.ObjectStoreKey],
accountKeeper,
blockedAddresses,
authority.String(),
Expand Down
4 changes: 3 additions & 1 deletion tests/integration/staking/keeper/determinstic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,11 @@ func initDeterministicFixture(t *testing.T) *deterministicFixture {
keys := storetypes.NewKVStoreKeys(
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey,
)
okeys := storetypes.NewObjectStoreKeys(banktypes.ObjectStoreKey)
cdc := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, distribution.AppModuleBasic{}).Codec

logger := log.NewTestLogger(t)
cms := integration.CreateMultiStore(keys, logger)
cms := integration.CreateMultiStore(keys, okeys, logger)

newCtx := sdk.NewContext(cms, cmtproto.Header{}, true, logger)

Expand Down Expand Up @@ -100,6 +101,7 @@ func initDeterministicFixture(t *testing.T) *deterministicFixture {
bankKeeper := bankkeeper.NewBaseKeeper(
cdc,
runtime.NewKVStoreService(keys[banktypes.StoreKey]),
okeys[banktypes.ObjectStoreKey],
accountKeeper,
blockedAddresses,
authority.String(),
Expand Down
14 changes: 14 additions & 0 deletions testutil/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,17 @@ func DefaultContextWithDB(t testing.TB, key, tkey storetypes.StoreKey) TestConte

return TestContext{ctx, db, cms}
}

func DefaultContextWithObjectStore(t testing.TB, key, tkey, okey storetypes.StoreKey) TestContext {
db := dbm.NewMemDB()
cms := store.NewCommitMultiStore(db, log.NewNopLogger(), metrics.NewNoOpMetrics())
cms.MountStoreWithDB(key, storetypes.StoreTypeIAVL, db)
cms.MountStoreWithDB(tkey, storetypes.StoreTypeTransient, nil)
cms.MountStoreWithDB(okey, storetypes.StoreTypeObject, nil)
err := cms.LoadLatestVersion()
assert.NoError(t, err)

ctx := sdk.NewContext(cms, cmtproto.Header{Time: time.Now()}, false, log.NewNopLogger())

return TestContext{ctx, db, cms}
}
4 changes: 2 additions & 2 deletions testutil/integration/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func Example() {
// replace the logger by testing values in a real test case (e.g. log.NewTestLogger(t))
logger := log.NewNopLogger()

cms := integration.CreateMultiStore(keys, logger)
cms := integration.CreateMultiStore(keys, nil, logger)
newCtx := sdk.NewContext(cms, cmtproto.Header{}, true, logger)

accountKeeper := authkeeper.NewAccountKeeper(
Expand Down Expand Up @@ -126,7 +126,7 @@ func Example_oneModule() {
// replace the logger by testing values in a real test case (e.g. log.NewTestLogger(t))
logger := log.NewLogger(io.Discard)

cms := integration.CreateMultiStore(keys, logger)
cms := integration.CreateMultiStore(keys, nil, logger)
newCtx := sdk.NewContext(cms, cmtproto.Header{}, true, logger)

accountKeeper := authkeeper.NewAccountKeeper(
Expand Down
6 changes: 5 additions & 1 deletion testutil/integration/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,14 +177,18 @@ func (app *App) QueryHelper() *baseapp.QueryServiceTestHelper {
}

// CreateMultiStore is a helper for setting up multiple stores for provided modules.
func CreateMultiStore(keys map[string]*storetypes.KVStoreKey, logger log.Logger) storetypes.CommitMultiStore {
func CreateMultiStore(keys map[string]*storetypes.KVStoreKey, okeys map[string]*storetypes.ObjectStoreKey, logger log.Logger) storetypes.CommitMultiStore {
db := dbm.NewMemDB()
cms := store.NewCommitMultiStore(db, logger, metrics.NewNoOpMetrics())

for key := range keys {
cms.MountStoreWithDB(keys[key], storetypes.StoreTypeIAVL, db)
}

for key := range okeys {
cms.MountStoreWithDB(okeys[key], storetypes.StoreTypeObject, nil)
}

Check warning

Code scanning / CodeQL

Iteration over map Warning test

Iteration over map may be a possible source of non-determinism

_ = cms.LoadLatestVersion()
return cms
}
4 changes: 3 additions & 1 deletion x/bank/keeper/collections_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ import (

func TestBankStateCompatibility(t *testing.T) {
key := storetypes.NewKVStoreKey(banktypes.StoreKey)
testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test"))
okey := storetypes.NewObjectStoreKey(banktypes.ObjectStoreKey)
testCtx := testutil.DefaultContextWithObjectStore(t, key, storetypes.NewTransientStoreKey("transient_test"), okey)
ctx := testCtx.Ctx.WithBlockHeader(cmtproto.Header{Time: cmttime.Now()})
encCfg := moduletestutil.MakeTestEncodingConfig()

Expand All @@ -40,6 +41,7 @@ func TestBankStateCompatibility(t *testing.T) {
k := keeper.NewBaseKeeper(
encCfg.Codec,
storeService,
okey,
authKeeper,
map[string]bool{accAddrs[4].String(): true},
authtypes.NewModuleAddress("gov").String(),
Expand Down
9 changes: 8 additions & 1 deletion x/bank/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
errorsmod "cosmossdk.io/errors"
"cosmossdk.io/log"
"cosmossdk.io/math"
storetypes "cosmossdk.io/store/types"

"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -46,9 +47,14 @@ type Keeper interface {
MintCoins(ctx context.Context, moduleName string, amt sdk.Coins) error
BurnCoins(ctx context.Context, moduleName string, amt sdk.Coins) error

SendCoinsFromAccountToModuleVirtual(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error
SendCoinsFromModuleToAccountVirtual(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error

DelegateCoins(ctx context.Context, delegatorAddr, moduleAccAddr sdk.AccAddress, amt sdk.Coins) error
UndelegateCoins(ctx context.Context, moduleAccAddr, delegatorAddr sdk.AccAddress, amt sdk.Coins) error

CreditVirtualAccounts(ctx context.Context) error

types.QueryServer
}

Expand Down Expand Up @@ -84,6 +90,7 @@ func (k BaseKeeper) GetPaginatedTotalSupply(ctx context.Context, pagination *que
func NewBaseKeeper(
cdc codec.BinaryCodec,
storeService store.KVStoreService,
objStoreKey storetypes.StoreKey,
ak types.AccountKeeper,
blockedAddrs map[string]bool,
authority string,
Expand All @@ -97,7 +104,7 @@ func NewBaseKeeper(
logger = logger.With(log.ModuleKey, "x/"+types.ModuleName)

return BaseKeeper{
BaseSendKeeper: NewBaseSendKeeper(cdc, storeService, ak, blockedAddrs, authority, logger),
BaseSendKeeper: NewBaseSendKeeper(cdc, storeService, objStoreKey, ak, blockedAddrs, authority, logger),
ak: ak,
cdc: cdc,
storeService: storeService,
Expand Down
Loading

0 comments on commit f04a9c9

Please sign in to comment.