refactor(testutil): Removing testutil integration (#23091)

This commit is contained in:
son trinh 2024-12-30 20:18:49 +07:00 committed by GitHub
parent dafa93f05d
commit 4fb2347af4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 225 additions and 1857 deletions

View File

@ -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))
}

View File

@ -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))
}

View File

@ -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(),
)

View File

@ -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,
}
}

View File

@ -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)
}
}

View File

@ -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)
})
}

View File

@ -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)
}

View File

@ -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
}
}
}
})
}
}

View File

@ -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)
}

View File

@ -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
}

View 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)
}
}

View 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)
}

View 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
}

View File

@ -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

View File

@ -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

View File

@ -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
}
}

View File

@ -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)
}