refactor(testutil): Removing testutil integration (#23091)
This commit is contained in:
parent
dafa93f05d
commit
4fb2347af4
@ -1,87 +0,0 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
minttypes "cosmossdk.io/x/mint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
srvconfig "github.com/cosmos/cosmos-sdk/server/config"
|
||||
servergrpc "github.com/cosmos/cosmos-sdk/server/grpc"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
func TestAccountRetriever(t *testing.T) {
|
||||
t.Skip() // TODO: https://github.com/cosmos/cosmos-sdk/issues/22825
|
||||
|
||||
f := initFixture(t, nil)
|
||||
|
||||
grpcSrv := grpc.NewServer(grpc.ForceServerCodec(codec.NewProtoCodec(f.encodingCfg.InterfaceRegistry).GRPCCodec()))
|
||||
|
||||
types.RegisterQueryServer(f.app.GRPCQueryRouter(), keeper.NewQueryServer(f.authKeeper))
|
||||
f.app.RegisterGRPCServer(grpcSrv)
|
||||
|
||||
grpcCfg := srvconfig.DefaultConfig().GRPC
|
||||
|
||||
go func() {
|
||||
require.NoError(t, servergrpc.StartGRPCServer(context.Background(), f.app.Logger(), grpcCfg, grpcSrv))
|
||||
}()
|
||||
|
||||
conn, err := grpc.NewClient(
|
||||
grpcCfg.Address,
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithDefaultCallOptions(grpc.ForceCodec(codec.NewProtoCodec(f.encodingCfg.InterfaceRegistry).GRPCCodec())),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
pubkeys := simtestutil.CreateTestPubKeys(1)
|
||||
addr := sdk.AccAddress(pubkeys[0].Address())
|
||||
|
||||
newAcc := types.BaseAccount{
|
||||
Address: addr.String(),
|
||||
PubKey: nil,
|
||||
AccountNumber: 2,
|
||||
Sequence: 7,
|
||||
}
|
||||
|
||||
updatedAcc := f.authKeeper.NewAccount(f.ctx, &newAcc)
|
||||
f.authKeeper.SetAccount(f.ctx, updatedAcc)
|
||||
|
||||
amount := sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10000)))
|
||||
require.NoError(t, f.bankKeeper.MintCoins(f.ctx, minttypes.ModuleName, amount))
|
||||
require.NoError(t, f.bankKeeper.SendCoinsFromModuleToAccount(f.ctx, minttypes.ModuleName, addr, amount))
|
||||
|
||||
ar := types.AccountRetriever{}
|
||||
|
||||
clientCtx := client.Context{}.
|
||||
WithGRPCClient(conn).
|
||||
WithAddressPrefix(sdk.Bech32MainPrefix)
|
||||
|
||||
acc, err := ar.GetAccount(clientCtx, addr)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, acc)
|
||||
|
||||
acc, height, err := ar.GetAccountWithHeight(clientCtx, addr)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, acc)
|
||||
require.Equal(t, height, int64(2))
|
||||
|
||||
require.NoError(t, ar.EnsureExists(clientCtx, addr))
|
||||
|
||||
accNum, accSeq, err := ar.GetAccountNumberSequence(clientCtx, addr)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, accNum, uint64(0))
|
||||
require.Equal(t, accSeq, uint64(1))
|
||||
}
|
||||
@ -1,157 +0,0 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
gogotypes "github.com/cosmos/gogoproto/types"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"cosmossdk.io/x/accounts/accountstd"
|
||||
basev1 "cosmossdk.io/x/accounts/defaults/base/v1"
|
||||
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
var _ accountstd.Interface = mockRetroCompatAccount{}
|
||||
|
||||
type mockRetroCompatAccount struct {
|
||||
retroCompat *authtypes.QueryLegacyAccountResponse
|
||||
address []byte
|
||||
}
|
||||
|
||||
func (m mockRetroCompatAccount) RegisterInitHandler(builder *accountstd.InitBuilder) {
|
||||
accountstd.RegisterInitHandler(builder, func(ctx context.Context, req *gogotypes.Empty) (*gogotypes.Empty, error) {
|
||||
return &gogotypes.Empty{}, nil
|
||||
})
|
||||
}
|
||||
|
||||
func (m mockRetroCompatAccount) RegisterExecuteHandlers(_ *accountstd.ExecuteBuilder) {}
|
||||
|
||||
func (m mockRetroCompatAccount) RegisterQueryHandlers(builder *accountstd.QueryBuilder) {
|
||||
if m.retroCompat == nil {
|
||||
return
|
||||
}
|
||||
accountstd.RegisterQueryHandler(builder, func(ctx context.Context, req *authtypes.QueryLegacyAccount) (*authtypes.QueryLegacyAccountResponse, error) {
|
||||
return m.retroCompat, nil
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthToAccountsGRPCCompat(t *testing.T) {
|
||||
valid := &mockRetroCompatAccount{
|
||||
retroCompat: &authtypes.QueryLegacyAccountResponse{
|
||||
Account: &codectypes.Any{},
|
||||
Base: &authtypes.BaseAccount{
|
||||
Address: "test",
|
||||
PubKey: nil,
|
||||
AccountNumber: 10,
|
||||
Sequence: 20,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
noInfo := &mockRetroCompatAccount{
|
||||
retroCompat: &authtypes.QueryLegacyAccountResponse{
|
||||
Account: &codectypes.Any{},
|
||||
},
|
||||
}
|
||||
noImplement := &mockRetroCompatAccount{
|
||||
retroCompat: nil,
|
||||
}
|
||||
|
||||
accs := map[string]accountstd.Interface{
|
||||
"valid": valid,
|
||||
"no_info": noInfo,
|
||||
"no_implement": noImplement,
|
||||
}
|
||||
|
||||
f := initFixture(t, accs)
|
||||
|
||||
// init three accounts
|
||||
for n, a := range accs {
|
||||
_, addr, err := f.accountsKeeper.Init(f.app.Context(), n, []byte("me"), &gogotypes.Empty{}, nil, nil)
|
||||
require.NoError(t, err)
|
||||
a.(*mockRetroCompatAccount).address = addr
|
||||
}
|
||||
|
||||
qs := authkeeper.NewQueryServer(f.authKeeper)
|
||||
|
||||
t.Run("account supports info and account query", func(t *testing.T) {
|
||||
infoResp, err := qs.AccountInfo(f.app.Context(), &authtypes.QueryAccountInfoRequest{
|
||||
Address: f.mustAddr(valid.address),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, infoResp.Info, valid.retroCompat.Base)
|
||||
|
||||
accountResp, err := qs.Account(f.app.Context(), &authtypes.QueryAccountRequest{
|
||||
Address: f.mustAddr(noInfo.address),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, accountResp.Account, valid.retroCompat.Account)
|
||||
})
|
||||
|
||||
t.Run("account only supports account query, not info", func(t *testing.T) {
|
||||
_, err := qs.AccountInfo(f.app.Context(), &authtypes.QueryAccountInfoRequest{
|
||||
Address: f.mustAddr(noInfo.address),
|
||||
})
|
||||
require.Error(t, err)
|
||||
require.Equal(t, status.Code(err), codes.NotFound)
|
||||
|
||||
resp, err := qs.Account(f.app.Context(), &authtypes.QueryAccountRequest{
|
||||
Address: f.mustAddr(noInfo.address),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, resp.Account, valid.retroCompat.Account)
|
||||
})
|
||||
|
||||
t.Run("account does not support any retro compat", func(t *testing.T) {
|
||||
_, err := qs.AccountInfo(f.app.Context(), &authtypes.QueryAccountInfoRequest{
|
||||
Address: f.mustAddr(noImplement.address),
|
||||
})
|
||||
require.Error(t, err)
|
||||
require.Equal(t, status.Code(err), codes.NotFound)
|
||||
|
||||
_, err = qs.Account(f.app.Context(), &authtypes.QueryAccountRequest{
|
||||
Address: f.mustAddr(noImplement.address),
|
||||
})
|
||||
|
||||
require.Error(t, err)
|
||||
require.Equal(t, status.Code(err), codes.NotFound)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccountsBaseAccountRetroCompat(t *testing.T) {
|
||||
f := initFixture(t, nil)
|
||||
// init a base acc
|
||||
anyPk, err := codectypes.NewAnyWithValue(secp256k1.GenPrivKey().PubKey())
|
||||
require.NoError(t, err)
|
||||
|
||||
// we init two accounts to have account num not be zero.
|
||||
_, _, err = f.accountsKeeper.Init(f.app.Context(), "base", []byte("me"), &basev1.MsgInit{PubKey: anyPk}, nil, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, addr, err := f.accountsKeeper.Init(f.app.Context(), "base", []byte("me"), &basev1.MsgInit{PubKey: anyPk}, nil, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
// try to query it via auth
|
||||
qs := authkeeper.NewQueryServer(f.authKeeper)
|
||||
|
||||
r, err := qs.Account(f.app.Context(), &authtypes.QueryAccountRequest{
|
||||
Address: f.mustAddr(addr),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, r.Account)
|
||||
|
||||
info, err := qs.AccountInfo(f.app.Context(), &authtypes.QueryAccountInfoRequest{
|
||||
Address: f.mustAddr(addr),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, info.Info)
|
||||
require.Equal(t, info.Info.PubKey, anyPk)
|
||||
require.Equal(t, info.Info.AccountNumber, uint64(1))
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
_ "cosmossdk.io/x/accounts" // import as blank for app wiring
|
||||
_ "cosmossdk.io/x/bank" // import as blank for app wiring
|
||||
_ "cosmossdk.io/x/consensus" // import as blank for app wiring
|
||||
_ "cosmossdk.io/x/staking" // import as blank for app wiring
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/testutil/configurator"
|
||||
_ "github.com/cosmos/cosmos-sdk/x/auth" // import as blank for app wiring
|
||||
_ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import as blank for app wiring``
|
||||
_ "github.com/cosmos/cosmos-sdk/x/auth/vesting" // import as blank for app wiring
|
||||
_ "github.com/cosmos/cosmos-sdk/x/genutil" // import as blank for app wiring
|
||||
)
|
||||
|
||||
var AppConfig = configurator.NewAppConfig(
|
||||
configurator.AccountsModule(),
|
||||
configurator.AuthModule(),
|
||||
configurator.BankModule(),
|
||||
configurator.VestingModule(),
|
||||
configurator.StakingModule(),
|
||||
configurator.TxModule(),
|
||||
configurator.ValidateModule(),
|
||||
configurator.ConsensusModule(),
|
||||
configurator.GenutilModule(),
|
||||
)
|
||||
@ -1,153 +0,0 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
cmtabcitypes "github.com/cometbft/cometbft/api/cometbft/abci/v1"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gotest.tools/v3/assert"
|
||||
|
||||
"cosmossdk.io/core/appmodule"
|
||||
"cosmossdk.io/log"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
"cosmossdk.io/x/accounts"
|
||||
"cosmossdk.io/x/accounts/accountstd"
|
||||
baseaccount "cosmossdk.io/x/accounts/defaults/base"
|
||||
accountsv1 "cosmossdk.io/x/accounts/v1"
|
||||
"cosmossdk.io/x/bank"
|
||||
bankkeeper "cosmossdk.io/x/bank/keeper"
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
minttypes "cosmossdk.io/x/mint/types"
|
||||
"cosmossdk.io/x/tx/signing"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
|
||||
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/integration"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
type fixture struct {
|
||||
app *integration.App
|
||||
|
||||
cdc codec.Codec
|
||||
ctx sdk.Context
|
||||
encodingCfg moduletestutil.TestEncodingConfig
|
||||
|
||||
authKeeper authkeeper.AccountKeeper
|
||||
accountsKeeper accounts.Keeper
|
||||
bankKeeper bankkeeper.Keeper
|
||||
}
|
||||
|
||||
func (f fixture) mustAddr(address []byte) string {
|
||||
s, _ := f.authKeeper.AddressCodec().BytesToString(address)
|
||||
return s
|
||||
}
|
||||
|
||||
func initFixture(t *testing.T, extraAccs map[string]accountstd.Interface) *fixture {
|
||||
t.Helper()
|
||||
keys := storetypes.NewKVStoreKeys(
|
||||
authtypes.StoreKey, banktypes.StoreKey, accounts.StoreKey,
|
||||
)
|
||||
encodingCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{}, bank.AppModule{}, accounts.AppModule{})
|
||||
cdc := encodingCfg.Codec
|
||||
|
||||
logger := log.NewTestLogger(t)
|
||||
|
||||
router := baseapp.NewMsgServiceRouter()
|
||||
queryRouter := baseapp.NewGRPCQueryRouter()
|
||||
|
||||
handler := directHandler{}
|
||||
account := baseaccount.NewAccount("base", signing.NewHandlerMap(handler), baseaccount.WithSecp256K1PubKey())
|
||||
|
||||
var accs []accountstd.AccountCreatorFunc
|
||||
for name, acc := range extraAccs {
|
||||
f := accountstd.AddAccount(name, func(_ accountstd.Dependencies) (accountstd.Interface, error) {
|
||||
return acc, nil
|
||||
})
|
||||
accs = append(accs, f)
|
||||
}
|
||||
accountsKeeper, err := accounts.NewKeeper(
|
||||
cdc,
|
||||
runtime.NewEnvironment(runtime.NewKVStoreService(keys[accounts.StoreKey]), log.NewNopLogger(), runtime.EnvWithQueryRouterService(queryRouter), runtime.EnvWithMsgRouterService(router)),
|
||||
addresscodec.NewBech32Codec("cosmos"),
|
||||
cdc.InterfaceRegistry(),
|
||||
nil,
|
||||
append(accs, account)...,
|
||||
)
|
||||
assert.NilError(t, err)
|
||||
accountsv1.RegisterQueryServer(queryRouter, accounts.NewQueryServer(accountsKeeper))
|
||||
|
||||
authority := authtypes.NewModuleAddress("gov")
|
||||
|
||||
authKeeper := authkeeper.NewAccountKeeper(
|
||||
runtime.NewEnvironment(runtime.NewKVStoreService(keys[authtypes.StoreKey]), log.NewNopLogger()),
|
||||
cdc,
|
||||
authtypes.ProtoBaseAccount,
|
||||
accountsKeeper,
|
||||
map[string][]string{minttypes.ModuleName: {authtypes.Minter}},
|
||||
addresscodec.NewBech32Codec(sdk.Bech32MainPrefix),
|
||||
sdk.Bech32MainPrefix,
|
||||
authority.String(),
|
||||
)
|
||||
|
||||
blockedAddresses := map[string]bool{
|
||||
authKeeper.GetAuthority(): false,
|
||||
}
|
||||
bankKeeper := bankkeeper.NewBaseKeeper(
|
||||
runtime.NewEnvironment(runtime.NewKVStoreService(keys[banktypes.StoreKey]), log.NewNopLogger()),
|
||||
cdc,
|
||||
authKeeper,
|
||||
blockedAddresses,
|
||||
authority.String(),
|
||||
)
|
||||
|
||||
accountsModule := accounts.NewAppModule(cdc, accountsKeeper)
|
||||
authModule := auth.NewAppModule(cdc, authKeeper, accountsKeeper, authsims.RandomGenesisAccounts, nil)
|
||||
bankModule := bank.NewAppModule(cdc, bankKeeper, authKeeper)
|
||||
|
||||
integrationApp := integration.NewIntegrationApp(logger, keys, cdc,
|
||||
encodingCfg.InterfaceRegistry.SigningContext().AddressCodec(),
|
||||
encodingCfg.InterfaceRegistry.SigningContext().ValidatorAddressCodec(),
|
||||
map[string]appmodule.AppModule{
|
||||
accounts.ModuleName: accountsModule,
|
||||
authtypes.ModuleName: authModule,
|
||||
banktypes.ModuleName: bankModule,
|
||||
}, router, queryRouter)
|
||||
|
||||
authtypes.RegisterInterfaces(cdc.InterfaceRegistry())
|
||||
banktypes.RegisterInterfaces(cdc.InterfaceRegistry())
|
||||
|
||||
authtypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), authkeeper.NewMsgServerImpl(authKeeper))
|
||||
authtypes.RegisterQueryServer(integrationApp.QueryHelper(), authkeeper.NewQueryServer(authKeeper))
|
||||
|
||||
banktypes.RegisterMsgServer(router, bankkeeper.NewMsgServerImpl(bankKeeper))
|
||||
|
||||
// commit and finalize block
|
||||
defer func() {
|
||||
_, err := integrationApp.Commit()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
height := integrationApp.LastBlockHeight() + 1
|
||||
_, err = integrationApp.FinalizeBlock(&cmtabcitypes.FinalizeBlockRequest{Height: height, DecidedLastCommit: cmtabcitypes.CommitInfo{Votes: []cmtabcitypes.VoteInfo{{}}}})
|
||||
require.NoError(t, err)
|
||||
|
||||
return &fixture{
|
||||
app: integrationApp,
|
||||
cdc: cdc,
|
||||
ctx: sdk.UnwrapSDKContext(integrationApp.Context()),
|
||||
accountsKeeper: accountsKeeper,
|
||||
authKeeper: authKeeper,
|
||||
bankKeeper: bankKeeper,
|
||||
encodingCfg: encodingCfg,
|
||||
}
|
||||
}
|
||||
@ -1,67 +0,0 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/log"
|
||||
|
||||
authTest "github.com/cosmos/cosmos-sdk/tests/integration/auth/keeper"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
)
|
||||
|
||||
func BenchmarkAccountMapperGetAccountFound(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
var accountKeeper keeper.AccountKeeper
|
||||
app, err := simtestutil.Setup(
|
||||
depinject.Configs(
|
||||
depinject.Supply(log.NewNopLogger()),
|
||||
authTest.AppConfig,
|
||||
),
|
||||
&accountKeeper,
|
||||
)
|
||||
require.NoError(b, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false)
|
||||
|
||||
// assumes b.N < 2**24
|
||||
for i := 0; i < b.N; i++ {
|
||||
arr := []byte{byte((i & 0xFF0000) >> 16), byte((i & 0xFF00) >> 8), byte(i & 0xFF)}
|
||||
addr := sdk.AccAddress(arr)
|
||||
acc := accountKeeper.NewAccountWithAddress(ctx, addr)
|
||||
accountKeeper.SetAccount(ctx, acc)
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
arr := []byte{byte((i & 0xFF0000) >> 16), byte((i & 0xFF00) >> 8), byte(i & 0xFF)}
|
||||
accountKeeper.GetAccount(ctx, sdk.AccAddress(arr))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAccountMapperSetAccount(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
var accountKeeper keeper.AccountKeeper
|
||||
app, err := simtestutil.Setup(
|
||||
depinject.Configs(
|
||||
depinject.Supply(log.NewNopLogger()),
|
||||
authTest.AppConfig,
|
||||
), &accountKeeper)
|
||||
require.NoError(b, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false)
|
||||
|
||||
b.ResetTimer()
|
||||
|
||||
// assumes b.N < 2**24
|
||||
for i := 0; i < b.N; i++ {
|
||||
arr := []byte{byte((i & 0xFF0000) >> 16), byte((i & 0xFF00) >> 8), byte(i & 0xFF)}
|
||||
addr := sdk.AccAddress(arr)
|
||||
acc := accountKeeper.NewAccountWithAddress(ctx, addr)
|
||||
accountKeeper.SetAccount(ctx, acc)
|
||||
}
|
||||
}
|
||||
@ -1,100 +0,0 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
basev1 "cosmossdk.io/x/accounts/defaults/base/v1"
|
||||
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
func TestMigrateToAccounts(t *testing.T) {
|
||||
f := initFixture(t, nil)
|
||||
|
||||
// create a module account
|
||||
modAcc := &authtypes.ModuleAccount{
|
||||
BaseAccount: &authtypes.BaseAccount{
|
||||
Address: f.mustAddr([]byte("cookies")),
|
||||
PubKey: nil,
|
||||
AccountNumber: 0,
|
||||
Sequence: 0,
|
||||
},
|
||||
Name: "cookies",
|
||||
Permissions: nil,
|
||||
}
|
||||
updatedMod := f.authKeeper.NewAccount(f.app.Context(), modAcc)
|
||||
f.authKeeper.SetAccount(f.app.Context(), updatedMod)
|
||||
|
||||
// create account
|
||||
msgSrv := authkeeper.NewMsgServerImpl(f.authKeeper)
|
||||
privKey := secp256k1.GenPrivKey()
|
||||
addr := sdk.AccAddress(privKey.PubKey().Address())
|
||||
|
||||
acc := f.authKeeper.NewAccountWithAddress(f.app.Context(), addr)
|
||||
require.NoError(t, acc.SetPubKey(privKey.PubKey()))
|
||||
f.authKeeper.SetAccount(f.app.Context(), acc)
|
||||
|
||||
t.Run("account does not exist", func(t *testing.T) {
|
||||
resp, err := msgSrv.MigrateAccount(f.app.Context(), &authtypes.MsgMigrateAccount{
|
||||
Signer: f.mustAddr([]byte("notexist")),
|
||||
AccountType: "base",
|
||||
AccountInitMsg: nil,
|
||||
})
|
||||
require.Nil(t, resp)
|
||||
require.ErrorIs(t, err, sdkerrors.ErrUnknownAddress)
|
||||
})
|
||||
|
||||
t.Run("invalid account type", func(t *testing.T) {
|
||||
resp, err := msgSrv.MigrateAccount(f.app.Context(), &authtypes.MsgMigrateAccount{
|
||||
Signer: f.mustAddr(updatedMod.GetAddress()),
|
||||
AccountType: "base",
|
||||
AccountInitMsg: nil,
|
||||
})
|
||||
require.Nil(t, resp)
|
||||
require.ErrorContains(t, err, "only BaseAccount can be migrated")
|
||||
})
|
||||
|
||||
t.Run("success", func(t *testing.T) {
|
||||
pk, err := codectypes.NewAnyWithValue(privKey.PubKey())
|
||||
require.NoError(t, err)
|
||||
|
||||
migrateMsg := &basev1.MsgInit{
|
||||
PubKey: pk,
|
||||
InitSequence: 100,
|
||||
}
|
||||
|
||||
initMsgAny, err := codectypes.NewAnyWithValue(migrateMsg)
|
||||
require.NoError(t, err)
|
||||
|
||||
resp, err := msgSrv.MigrateAccount(f.app.Context(), &authtypes.MsgMigrateAccount{
|
||||
Signer: f.mustAddr(addr),
|
||||
AccountType: "base",
|
||||
AccountInitMsg: initMsgAny,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// check response semantics.
|
||||
require.Equal(t, resp.InitResponse.TypeUrl, "/cosmos.accounts.defaults.base.v1.MsgInitResponse")
|
||||
require.NotNil(t, resp.InitResponse.Value)
|
||||
|
||||
// check the account was removed from x/auth and added to x/accounts
|
||||
require.Nil(t, f.authKeeper.GetAccount(f.app.Context(), addr))
|
||||
require.True(t, f.accountsKeeper.IsAccountsModuleAccount(f.app.Context(), addr))
|
||||
|
||||
// check the init information is correctly propagated.
|
||||
seq, err := f.accountsKeeper.Query(f.app.Context(), addr, &basev1.QuerySequence{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, migrateMsg.InitSequence, seq.(*basev1.QuerySequenceResponse).Sequence)
|
||||
|
||||
pkResp, err := f.accountsKeeper.Query(f.app.Context(), addr, &basev1.QueryPubKey{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, migrateMsg.PubKey, pkResp.(*basev1.QueryPubKeyResponse).PubKey)
|
||||
})
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/log"
|
||||
|
||||
authTest "github.com/cosmos/cosmos-sdk/tests/integration/auth/keeper"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
func TestItCreatesModuleAccountOnInitBlock(t *testing.T) {
|
||||
var accountKeeper keeper.AccountKeeper
|
||||
app, err := simtestutil.SetupAtGenesis(
|
||||
depinject.Configs(
|
||||
authTest.AppConfig,
|
||||
depinject.Supply(log.NewNopLogger()),
|
||||
),
|
||||
&accountKeeper)
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx := app.BaseApp.NewContext(false)
|
||||
acc := accountKeeper.GetAccount(ctx, types.NewModuleAddress(types.FeeCollectorName))
|
||||
require.NotNil(t, acc)
|
||||
}
|
||||
@ -1,168 +0,0 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
|
||||
signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1"
|
||||
sdkmath "cosmossdk.io/math"
|
||||
"cosmossdk.io/x/bank/testutil"
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
"cosmossdk.io/x/tx/signing"
|
||||
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/integration"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
var _ signing.SignModeHandler = directHandler{}
|
||||
|
||||
type directHandler struct{}
|
||||
|
||||
func (s directHandler) Mode() signingv1beta1.SignMode {
|
||||
return signingv1beta1.SignMode_SIGN_MODE_DIRECT
|
||||
}
|
||||
|
||||
func (s directHandler) GetSignBytes(_ context.Context, _ signing.SignerData, _ signing.TxData) ([]byte, error) {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func TestAsyncExec(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initFixture(t, nil)
|
||||
|
||||
addrs := simtestutil.CreateIncrementalAccounts(2)
|
||||
coins := sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10)))
|
||||
|
||||
assert.NilError(t, testutil.FundAccount(f.app.Context(), f.bankKeeper, addrs[0], sdk.NewCoins(sdk.NewInt64Coin("stake", 500))))
|
||||
|
||||
msg := &banktypes.MsgSend{
|
||||
FromAddress: addrs[0].String(),
|
||||
ToAddress: addrs[1].String(),
|
||||
Amount: coins,
|
||||
}
|
||||
msg2 := &banktypes.MsgSend{
|
||||
FromAddress: addrs[1].String(),
|
||||
ToAddress: addrs[0].String(),
|
||||
Amount: coins,
|
||||
}
|
||||
failingMsg := &banktypes.MsgSend{
|
||||
FromAddress: addrs[0].String(),
|
||||
ToAddress: addrs[1].String(),
|
||||
Amount: sdk.NewCoins(sdk.NewCoin("stake", sdkmath.ZeroInt())), // No amount specified
|
||||
}
|
||||
|
||||
msgAny, err := codectypes.NewAnyWithValue(msg)
|
||||
assert.NilError(t, err)
|
||||
|
||||
msgAny2, err := codectypes.NewAnyWithValue(msg2)
|
||||
assert.NilError(t, err)
|
||||
|
||||
failingMsgAny, err := codectypes.NewAnyWithValue(failingMsg)
|
||||
assert.NilError(t, err)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
req *authtypes.MsgNonAtomicExec
|
||||
expectErr bool
|
||||
expErrMsg string
|
||||
}{
|
||||
{
|
||||
name: "empty signer address",
|
||||
req: &authtypes.MsgNonAtomicExec{
|
||||
Signer: "",
|
||||
Msgs: []*codectypes.Any{},
|
||||
},
|
||||
expectErr: true,
|
||||
expErrMsg: "empty signer address string is not allowed",
|
||||
},
|
||||
{
|
||||
name: "invalid signer address",
|
||||
req: &authtypes.MsgNonAtomicExec{
|
||||
Signer: "invalid",
|
||||
Msgs: []*codectypes.Any{},
|
||||
},
|
||||
expectErr: true,
|
||||
expErrMsg: "invalid signer address",
|
||||
},
|
||||
{
|
||||
name: "empty msgs",
|
||||
req: &authtypes.MsgNonAtomicExec{
|
||||
Signer: addrs[0].String(),
|
||||
Msgs: []*codectypes.Any{},
|
||||
},
|
||||
expectErr: true,
|
||||
expErrMsg: "messages cannot be empty",
|
||||
},
|
||||
{
|
||||
name: "valid msg",
|
||||
req: &authtypes.MsgNonAtomicExec{
|
||||
Signer: addrs[0].String(),
|
||||
Msgs: []*codectypes.Any{msgAny},
|
||||
},
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "multiple messages being executed",
|
||||
req: &authtypes.MsgNonAtomicExec{
|
||||
Signer: addrs[0].String(),
|
||||
Msgs: []*codectypes.Any{msgAny, msgAny},
|
||||
},
|
||||
expectErr: false,
|
||||
},
|
||||
{
|
||||
name: "multiple messages with different signers",
|
||||
req: &authtypes.MsgNonAtomicExec{
|
||||
Signer: addrs[0].String(),
|
||||
Msgs: []*codectypes.Any{msgAny, msgAny2},
|
||||
},
|
||||
expectErr: false,
|
||||
expErrMsg: "unauthorized: sender does not match expected sender",
|
||||
},
|
||||
{
|
||||
name: "multi msg with one failing being executed",
|
||||
req: &authtypes.MsgNonAtomicExec{
|
||||
Signer: addrs[0].String(),
|
||||
Msgs: []*codectypes.Any{msgAny, failingMsgAny},
|
||||
},
|
||||
expectErr: false,
|
||||
expErrMsg: "invalid coins",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
res, err := f.app.RunMsg(
|
||||
tc.req,
|
||||
integration.WithAutomaticFinalizeBlock(),
|
||||
integration.WithAutomaticCommit(),
|
||||
)
|
||||
if tc.expectErr {
|
||||
assert.ErrorContains(t, err, tc.expErrMsg)
|
||||
} else {
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, res != nil)
|
||||
|
||||
// check the result
|
||||
result := authtypes.MsgNonAtomicExecResponse{}
|
||||
err = f.cdc.Unmarshal(res.Value, &result)
|
||||
assert.NilError(t, err)
|
||||
|
||||
if tc.expErrMsg != "" {
|
||||
for _, res := range result.Results {
|
||||
if res.Error != "" {
|
||||
assert.Assert(t, strings.Contains(res.Error, tc.expErrMsg), fmt.Sprintf("res.Error %s does not contain %s", res.Error, tc.expErrMsg))
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,560 +0,0 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"go.uber.org/mock/gomock"
|
||||
"gotest.tools/v3/assert"
|
||||
"pgregory.net/rapid"
|
||||
|
||||
"cosmossdk.io/core/appmodule"
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/math"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
"cosmossdk.io/x/bank"
|
||||
"cosmossdk.io/x/bank/keeper"
|
||||
banktestutil "cosmossdk.io/x/bank/testutil"
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
_ "cosmossdk.io/x/consensus"
|
||||
minttypes "cosmossdk.io/x/mint/types"
|
||||
_ "cosmossdk.io/x/staking"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
|
||||
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/integration"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation"
|
||||
authtestutil "github.com/cosmos/cosmos-sdk/x/auth/testutil"
|
||||
_ "github.com/cosmos/cosmos-sdk/x/auth/tx/config"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
var (
|
||||
denomRegex = `[a-zA-Z][a-zA-Z0-9/:._-]{2,127}`
|
||||
addr1 = sdk.MustAccAddressFromBech32("cosmos139f7kncmglres2nf3h4hc4tade85ekfr8sulz5")
|
||||
coin1 = sdk.NewCoin("denom", math.NewInt(10))
|
||||
metadataAtom = banktypes.Metadata{
|
||||
Description: "The native staking token of the Cosmos Hub.",
|
||||
DenomUnits: []*banktypes.DenomUnit{
|
||||
{
|
||||
Denom: "uatom",
|
||||
Exponent: 0,
|
||||
Aliases: []string{"microatom"},
|
||||
},
|
||||
{
|
||||
Denom: "atom",
|
||||
Exponent: 6,
|
||||
Aliases: []string{"ATOM"},
|
||||
},
|
||||
},
|
||||
Base: "uatom",
|
||||
Display: "atom",
|
||||
}
|
||||
)
|
||||
|
||||
type deterministicFixture struct {
|
||||
ctx sdk.Context
|
||||
bankKeeper keeper.BaseKeeper
|
||||
queryClient banktypes.QueryClient
|
||||
}
|
||||
|
||||
func initDeterministicFixture(t *testing.T) *deterministicFixture {
|
||||
t.Helper()
|
||||
keys := storetypes.NewKVStoreKeys(authtypes.StoreKey, banktypes.StoreKey)
|
||||
encodingCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{}, bank.AppModule{})
|
||||
cdc := encodingCfg.Codec
|
||||
|
||||
logger := log.NewTestLogger(t)
|
||||
authority := authtypes.NewModuleAddress("gov")
|
||||
|
||||
maccPerms := map[string][]string{
|
||||
minttypes.ModuleName: {authtypes.Minter},
|
||||
}
|
||||
|
||||
// gomock initializations
|
||||
ctrl := gomock.NewController(t)
|
||||
acctsModKeeper := authtestutil.NewMockAccountsModKeeper(ctrl)
|
||||
accNum := uint64(0)
|
||||
acctsModKeeper.EXPECT().NextAccountNumber(gomock.Any()).AnyTimes().DoAndReturn(func(ctx context.Context) (uint64, error) {
|
||||
currentNum := accNum
|
||||
accNum++
|
||||
return currentNum, nil
|
||||
})
|
||||
|
||||
accountKeeper := authkeeper.NewAccountKeeper(
|
||||
runtime.NewEnvironment(runtime.NewKVStoreService(keys[authtypes.StoreKey]), log.NewNopLogger()),
|
||||
cdc,
|
||||
authtypes.ProtoBaseAccount,
|
||||
acctsModKeeper,
|
||||
maccPerms,
|
||||
addresscodec.NewBech32Codec(sdk.Bech32MainPrefix),
|
||||
sdk.Bech32MainPrefix,
|
||||
authority.String(),
|
||||
)
|
||||
|
||||
blockedAddresses := map[string]bool{
|
||||
accountKeeper.GetAuthority(): false,
|
||||
}
|
||||
bankKeeper := keeper.NewBaseKeeper(
|
||||
runtime.NewEnvironment(runtime.NewKVStoreService(keys[banktypes.StoreKey]), log.NewNopLogger()),
|
||||
cdc,
|
||||
accountKeeper,
|
||||
blockedAddresses,
|
||||
authority.String(),
|
||||
)
|
||||
|
||||
authModule := auth.NewAppModule(cdc, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil)
|
||||
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper)
|
||||
|
||||
integrationApp := integration.NewIntegrationApp(logger, keys, cdc,
|
||||
encodingCfg.InterfaceRegistry.SigningContext().AddressCodec(),
|
||||
encodingCfg.InterfaceRegistry.SigningContext().ValidatorAddressCodec(),
|
||||
map[string]appmodule.AppModule{
|
||||
authtypes.ModuleName: authModule,
|
||||
banktypes.ModuleName: bankModule,
|
||||
},
|
||||
baseapp.NewMsgServiceRouter(),
|
||||
baseapp.NewGRPCQueryRouter(),
|
||||
)
|
||||
|
||||
sdkCtx := sdk.UnwrapSDKContext(integrationApp.Context())
|
||||
|
||||
// Register MsgServer and QueryServer
|
||||
banktypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), keeper.NewMsgServerImpl(bankKeeper))
|
||||
banktypes.RegisterQueryServer(integrationApp.QueryHelper(), keeper.NewQuerier(&bankKeeper))
|
||||
|
||||
qr := integrationApp.QueryHelper()
|
||||
queryClient := banktypes.NewQueryClient(qr)
|
||||
|
||||
f := deterministicFixture{
|
||||
ctx: sdkCtx,
|
||||
bankKeeper: bankKeeper,
|
||||
queryClient: queryClient,
|
||||
}
|
||||
|
||||
return &f
|
||||
}
|
||||
|
||||
func fundAccount(f *deterministicFixture, addr sdk.AccAddress, coin ...sdk.Coin) {
|
||||
err := banktestutil.FundAccount(f.ctx, f.bankKeeper, addr, sdk.NewCoins(coin...))
|
||||
assert.NilError(&testing.T{}, err)
|
||||
}
|
||||
|
||||
func getCoin(rt *rapid.T) sdk.Coin {
|
||||
return sdk.NewCoin(
|
||||
rapid.StringMatching(denomRegex).Draw(rt, "denom"),
|
||||
math.NewInt(rapid.Int64Min(1).Draw(rt, "amount")),
|
||||
)
|
||||
}
|
||||
|
||||
func TestGRPCQueryBalance(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
addr := testdata.AddressGenerator(rt).Draw(rt, "address")
|
||||
coin := getCoin(rt)
|
||||
fundAccount(f, addr, coin)
|
||||
|
||||
addrStr, err := codectestutil.CodecOptions{}.GetAddressCodec().BytesToString(addr)
|
||||
assert.NilError(t, err)
|
||||
|
||||
req := banktypes.NewQueryBalanceRequest(addrStr, coin.GetDenom())
|
||||
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Balance, 0, true)
|
||||
})
|
||||
|
||||
addr1Str, err := codectestutil.CodecOptions{}.GetAddressCodec().BytesToString(addr1)
|
||||
assert.NilError(t, err)
|
||||
|
||||
fundAccount(f, addr1, coin1)
|
||||
req := banktypes.NewQueryBalanceRequest(addr1Str, coin1.GetDenom())
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Balance, 1087, false)
|
||||
}
|
||||
|
||||
func TestGRPCQueryAllBalances(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
addressCodec := codectestutil.CodecOptions{}.GetAddressCodec()
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
addr := testdata.AddressGenerator(rt).Draw(rt, "address")
|
||||
numCoins := rapid.IntRange(1, 10).Draw(rt, "num-count")
|
||||
coins := make(sdk.Coins, 0, numCoins)
|
||||
|
||||
addrStr, err := addressCodec.BytesToString(addr)
|
||||
assert.NilError(t, err)
|
||||
|
||||
for i := 0; i < numCoins; i++ {
|
||||
coin := getCoin(rt)
|
||||
if exists, _ := coins.Find(coin.Denom); exists {
|
||||
t.Skip("duplicate denom")
|
||||
}
|
||||
// NewCoins sorts the denoms
|
||||
coins = sdk.NewCoins(append(coins, coin)...)
|
||||
}
|
||||
|
||||
fundAccount(f, addr, coins...)
|
||||
|
||||
req := banktypes.NewQueryAllBalancesRequest(addrStr, testdata.PaginationGenerator(rt, uint64(numCoins)).Draw(rt, "pagination"), false)
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.AllBalances, 0, true)
|
||||
})
|
||||
|
||||
coins := sdk.NewCoins(
|
||||
sdk.NewCoin("stake", math.NewInt(10)),
|
||||
sdk.NewCoin("denom", math.NewInt(100)),
|
||||
)
|
||||
|
||||
fundAccount(f, addr1, coins...)
|
||||
addr1Str, err := addressCodec.BytesToString(addr1)
|
||||
assert.NilError(t, err)
|
||||
|
||||
req := banktypes.NewQueryAllBalancesRequest(addr1Str, nil, false)
|
||||
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.AllBalances, 357, false)
|
||||
}
|
||||
|
||||
func TestGRPCQuerySpendableBalances(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
addr := testdata.AddressGenerator(rt).Draw(rt, "address")
|
||||
addrStr, err := codectestutil.CodecOptions{}.GetAddressCodec().BytesToString(addr)
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Denoms must be unique, otherwise sdk.NewCoins will panic.
|
||||
denoms := rapid.SliceOfNDistinct(rapid.StringMatching(denomRegex), 1, 10, rapid.ID[string]).Draw(rt, "denoms")
|
||||
coins := make(sdk.Coins, 0, len(denoms))
|
||||
for _, denom := range denoms {
|
||||
coin := sdk.NewCoin(
|
||||
denom,
|
||||
math.NewInt(rapid.Int64Min(1).Draw(rt, "amount")),
|
||||
)
|
||||
|
||||
// NewCoins sorts the denoms
|
||||
coins = sdk.NewCoins(append(coins, coin)...)
|
||||
}
|
||||
|
||||
err = banktestutil.FundAccount(f.ctx, f.bankKeeper, addr, coins)
|
||||
assert.NilError(t, err)
|
||||
|
||||
req := banktypes.NewQuerySpendableBalancesRequest(addrStr, testdata.PaginationGenerator(rt, uint64(len(denoms))).Draw(rt, "pagination"))
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.SpendableBalances, 0, true)
|
||||
})
|
||||
|
||||
coins := sdk.NewCoins(
|
||||
sdk.NewCoin("stake", math.NewInt(10)),
|
||||
sdk.NewCoin("denom", math.NewInt(100)),
|
||||
)
|
||||
|
||||
err := banktestutil.FundAccount(f.ctx, f.bankKeeper, addr1, coins)
|
||||
assert.NilError(t, err)
|
||||
|
||||
addr1Str, err := codectestutil.CodecOptions{}.GetAddressCodec().BytesToString(addr1)
|
||||
assert.NilError(t, err)
|
||||
|
||||
req := banktypes.NewQuerySpendableBalancesRequest(addr1Str, nil)
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.SpendableBalances, 1420, false)
|
||||
}
|
||||
|
||||
func TestGRPCQueryTotalSupply(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
|
||||
res, err := f.queryClient.TotalSupply(f.ctx, &banktypes.QueryTotalSupplyRequest{})
|
||||
assert.NilError(t, err)
|
||||
initialSupply := res.GetSupply()
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
numCoins := rapid.IntRange(1, 3).Draw(rt, "num-count")
|
||||
coins := make(sdk.Coins, 0, numCoins)
|
||||
|
||||
for i := 0; i < numCoins; i++ {
|
||||
coin := sdk.NewCoin(
|
||||
rapid.StringMatching(denomRegex).Draw(rt, "denom"),
|
||||
math.NewInt(rapid.Int64Min(1).Draw(rt, "amount")),
|
||||
)
|
||||
|
||||
coins = coins.Add(coin)
|
||||
}
|
||||
|
||||
assert.NilError(t, f.bankKeeper.MintCoins(f.ctx, minttypes.ModuleName, coins))
|
||||
|
||||
initialSupply = initialSupply.Add(coins...)
|
||||
|
||||
req := &banktypes.QueryTotalSupplyRequest{
|
||||
Pagination: testdata.PaginationGenerator(rt, uint64(len(initialSupply))).Draw(rt, "pagination"),
|
||||
}
|
||||
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.TotalSupply, 0, true)
|
||||
})
|
||||
|
||||
f = initDeterministicFixture(t) // reset
|
||||
|
||||
coins := sdk.NewCoins(
|
||||
sdk.NewCoin("foo", math.NewInt(10)),
|
||||
sdk.NewCoin("bar", math.NewInt(100)),
|
||||
)
|
||||
|
||||
assert.NilError(t, f.bankKeeper.MintCoins(f.ctx, minttypes.ModuleName, coins))
|
||||
|
||||
req := &banktypes.QueryTotalSupplyRequest{}
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.TotalSupply, 150, false)
|
||||
}
|
||||
|
||||
func TestGRPCQueryTotalSupplyOf(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
coin := sdk.NewCoin(
|
||||
rapid.StringMatching(denomRegex).Draw(rt, "denom"),
|
||||
math.NewInt(rapid.Int64Min(1).Draw(rt, "amount")),
|
||||
)
|
||||
|
||||
assert.NilError(t, f.bankKeeper.MintCoins(f.ctx, minttypes.ModuleName, sdk.NewCoins(coin)))
|
||||
|
||||
req := &banktypes.QuerySupplyOfRequest{Denom: coin.GetDenom()}
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.SupplyOf, 0, true)
|
||||
})
|
||||
|
||||
coin := sdk.NewCoin("bar", math.NewInt(100))
|
||||
|
||||
assert.NilError(t, f.bankKeeper.MintCoins(f.ctx, minttypes.ModuleName, sdk.NewCoins(coin)))
|
||||
req := &banktypes.QuerySupplyOfRequest{Denom: coin.GetDenom()}
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.SupplyOf, 1021, false)
|
||||
}
|
||||
|
||||
func TestGRPCQueryParams(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
enabledStatus := banktypes.SendEnabled{
|
||||
Denom: rapid.StringMatching(denomRegex).Draw(rt, "denom"),
|
||||
Enabled: rapid.Bool().Draw(rt, "status"),
|
||||
}
|
||||
|
||||
params := banktypes.Params{
|
||||
SendEnabled: []*banktypes.SendEnabled{&enabledStatus},
|
||||
DefaultSendEnabled: rapid.Bool().Draw(rt, "send"),
|
||||
}
|
||||
|
||||
err := f.bankKeeper.SetParams(f.ctx, params)
|
||||
assert.NilError(t, err)
|
||||
|
||||
req := &banktypes.QueryParamsRequest{}
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Params, 0, true)
|
||||
})
|
||||
|
||||
enabledStatus := banktypes.SendEnabled{
|
||||
Denom: "denom",
|
||||
Enabled: true,
|
||||
}
|
||||
|
||||
params := banktypes.Params{
|
||||
SendEnabled: []*banktypes.SendEnabled{&enabledStatus},
|
||||
DefaultSendEnabled: false,
|
||||
}
|
||||
|
||||
err := f.bankKeeper.SetParams(f.ctx, params)
|
||||
assert.NilError(t, err)
|
||||
req := &banktypes.QueryParamsRequest{}
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Params, 1003, false)
|
||||
}
|
||||
|
||||
func createAndReturnMetadatas(t *rapid.T, count int) []banktypes.Metadata {
|
||||
denomsMetadata := make([]banktypes.Metadata, 0, count)
|
||||
for i := 0; i < count; i++ {
|
||||
|
||||
denom := rapid.StringMatching(denomRegex).Draw(t, "denom")
|
||||
|
||||
aliases := rapid.SliceOf(rapid.String()).Draw(t, "aliases")
|
||||
// In the GRPC server code, empty arrays are returned as nil
|
||||
if len(aliases) == 0 {
|
||||
aliases = nil
|
||||
}
|
||||
|
||||
metadata := banktypes.Metadata{
|
||||
Description: rapid.StringN(1, 100, 100).Draw(t, "desc"),
|
||||
DenomUnits: []*banktypes.DenomUnit{
|
||||
{
|
||||
Denom: denom,
|
||||
Exponent: rapid.Uint32().Draw(t, "exponent"),
|
||||
Aliases: aliases,
|
||||
},
|
||||
},
|
||||
Base: denom,
|
||||
Display: denom,
|
||||
Name: rapid.String().Draw(t, "name"),
|
||||
Symbol: rapid.String().Draw(t, "symbol"),
|
||||
URI: rapid.String().Draw(t, "uri"),
|
||||
URIHash: rapid.String().Draw(t, "uri-hash"),
|
||||
}
|
||||
|
||||
denomsMetadata = append(denomsMetadata, metadata)
|
||||
}
|
||||
|
||||
return denomsMetadata
|
||||
}
|
||||
|
||||
func TestGRPCDenomsMetadata(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
count := rapid.IntRange(1, 3).Draw(rt, "count")
|
||||
denomsMetadata := createAndReturnMetadatas(rt, count)
|
||||
assert.Assert(t, len(denomsMetadata) == count)
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
f.bankKeeper.SetDenomMetaData(f.ctx, denomsMetadata[i])
|
||||
}
|
||||
|
||||
req := &banktypes.QueryDenomsMetadataRequest{
|
||||
Pagination: testdata.PaginationGenerator(rt, uint64(count)).Draw(rt, "pagination"),
|
||||
}
|
||||
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DenomsMetadata, 0, true)
|
||||
})
|
||||
|
||||
f = initDeterministicFixture(t) // reset
|
||||
|
||||
f.bankKeeper.SetDenomMetaData(f.ctx, metadataAtom)
|
||||
|
||||
req := &banktypes.QueryDenomsMetadataRequest{}
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DenomsMetadata, 660, false)
|
||||
}
|
||||
|
||||
func TestGRPCDenomMetadata(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
denomMetadata := createAndReturnMetadatas(rt, 1)
|
||||
assert.Assert(t, len(denomMetadata) == 1)
|
||||
f.bankKeeper.SetDenomMetaData(f.ctx, denomMetadata[0])
|
||||
|
||||
req := &banktypes.QueryDenomMetadataRequest{
|
||||
Denom: denomMetadata[0].Base,
|
||||
}
|
||||
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DenomMetadata, 0, true)
|
||||
})
|
||||
|
||||
f.bankKeeper.SetDenomMetaData(f.ctx, metadataAtom)
|
||||
|
||||
req := &banktypes.QueryDenomMetadataRequest{
|
||||
Denom: metadataAtom.Base,
|
||||
}
|
||||
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DenomMetadata, 1300, false)
|
||||
}
|
||||
|
||||
func TestGRPCSendEnabled(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
|
||||
allDenoms := []string{}
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
count := rapid.IntRange(0, 10).Draw(rt, "count")
|
||||
denoms := make([]string, 0, count)
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
coin := banktypes.SendEnabled{
|
||||
Denom: rapid.StringMatching(denomRegex).Draw(rt, "denom"),
|
||||
Enabled: rapid.Bool().Draw(rt, "enabled-status"),
|
||||
}
|
||||
|
||||
f.bankKeeper.SetSendEnabled(f.ctx, coin.Denom, coin.Enabled)
|
||||
denoms = append(denoms, coin.Denom)
|
||||
}
|
||||
|
||||
allDenoms = append(allDenoms, denoms...)
|
||||
|
||||
req := &banktypes.QuerySendEnabledRequest{
|
||||
Denoms: denoms,
|
||||
// Pagination is only taken into account when `denoms` is an empty array
|
||||
Pagination: testdata.PaginationGenerator(rt, uint64(len(allDenoms))).Draw(rt, "pagination"),
|
||||
}
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.SendEnabled, 0, true)
|
||||
})
|
||||
|
||||
coin1 := banktypes.SendEnabled{
|
||||
Denom: "falsecoin",
|
||||
Enabled: false,
|
||||
}
|
||||
coin2 := banktypes.SendEnabled{
|
||||
Denom: "truecoin",
|
||||
Enabled: true,
|
||||
}
|
||||
|
||||
f.bankKeeper.SetSendEnabled(f.ctx, coin1.Denom, false)
|
||||
f.bankKeeper.SetSendEnabled(f.ctx, coin2.Denom, true)
|
||||
|
||||
req := &banktypes.QuerySendEnabledRequest{
|
||||
Denoms: []string{coin1.GetDenom(), coin2.GetDenom()},
|
||||
}
|
||||
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.SendEnabled, 4063, false)
|
||||
}
|
||||
|
||||
func TestGRPCDenomOwners(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := initDeterministicFixture(t)
|
||||
|
||||
rapid.Check(t, func(rt *rapid.T) {
|
||||
denom := rapid.StringMatching(denomRegex).Draw(rt, "denom")
|
||||
numAddr := rapid.IntRange(1, 10).Draw(rt, "number-address")
|
||||
for i := 0; i < numAddr; i++ {
|
||||
addr := testdata.AddressGenerator(rt).Draw(rt, "address")
|
||||
|
||||
coin := sdk.NewCoin(
|
||||
denom,
|
||||
math.NewInt(rapid.Int64Min(1).Draw(rt, "amount")),
|
||||
)
|
||||
|
||||
err := banktestutil.FundAccount(f.ctx, f.bankKeeper, addr, sdk.NewCoins(coin))
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
req := &banktypes.QueryDenomOwnersRequest{
|
||||
Denom: denom,
|
||||
Pagination: testdata.PaginationGenerator(rt, uint64(numAddr)).Draw(rt, "pagination"),
|
||||
}
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DenomOwners, 0, true)
|
||||
})
|
||||
|
||||
denomOwners := []*banktypes.DenomOwner{
|
||||
{
|
||||
Address: "cosmos1qg65a9q6k2sqq7l3ycp428sqqpmqcucgzze299",
|
||||
Balance: coin1,
|
||||
},
|
||||
{
|
||||
Address: "cosmos1qglnsqgpq48l7qqzgs8qdshr6fh3gqq9ej3qut",
|
||||
Balance: coin1,
|
||||
},
|
||||
}
|
||||
|
||||
for i := 0; i < len(denomOwners); i++ {
|
||||
addr, err := sdk.AccAddressFromBech32(denomOwners[i].Address)
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = banktestutil.FundAccount(f.ctx, f.bankKeeper, addr, sdk.NewCoins(coin1))
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
req := &banktypes.QueryDenomOwnersRequest{
|
||||
Denom: coin1.GetDenom(),
|
||||
}
|
||||
testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DenomOwners, 2516, false)
|
||||
}
|
||||
@ -1,235 +0,0 @@
|
||||
package integration_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"go.uber.org/mock/gomock"
|
||||
|
||||
"cosmossdk.io/core/appmodule"
|
||||
"cosmossdk.io/log"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
"cosmossdk.io/x/mint"
|
||||
mintkeeper "cosmossdk.io/x/mint/keeper"
|
||||
minttypes "cosmossdk.io/x/mint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
|
||||
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/integration"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation"
|
||||
authtestutil "github.com/cosmos/cosmos-sdk/x/auth/testutil"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
// Example shows how to use the integration test framework to test the integration of SDK modules.
|
||||
// Panics are used in this example, but in a real test case, you should use the testing.T object and assertions.
|
||||
func Example() {
|
||||
// in this example we are testing the integration of the following modules:
|
||||
// - mint, which directly depends on auth, bank and staking
|
||||
encodingCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{}, mint.AppModule{})
|
||||
signingCtx := encodingCfg.InterfaceRegistry.SigningContext()
|
||||
|
||||
keys := storetypes.NewKVStoreKeys(authtypes.StoreKey, minttypes.StoreKey)
|
||||
authority := authtypes.NewModuleAddress("gov").String()
|
||||
|
||||
// replace the logger by testing values in a real test case (e.g. log.NewTestLogger(t))
|
||||
logger := log.NewNopLogger()
|
||||
|
||||
// gomock initializations
|
||||
ctrl := gomock.NewController(&testing.T{})
|
||||
acctsModKeeper := authtestutil.NewMockAccountsModKeeper(ctrl)
|
||||
accNum := uint64(0)
|
||||
acctsModKeeper.EXPECT().NextAccountNumber(gomock.Any()).AnyTimes().DoAndReturn(func(ctx context.Context) (uint64, error) {
|
||||
currentNum := accNum
|
||||
accNum++
|
||||
return currentNum, nil
|
||||
})
|
||||
|
||||
accountKeeper := authkeeper.NewAccountKeeper(
|
||||
runtime.NewEnvironment(runtime.NewKVStoreService(keys[authtypes.StoreKey]), log.NewNopLogger()),
|
||||
encodingCfg.Codec,
|
||||
authtypes.ProtoBaseAccount,
|
||||
acctsModKeeper,
|
||||
map[string][]string{minttypes.ModuleName: {authtypes.Minter}},
|
||||
addresscodec.NewBech32Codec("cosmos"),
|
||||
"cosmos",
|
||||
authority,
|
||||
)
|
||||
|
||||
// subspace is nil because we don't test params (which is legacy anyway)
|
||||
authModule := auth.NewAppModule(encodingCfg.Codec, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil)
|
||||
|
||||
// here bankkeeper and staking keeper is nil because we are not testing them
|
||||
// subspace is nil because we don't test params (which is legacy anyway)
|
||||
mintKeeper := mintkeeper.NewKeeper(encodingCfg.Codec, runtime.NewEnvironment(runtime.NewKVStoreService(keys[minttypes.StoreKey]), logger), accountKeeper, nil, authtypes.FeeCollectorName, authority)
|
||||
mintModule := mint.NewAppModule(encodingCfg.Codec, mintKeeper, accountKeeper)
|
||||
|
||||
// create the application and register all the modules from the previous step
|
||||
integrationApp := integration.NewIntegrationApp(
|
||||
logger,
|
||||
keys,
|
||||
encodingCfg.Codec,
|
||||
signingCtx.AddressCodec(),
|
||||
signingCtx.ValidatorAddressCodec(),
|
||||
map[string]appmodule.AppModule{
|
||||
authtypes.ModuleName: authModule,
|
||||
minttypes.ModuleName: mintModule,
|
||||
},
|
||||
baseapp.NewMsgServiceRouter(),
|
||||
baseapp.NewGRPCQueryRouter(),
|
||||
)
|
||||
|
||||
// register the message and query servers
|
||||
authtypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), authkeeper.NewMsgServerImpl(accountKeeper))
|
||||
minttypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), mintkeeper.NewMsgServerImpl(mintKeeper))
|
||||
minttypes.RegisterQueryServer(integrationApp.QueryHelper(), mintkeeper.NewQueryServerImpl(mintKeeper))
|
||||
|
||||
params := minttypes.DefaultParams()
|
||||
params.BlocksPerYear = 10000
|
||||
|
||||
// now we can use the application to test a mint message
|
||||
result, err := integrationApp.RunMsg(&minttypes.MsgUpdateParams{
|
||||
Authority: authority,
|
||||
Params: params,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// in this example the result is an empty response, a nil check is enough
|
||||
// in other cases, it is recommended to check the result value.
|
||||
if result == nil {
|
||||
panic(errors.New("unexpected nil result"))
|
||||
}
|
||||
|
||||
// we now check the result
|
||||
resp := minttypes.MsgUpdateParamsResponse{}
|
||||
err = encodingCfg.Codec.Unmarshal(result.Value, &resp)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sdkCtx := sdk.UnwrapSDKContext(integrationApp.Context())
|
||||
|
||||
// we should also check the state of the application
|
||||
got, err := mintKeeper.Params.Get(sdkCtx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(got, params); diff != "" {
|
||||
panic(diff)
|
||||
}
|
||||
fmt.Println(got.BlocksPerYear)
|
||||
// Output: 10000
|
||||
}
|
||||
|
||||
// Example_oneModule shows how to use the integration test framework to test the integration of a single module.
|
||||
// That module has no dependency on other modules.
|
||||
func Example_oneModule() {
|
||||
// in this example we are testing the integration of the auth module:
|
||||
encodingCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{})
|
||||
keys := storetypes.NewKVStoreKeys(authtypes.StoreKey)
|
||||
authority := authtypes.NewModuleAddress("gov").String()
|
||||
|
||||
// replace the logger by testing values in a real test case (e.g. log.NewTestLogger(t))
|
||||
logger := log.NewLogger(io.Discard)
|
||||
|
||||
// gomock initializations
|
||||
ctrl := gomock.NewController(&testing.T{})
|
||||
acctsModKeeper := authtestutil.NewMockAccountsModKeeper(ctrl)
|
||||
accNum := uint64(0)
|
||||
acctsModKeeper.EXPECT().NextAccountNumber(gomock.Any()).AnyTimes().DoAndReturn(func(ctx context.Context) (uint64, error) {
|
||||
currentNum := accNum
|
||||
accNum++
|
||||
return currentNum, nil
|
||||
})
|
||||
|
||||
accountKeeper := authkeeper.NewAccountKeeper(
|
||||
runtime.NewEnvironment(runtime.NewKVStoreService(keys[authtypes.StoreKey]), log.NewNopLogger()),
|
||||
encodingCfg.Codec,
|
||||
authtypes.ProtoBaseAccount,
|
||||
acctsModKeeper,
|
||||
map[string][]string{minttypes.ModuleName: {authtypes.Minter}},
|
||||
addresscodec.NewBech32Codec("cosmos"),
|
||||
"cosmos",
|
||||
authority,
|
||||
)
|
||||
|
||||
// subspace is nil because we don't test params (which is legacy anyway)
|
||||
authModule := auth.NewAppModule(encodingCfg.Codec, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil)
|
||||
|
||||
// create the application and register all the modules from the previous step
|
||||
integrationApp := integration.NewIntegrationApp(
|
||||
logger,
|
||||
keys,
|
||||
encodingCfg.Codec,
|
||||
encodingCfg.InterfaceRegistry.SigningContext().AddressCodec(),
|
||||
encodingCfg.InterfaceRegistry.SigningContext().ValidatorAddressCodec(),
|
||||
map[string]appmodule.AppModule{
|
||||
authtypes.ModuleName: authModule,
|
||||
},
|
||||
baseapp.NewMsgServiceRouter(),
|
||||
baseapp.NewGRPCQueryRouter(),
|
||||
)
|
||||
|
||||
// register the message and query servers
|
||||
authtypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), authkeeper.NewMsgServerImpl(accountKeeper))
|
||||
|
||||
params := authtypes.DefaultParams()
|
||||
params.MaxMemoCharacters = 1000
|
||||
|
||||
// now we can use the application to test a mint message
|
||||
result, err := integrationApp.RunMsg(&authtypes.MsgUpdateParams{
|
||||
Authority: authority,
|
||||
Params: params,
|
||||
},
|
||||
// this allows to the begin and end blocker of the module before and after the message
|
||||
integration.WithAutomaticFinalizeBlock(),
|
||||
// this allows to commit the state after the message
|
||||
integration.WithAutomaticCommit(),
|
||||
)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// verify that the begin and end blocker were called
|
||||
// NOTE: in this example, we are testing auth, which doesn't have any begin or end blocker
|
||||
// so verifying the block height is enough
|
||||
if integrationApp.LastBlockHeight() != 2 {
|
||||
panic(fmt.Errorf("expected block height to be 2, got %d", integrationApp.LastBlockHeight()))
|
||||
}
|
||||
|
||||
// in this example the result is an empty response, a nil check is enough
|
||||
// in other cases, it is recommended to check the result value.
|
||||
if result == nil {
|
||||
panic(errors.New("unexpected nil result"))
|
||||
}
|
||||
|
||||
// we now check the result
|
||||
resp := authtypes.MsgUpdateParamsResponse{}
|
||||
err = encodingCfg.Codec.Unmarshal(result.Value, &resp)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sdkCtx := sdk.UnwrapSDKContext(integrationApp.Context())
|
||||
|
||||
// we should also check the state of the application
|
||||
got := accountKeeper.GetParams(sdkCtx)
|
||||
if diff := cmp.Diff(got, params); diff != "" {
|
||||
panic(diff)
|
||||
}
|
||||
fmt.Println(got.MaxMemoCharacters)
|
||||
// Output: 1000
|
||||
}
|
||||
116
tests/integration/v2/auth/keeper_bench_test.go
Normal file
116
tests/integration/v2/auth/keeper_bench_test.go
Normal file
@ -0,0 +1,116 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/log"
|
||||
basedepinject "cosmossdk.io/x/accounts/defaults/base/depinject"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/tests/integration/v2"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/configurator"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
)
|
||||
|
||||
func BenchmarkAccountMapperGetAccountFound(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
|
||||
moduleConfigs := []configurator.ModuleOption{
|
||||
configurator.AccountsModule(),
|
||||
configurator.AuthModule(),
|
||||
configurator.BankModule(),
|
||||
configurator.VestingModule(),
|
||||
configurator.StakingModule(),
|
||||
configurator.TxModule(),
|
||||
configurator.ValidateModule(),
|
||||
configurator.ConsensusModule(),
|
||||
configurator.GenutilModule(),
|
||||
}
|
||||
|
||||
var accountKeeper keeper.AccountKeeper
|
||||
startupCfg := integration.DefaultStartUpConfig(b)
|
||||
|
||||
app, err := integration.NewApp(
|
||||
depinject.Configs(configurator.NewAppV2Config(moduleConfigs...), depinject.Provide(
|
||||
// inject desired account types:
|
||||
basedepinject.ProvideAccount,
|
||||
|
||||
// provide base account options
|
||||
basedepinject.ProvideSecp256K1PubKey,
|
||||
|
||||
// provide extra accounts
|
||||
ProvideMockRetroCompatAccountValid,
|
||||
ProvideMockRetroCompatAccountNoInfo,
|
||||
ProvideMockRetroCompatAccountNoImplement,
|
||||
), depinject.Supply(log.NewNopLogger())),
|
||||
startupCfg,
|
||||
&accountKeeper)
|
||||
require.NoError(b, err)
|
||||
|
||||
ctx := app.StateLatestContext(b)
|
||||
|
||||
// assumes b.N < 2**24
|
||||
for i := 0; i < b.N; i++ {
|
||||
arr := []byte{byte((i & 0xFF0000) >> 16), byte((i & 0xFF00) >> 8), byte(i & 0xFF)}
|
||||
addr := sdk.AccAddress(arr)
|
||||
acc := accountKeeper.NewAccountWithAddress(ctx, addr)
|
||||
accountKeeper.SetAccount(ctx, acc)
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
arr := []byte{byte((i & 0xFF0000) >> 16), byte((i & 0xFF00) >> 8), byte(i & 0xFF)}
|
||||
accountKeeper.GetAccount(ctx, sdk.AccAddress(arr))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAccountMapperSetAccount(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
|
||||
moduleConfigs := []configurator.ModuleOption{
|
||||
configurator.AccountsModule(),
|
||||
configurator.AuthModule(),
|
||||
configurator.BankModule(),
|
||||
configurator.VestingModule(),
|
||||
configurator.StakingModule(),
|
||||
configurator.TxModule(),
|
||||
configurator.ValidateModule(),
|
||||
configurator.ConsensusModule(),
|
||||
configurator.GenutilModule(),
|
||||
}
|
||||
|
||||
var accountKeeper keeper.AccountKeeper
|
||||
startupCfg := integration.DefaultStartUpConfig(b)
|
||||
|
||||
app, err := integration.NewApp(
|
||||
depinject.Configs(configurator.NewAppV2Config(moduleConfigs...), depinject.Provide(
|
||||
// inject desired account types:
|
||||
basedepinject.ProvideAccount,
|
||||
|
||||
// provide base account options
|
||||
basedepinject.ProvideSecp256K1PubKey,
|
||||
|
||||
// provide extra accounts
|
||||
ProvideMockRetroCompatAccountValid,
|
||||
ProvideMockRetroCompatAccountNoInfo,
|
||||
ProvideMockRetroCompatAccountNoImplement,
|
||||
), depinject.Supply(log.NewNopLogger())),
|
||||
startupCfg,
|
||||
&accountKeeper)
|
||||
require.NoError(b, err)
|
||||
|
||||
ctx := app.StateLatestContext(b)
|
||||
|
||||
b.ResetTimer()
|
||||
|
||||
// assumes b.N < 2**24
|
||||
for i := 0; i < b.N; i++ {
|
||||
arr := []byte{byte((i & 0xFF0000) >> 16), byte((i & 0xFF00) >> 8), byte(i & 0xFF)}
|
||||
addr := sdk.AccAddress(arr)
|
||||
acc := accountKeeper.NewAccountWithAddress(ctx, addr)
|
||||
accountKeeper.SetAccount(ctx, acc)
|
||||
}
|
||||
}
|
||||
16
tests/integration/v2/auth/module_test.go
Normal file
16
tests/integration/v2/auth/module_test.go
Normal file
@ -0,0 +1,16 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
func TestItCreatesModuleAccountOnInitBlock(t *testing.T) {
|
||||
f := createTestSuite(t)
|
||||
ctx := f.ctx
|
||||
acc := f.authKeeper.GetAccount(ctx, types.NewModuleAddress(types.FeeCollectorName))
|
||||
require.NotNil(t, acc)
|
||||
}
|
||||
93
tests/integration/v2/example/example_test.go
Normal file
93
tests/integration/v2/example/example_test.go
Normal file
@ -0,0 +1,93 @@
|
||||
package integration_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/log"
|
||||
mintkeeper "cosmossdk.io/x/mint/keeper"
|
||||
minttypes "cosmossdk.io/x/mint/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/tests/integration/v2"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/configurator"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
)
|
||||
|
||||
// Example shows how to use the integration test framework to test the integration of SDK modules.
|
||||
// Panics are used in this example, but in a real test case, you should use the testing.T object and assertions.
|
||||
func Example(t *testing.T) {
|
||||
authority := authtypes.NewModuleAddress("gov").String()
|
||||
|
||||
var (
|
||||
mintKeeper *mintkeeper.Keeper
|
||||
)
|
||||
|
||||
moduleConfigs := []configurator.ModuleOption{
|
||||
configurator.AccountsModule(),
|
||||
configurator.AuthModule(),
|
||||
configurator.BankModule(),
|
||||
configurator.VestingModule(),
|
||||
configurator.TxModule(),
|
||||
configurator.ValidateModule(),
|
||||
configurator.ConsensusModule(),
|
||||
configurator.GenutilModule(),
|
||||
}
|
||||
|
||||
var err error
|
||||
startupCfg := integration.DefaultStartUpConfig(t)
|
||||
|
||||
app, err := integration.NewApp(
|
||||
depinject.Configs(configurator.NewAppV2Config(moduleConfigs...), depinject.Provide(), depinject.Supply(log.NewNopLogger())),
|
||||
startupCfg,
|
||||
mintKeeper)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, mintKeeper)
|
||||
|
||||
ctx := app.StateLatestContext(t)
|
||||
|
||||
mintMsgServer := mintkeeper.NewMsgServerImpl(mintKeeper)
|
||||
|
||||
params := minttypes.DefaultParams()
|
||||
params.BlocksPerYear = 10000
|
||||
|
||||
// now we can use the application to test a mint message
|
||||
result, err := app.RunMsg(t, ctx, func(ctx context.Context) (transaction.Msg, error) {
|
||||
msg := &minttypes.MsgUpdateParams{
|
||||
Authority: authority,
|
||||
Params: params,
|
||||
}
|
||||
|
||||
return mintMsgServer.UpdateParams(ctx, msg)
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// in this example the result is an empty response, a nil check is enough
|
||||
// in other cases, it is recommended to check the result value.
|
||||
if result == nil {
|
||||
panic(errors.New("unexpected nil result"))
|
||||
}
|
||||
|
||||
_, ok := result.(*minttypes.MsgUpdateParamsResponse)
|
||||
require.True(t, ok)
|
||||
|
||||
// we should also check the state of the application
|
||||
got, err := mintKeeper.Params.Get(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(got, params); diff != "" {
|
||||
panic(diff)
|
||||
}
|
||||
fmt.Println(got.BlocksPerYear)
|
||||
// Output: 10000
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
// Integration contains the integration test setup used for SDK modules.
|
||||
// To see how to use this, check the tests/integration/example_test.go file.
|
||||
package integration
|
||||
@ -1,9 +0,0 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
)
|
||||
|
||||
// CreateMultiStore is a helper for setting up multiple stores for provided modules.
|
||||
// Deprecated: use github.com/cosmos/cosmos-sdk/types/module/testutil.CreateMultiStore instead.
|
||||
var CreateMultiStore = moduletestutil.CreateMultiStore
|
||||
@ -1,25 +0,0 @@
|
||||
package integration
|
||||
|
||||
// Config is the configuration for the integration app.
|
||||
type Config struct {
|
||||
AutomaticFinalizeBlock bool
|
||||
AutomaticCommit bool
|
||||
}
|
||||
|
||||
// Option is a function that can be used to configure the integration app.
|
||||
type Option func(*Config)
|
||||
|
||||
// WithAutomaticFinalizeBlock calls ABCI finalize block.
|
||||
func WithAutomaticFinalizeBlock() Option {
|
||||
return func(cfg *Config) {
|
||||
cfg.AutomaticFinalizeBlock = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithAutomaticCommit enables automatic commit.
|
||||
// This means that the integration app will automatically commit the state after each msgs.
|
||||
func WithAutomaticCommit() Option {
|
||||
return func(cfg *Config) {
|
||||
cfg.AutomaticCommit = true
|
||||
}
|
||||
}
|
||||
@ -1,237 +0,0 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
cmtabcitypes "github.com/cometbft/cometbft/api/cometbft/abci/v1"
|
||||
cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1"
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
"cosmossdk.io/core/address"
|
||||
"cosmossdk.io/core/appmodule"
|
||||
corestore "cosmossdk.io/core/store"
|
||||
coretesting "cosmossdk.io/core/testing"
|
||||
"cosmossdk.io/log"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
)
|
||||
|
||||
const (
|
||||
appName = "integration-app"
|
||||
consensus = "consensus"
|
||||
)
|
||||
|
||||
// App is a test application that can be used to test the integration of modules.
|
||||
type App struct {
|
||||
*baseapp.BaseApp
|
||||
|
||||
ctx sdk.Context
|
||||
logger log.Logger
|
||||
queryHelper *baseapp.QueryServiceTestHelper
|
||||
}
|
||||
|
||||
// NewIntegrationApp creates an application for testing purposes. This application
|
||||
// is able to route messages to their respective handlers.
|
||||
func NewIntegrationApp(
|
||||
logger log.Logger,
|
||||
keys map[string]*storetypes.KVStoreKey,
|
||||
appCodec codec.Codec,
|
||||
addressCodec address.Codec,
|
||||
validatorCodec address.Codec,
|
||||
modules map[string]appmodule.AppModule,
|
||||
msgRouter *baseapp.MsgServiceRouter,
|
||||
grpcRouter *baseapp.GRPCQueryRouter,
|
||||
baseAppOptions ...func(*baseapp.BaseApp),
|
||||
) *App {
|
||||
db := coretesting.NewMemDB()
|
||||
|
||||
interfaceRegistry := codectypes.NewInterfaceRegistry()
|
||||
moduleManager := module.NewManagerFromMap(modules)
|
||||
moduleManager.RegisterInterfaces(interfaceRegistry)
|
||||
|
||||
txConfig := authtx.NewTxConfig(codec.NewProtoCodec(interfaceRegistry), addressCodec, validatorCodec, authtx.DefaultSignModes)
|
||||
bApp := baseapp.NewBaseApp(appName, logger, db, txConfig.TxDecoder(), append(baseAppOptions, baseapp.SetChainID(appName))...)
|
||||
bApp.MountKVStores(keys)
|
||||
|
||||
bApp.SetInitChainer(func(sdkCtx sdk.Context, _ *cmtabcitypes.InitChainRequest) (*cmtabcitypes.InitChainResponse, error) {
|
||||
for _, mod := range modules {
|
||||
if m, ok := mod.(module.HasGenesis); ok {
|
||||
if err := m.InitGenesis(sdkCtx, m.DefaultGenesis()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if m, ok := mod.(module.HasABCIGenesis); ok {
|
||||
if _, err := m.InitGenesis(sdkCtx, m.DefaultGenesis()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &cmtabcitypes.InitChainResponse{}, nil
|
||||
})
|
||||
|
||||
bApp.SetBeginBlocker(func(sdkCtx sdk.Context) (sdk.BeginBlock, error) {
|
||||
return moduleManager.BeginBlock(sdkCtx)
|
||||
})
|
||||
bApp.SetEndBlocker(func(sdkCtx sdk.Context) (sdk.EndBlock, error) {
|
||||
return moduleManager.EndBlock(sdkCtx)
|
||||
})
|
||||
|
||||
msgRouter.SetInterfaceRegistry(interfaceRegistry)
|
||||
bApp.SetMsgServiceRouter(msgRouter)
|
||||
grpcRouter.SetInterfaceRegistry(interfaceRegistry)
|
||||
bApp.SetGRPCQueryRouter(grpcRouter)
|
||||
|
||||
if consensusKey := keys[consensus]; consensusKey != nil {
|
||||
_ = bApp.CommitMultiStore().LoadLatestVersion()
|
||||
cps := newParamStore(runtime.NewKVStoreService(consensusKey), appCodec)
|
||||
params := cmttypes.ConsensusParamsFromProto(*simtestutil.DefaultConsensusParams) // This fills up missing param sections
|
||||
if err := cps.Set(sdk.NewContext(bApp.CommitMultiStore(), true, logger), params.ToProto()); err != nil { // at this point, because we haven't written state we don't have a real context
|
||||
panic(fmt.Errorf("failed to set consensus params: %w", err))
|
||||
}
|
||||
bApp.SetParamStore(cps)
|
||||
|
||||
if err := bApp.LoadLatestVersion(); err != nil {
|
||||
panic(fmt.Errorf("failed to load application version from store: %w", err))
|
||||
}
|
||||
|
||||
if _, err := bApp.InitChain(&cmtabcitypes.InitChainRequest{ChainId: appName, ConsensusParams: simtestutil.DefaultConsensusParams}); err != nil {
|
||||
panic(fmt.Errorf("failed to initialize application: %w", err))
|
||||
}
|
||||
} else {
|
||||
if err := bApp.LoadLatestVersion(); err != nil {
|
||||
panic(fmt.Errorf("failed to load application version from store: %w", err))
|
||||
}
|
||||
|
||||
if _, err := bApp.InitChain(&cmtabcitypes.InitChainRequest{ChainId: appName}); err != nil {
|
||||
panic(fmt.Errorf("failed to initialize application: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
bApp.SimWriteState() // forcing state write from init genesis like in sims
|
||||
_, err := bApp.Commit()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sdkCtx := bApp.NewContext(true).WithBlockHeader(cmtproto.Header{ChainID: appName})
|
||||
return &App{
|
||||
BaseApp: bApp,
|
||||
logger: logger,
|
||||
ctx: sdkCtx,
|
||||
queryHelper: baseapp.NewQueryServerTestHelper(sdkCtx, interfaceRegistry),
|
||||
}
|
||||
}
|
||||
|
||||
// RunMsg provides the ability to run a message and return the response.
|
||||
// In order to run a message, the application must have a handler for it.
|
||||
// These handlers are registered on the application message service router.
|
||||
// The result of the message execution is returned as an Any type.
|
||||
// That any type can be unmarshaled to the expected response type.
|
||||
// If the message execution fails, an error is returned.
|
||||
func (app *App) RunMsg(msg sdk.Msg, option ...Option) (*codectypes.Any, error) {
|
||||
// set options
|
||||
cfg := &Config{}
|
||||
for _, opt := range option {
|
||||
opt(cfg)
|
||||
}
|
||||
|
||||
if cfg.AutomaticCommit {
|
||||
defer func() {
|
||||
_, err := app.Commit()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
if cfg.AutomaticFinalizeBlock {
|
||||
height := app.LastBlockHeight() + 1
|
||||
if _, err := app.FinalizeBlock(&cmtabcitypes.FinalizeBlockRequest{Height: height, DecidedLastCommit: cmtabcitypes.CommitInfo{Votes: []cmtabcitypes.VoteInfo{}}}); err != nil {
|
||||
return nil, fmt.Errorf("failed to run finalize block: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
app.logger.Info("Running msg", "msg", msg.String())
|
||||
|
||||
handler := app.MsgServiceRouter().Handler(msg)
|
||||
if handler == nil {
|
||||
return nil, fmt.Errorf("handler is nil, can't route message %s: %+v", sdk.MsgTypeURL(msg), msg)
|
||||
}
|
||||
|
||||
msgResult, err := handler(app.ctx, msg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute message %s: %w", sdk.MsgTypeURL(msg), err)
|
||||
}
|
||||
|
||||
var response *codectypes.Any
|
||||
if len(msgResult.MsgResponses) > 0 {
|
||||
msgResponse := msgResult.MsgResponses[0]
|
||||
if msgResponse == nil {
|
||||
return nil, fmt.Errorf("got nil msg response %s in message result: %s", sdk.MsgTypeURL(msg), msgResult.String())
|
||||
}
|
||||
|
||||
response = msgResponse
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// NextBlock advances the chain height and returns the new height.
|
||||
func (app *App) NextBlock(txsblob ...[]byte) (int64, error) {
|
||||
height := app.LastBlockHeight() + 1
|
||||
if _, err := app.FinalizeBlock(&cmtabcitypes.FinalizeBlockRequest{
|
||||
Txs: txsblob, // txsBlob are raw txs to be executed in the block
|
||||
Height: height,
|
||||
DecidedLastCommit: cmtabcitypes.CommitInfo{Votes: []cmtabcitypes.VoteInfo{}},
|
||||
}); err != nil {
|
||||
return 0, fmt.Errorf("failed to run finalize block: %w", err)
|
||||
}
|
||||
|
||||
_, err := app.Commit()
|
||||
return height, err
|
||||
}
|
||||
|
||||
// Context returns the application context. It can be unwrapped to a sdk.Context,
|
||||
// with the sdk.UnwrapSDKContext function.
|
||||
func (app *App) Context() context.Context {
|
||||
return app.ctx
|
||||
}
|
||||
|
||||
// QueryHelper returns the application query helper.
|
||||
// It can be used when registering query services.
|
||||
func (app *App) QueryHelper() *baseapp.QueryServiceTestHelper {
|
||||
return app.queryHelper
|
||||
}
|
||||
|
||||
type paramStoreService struct {
|
||||
ParamsStore collections.Item[cmtproto.ConsensusParams]
|
||||
}
|
||||
|
||||
func newParamStore(storeService corestore.KVStoreService, cdc codec.Codec) paramStoreService {
|
||||
sb := collections.NewSchemaBuilder(storeService)
|
||||
return paramStoreService{
|
||||
ParamsStore: collections.NewItem(sb, collections.NewPrefix("Consensus"), "params", codec.CollValue[cmtproto.ConsensusParams](cdc)),
|
||||
}
|
||||
}
|
||||
|
||||
func (pss paramStoreService) Get(ctx context.Context) (cmtproto.ConsensusParams, error) {
|
||||
return pss.ParamsStore.Get(ctx)
|
||||
}
|
||||
|
||||
func (pss paramStoreService) Has(ctx context.Context) (bool, error) {
|
||||
return pss.ParamsStore.Has(ctx)
|
||||
}
|
||||
|
||||
func (pss paramStoreService) Set(ctx context.Context, cp cmtproto.ConsensusParams) error {
|
||||
return pss.ParamsStore.Set(ctx, cp)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user