diff --git a/testutil/integration/app.go b/testutil/integration/app.go index 04305089a..682438cf1 100644 --- a/testutil/integration/app.go +++ b/testutil/integration/app.go @@ -61,6 +61,9 @@ import ( gatewaykeeper "github.com/pokt-network/poktroll/x/gateway/keeper" gateway "github.com/pokt-network/poktroll/x/gateway/module" gatewaytypes "github.com/pokt-network/poktroll/x/gateway/types" + migrationkeeper "github.com/pokt-network/poktroll/x/migration/keeper" + migration "github.com/pokt-network/poktroll/x/migration/module" + migrationtypes "github.com/pokt-network/poktroll/x/migration/types" proofkeeper "github.com/pokt-network/poktroll/x/proof/keeper" proof "github.com/pokt-network/poktroll/x/proof/module" prooftypes "github.com/pokt-network/poktroll/x/proof/types" @@ -273,6 +276,7 @@ func NewCompleteIntegrationApp(t *testing.T, opts ...IntegrationAppOptionFn) *Ap cosmostypes.RegisterInterfaces(registry) cryptocodec.RegisterInterfaces(registry) banktypes.RegisterInterfaces(registry) + migrationtypes.RegisterInterfaces(registry) // Prepare all the store keys storeKeys := storetypes.NewKVStoreKeys( @@ -287,6 +291,7 @@ func NewCompleteIntegrationApp(t *testing.T, opts ...IntegrationAppOptionFn) *Ap prooftypes.StoreKey, servicetypes.StoreKey, authtypes.StoreKey, + migrationtypes.StoreKey, ) // Prepare the codec @@ -512,6 +517,22 @@ func NewCompleteIntegrationApp(t *testing.T, opts ...IntegrationAppOptionFn) *Ap supplierKeeper, ) + // Prepare the migration keeper and module + migrationKeeper := migrationkeeper.NewKeeper( + cdc, + runtime.NewKVStoreService(storeKeys[migrationtypes.StoreKey]), + logger, + authority.String(), + accountKeeper, + bankKeeper, + ) + migrationModule := migration.NewAppModule( + cdc, + migrationKeeper, + accountKeeper, + bankKeeper, + ) + // Prepare the message & query routers msgRouter := baseapp.NewMsgServiceRouter() queryHelper := baseapp.NewQueryServerTestHelper(sdkCtx, registry) @@ -544,6 +565,7 @@ func NewCompleteIntegrationApp(t *testing.T, opts ...IntegrationAppOptionFn) *Ap prooftypes.ModuleName: proofModule, authtypes.ModuleName: authModule, sessiontypes.ModuleName: sessionModule, + migrationtypes.ModuleName: migrationModule, } // Initialize the integration integrationApp @@ -563,32 +585,39 @@ func NewCompleteIntegrationApp(t *testing.T, opts ...IntegrationAppOptionFn) *Ap opts..., ) - // Register the message servers - banktypes.RegisterMsgServer(msgRouter, bankkeeper.NewMsgServerImpl(bankKeeper)) - tokenomicstypes.RegisterMsgServer(msgRouter, tokenomicskeeper.NewMsgServerImpl(tokenomicsKeeper)) - servicetypes.RegisterMsgServer(msgRouter, servicekeeper.NewMsgServerImpl(serviceKeeper)) - sharedtypes.RegisterMsgServer(msgRouter, sharedkeeper.NewMsgServerImpl(sharedKeeper)) - gatewaytypes.RegisterMsgServer(msgRouter, gatewaykeeper.NewMsgServerImpl(gatewayKeeper)) - apptypes.RegisterMsgServer(msgRouter, appkeeper.NewMsgServerImpl(applicationKeeper)) - suppliertypes.RegisterMsgServer(msgRouter, supplierkeeper.NewMsgServerImpl(supplierKeeper)) - prooftypes.RegisterMsgServer(msgRouter, proofkeeper.NewMsgServerImpl(proofKeeper)) - authtypes.RegisterMsgServer(msgRouter, authkeeper.NewMsgServerImpl(accountKeeper)) - sessiontypes.RegisterMsgServer(msgRouter, sessionkeeper.NewMsgServerImpl(sessionKeeper)) - authz.RegisterMsgServer(msgRouter, authzKeeper) - - // Register query servers - banktypes.RegisterQueryServer(queryHelper, bankKeeper) - authz.RegisterQueryServer(queryHelper, authzKeeper) - tokenomicstypes.RegisterQueryServer(queryHelper, tokenomicsKeeper) - servicetypes.RegisterQueryServer(queryHelper, serviceKeeper) - sharedtypes.RegisterQueryServer(queryHelper, sharedKeeper) - gatewaytypes.RegisterQueryServer(queryHelper, gatewayKeeper) - apptypes.RegisterQueryServer(queryHelper, applicationKeeper) - suppliertypes.RegisterQueryServer(queryHelper, supplierKeeper) - prooftypes.RegisterQueryServer(queryHelper, proofKeeper) - // TODO_TECHDEBT: What is the query server for authtypes? - // authtypes.RegisterQueryServer(queryHelper, accountKeeper) - sessiontypes.RegisterQueryServer(queryHelper, sessionKeeper) + // Register the message & query servers. + configurator := module.NewConfigurator(cdc, msgRouter, queryHelper) + for _, mod := range integrationApp.GetModuleManager().Modules { + mod.(module.HasServices).RegisterServices(configurator) + } + + //banktypes.RegisterMsgServer(msgRouter, bankkeeper.NewMsgServerImpl(bankKeeper)) + //tokenomicstypes.RegisterMsgServer(msgRouter, tokenomicskeeper.NewMsgServerImpl(tokenomicsKeeper)) + //servicetypes.RegisterMsgServer(msgRouter, servicekeeper.NewMsgServerImpl(serviceKeeper)) + //sharedtypes.RegisterMsgServer(msgRouter, sharedkeeper.NewMsgServerImpl(sharedKeeper)) + //gatewaytypes.RegisterMsgServer(msgRouter, gatewaykeeper.NewMsgServerImpl(gatewayKeeper)) + //apptypes.RegisterMsgServer(msgRouter, appkeeper.NewMsgServerImpl(applicationKeeper)) + //suppliertypes.RegisterMsgServer(msgRouter, supplierkeeper.NewMsgServerImpl(supplierKeeper)) + //prooftypes.RegisterMsgServer(msgRouter, proofkeeper.NewMsgServerImpl(proofKeeper)) + //authtypes.RegisterMsgServer(msgRouter, authkeeper.NewMsgServerImpl(accountKeeper)) + //sessiontypes.RegisterMsgServer(msgRouter, sessionkeeper.NewMsgServerImpl(sessionKeeper)) + //authz.RegisterMsgServer(msgRouter, authzKeeper) + //migrationtypes.RegisterMsgServer(msgRouter, migrationkeeper.NewMsgServerImpl(migrationKeeper)) + // + //// Register query servers + //banktypes.RegisterQueryServer(queryHelper, bankKeeper) + //authz.RegisterQueryServer(queryHelper, authzKeeper) + //tokenomicstypes.RegisterQueryServer(queryHelper, tokenomicsKeeper) + //servicetypes.RegisterQueryServer(queryHelper, serviceKeeper) + //sharedtypes.RegisterQueryServer(queryHelper, sharedKeeper) + //gatewaytypes.RegisterQueryServer(queryHelper, gatewayKeeper) + //apptypes.RegisterQueryServer(queryHelper, applicationKeeper) + //suppliertypes.RegisterQueryServer(queryHelper, supplierKeeper) + //prooftypes.RegisterQueryServer(queryHelper, proofKeeper) + //// TODO_TECHDEBT: What is the query server for authtypes? + //// authtypes.RegisterQueryServer(queryHelper, accountKeeper) + //sessiontypes.RegisterQueryServer(queryHelper, sessionKeeper) + //migrationtypes.RegisterQueryServer(queryHelper, migrationKeeper) // Need to go to the next block to finalize the genesis and setup. // This has to be after the params are set, as the params are stored in the @@ -963,6 +992,10 @@ func (app *App) setupDefaultActorsState( app.NextBlock(t) } +func (app *App) GetModuleManager() module.Manager { + return app.moduleManager +} + // fundAccount mints and sends amountUpokt tokens to the given recipientAddr. // // TODO_IMPROVE: Eliminate usage of and remove this function in favor of diff --git a/testutil/keeper/migration.go b/testutil/keeper/migration.go index fd85baf9f..ac005904b 100644 --- a/testutil/keeper/migration.go +++ b/testutil/keeper/migration.go @@ -1,6 +1,7 @@ package keeper import ( + "context" "testing" "cosmossdk.io/log" @@ -15,8 +16,10 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" + "github.com/pokt-network/poktroll/testutil/proof/mocks" "github.com/pokt-network/poktroll/x/migration/keeper" "github.com/pokt-network/poktroll/x/migration/types" ) @@ -33,11 +36,29 @@ func MigrationKeeper(t testing.TB) (keeper.Keeper, sdk.Context) { cdc := codec.NewProtoCodec(registry) authority := authtypes.NewModuleAddress(govtypes.ModuleName) + ctrl := gomock.NewController(t) + mockBankKeeper := mocks.NewMockBankKeeper(ctrl) + mockBankKeeper.EXPECT(). + SpendableCoins(gomock.Any(), gomock.Any()). + DoAndReturn( + func(ctx context.Context, addr sdk.AccAddress) sdk.Coins { + mapMu.RLock() + defer mapMu.RUnlock() + if coins, ok := mapAccAddrCoins[addr.String()]; ok { + return coins + } + return sdk.Coins{} + }, + ).AnyTimes() + mockAccountKeeper := mocks.NewMockAccountKeeper(ctrl) + k := keeper.NewKeeper( cdc, runtime.NewKVStoreService(storeKey), log.NewNopLogger(), authority.String(), + mockAccountKeeper, + mockBankKeeper, ) ctx := sdk.NewContext(stateStore, cmtproto.Header{}, false, log.NewNopLogger()) diff --git a/testutil/keeper/tokenomics.go b/testutil/keeper/tokenomics.go index 31f5dc53a..4631837d5 100644 --- a/testutil/keeper/tokenomics.go +++ b/testutil/keeper/tokenomics.go @@ -36,6 +36,8 @@ import ( apptypes "github.com/pokt-network/poktroll/x/application/types" gatewaykeeper "github.com/pokt-network/poktroll/x/gateway/keeper" gatewaytypes "github.com/pokt-network/poktroll/x/gateway/types" + migrationkeeper "github.com/pokt-network/poktroll/x/migration/keeper" + migrationtypes "github.com/pokt-network/poktroll/x/migration/types" proofkeeper "github.com/pokt-network/poktroll/x/proof/keeper" prooftypes "github.com/pokt-network/poktroll/x/proof/types" servicekeeper "github.com/pokt-network/poktroll/x/service/keeper" @@ -67,6 +69,7 @@ type TokenomicsModuleKeepers struct { tokenomicstypes.SharedKeeper tokenomicstypes.SessionKeeper tokenomicstypes.ServiceKeeper + tokenomicstypes.MigrationKeeper Codec *codec.ProtoCodec } @@ -324,6 +327,7 @@ func NewTokenomicsModuleKeepers( prooftypes.StoreKey, sharedtypes.StoreKey, servicetypes.StoreKey, + migrationtypes.StoreKey, ) // Construct a multistore & mount store keys for each keeper that will interact with the state store. @@ -523,6 +527,22 @@ func NewTokenomicsModuleKeepers( require.NoError(t, err) } + migrationKeeper := migrationkeeper.NewKeeper( + cdc, + runtime.NewKVStoreService(keys[migrationtypes.StoreKey]), + logger, + authority.String(), + accountKeeper, + bankKeeper, + ) + + require.NoError(t, migrationKeeper.SetParams(sdkCtx, migrationtypes.DefaultParams())) + + if params, ok := cfg.moduleParams[migrationtypes.ModuleName]; ok { + err := migrationKeeper.SetParams(ctx, *params.(*migrationtypes.Params)) + require.NoError(t, err) + } + keepers := TokenomicsModuleKeepers{ Keeper: &tokenomicsKeeper, AccountKeeper: &accountKeeper, @@ -533,6 +553,7 @@ func NewTokenomicsModuleKeepers( SharedKeeper: &sharedKeeper, SessionKeeper: &sessionKeeper, ServiceKeeper: &serviceKeeper, + MigrationKeeper: &migrationKeeper, Codec: cdc, } diff --git a/testutil/testmigration/fixtures.go b/testutil/testmigration/fixtures.go index fb36d92ba..4329fcf72 100644 --- a/testutil/testmigration/fixtures.go +++ b/testutil/testmigration/fixtures.go @@ -3,7 +3,6 @@ package testmigration import ( "encoding/binary" "fmt" - "math/rand" cometcrypto "github.com/cometbft/cometbft/crypto/ed25519" cmtjson "github.com/cometbft/cometbft/libs/json" @@ -59,9 +58,8 @@ func NewMorseStateExportAndAccountState( } for i := 1; i < numAccounts+1; i++ { - seedUint := rand.Uint64() seedBz := make([]byte, 8) - binary.LittleEndian.PutUint64(seedBz, seedUint) + binary.LittleEndian.PutUint64(seedBz, uint64(i)) privKey := cometcrypto.GenPrivKeyFromSecret(seedBz) pubKey := privKey.PubKey() balanceAmount := int64(1e6*i + i) // i_000_00i diff --git a/x/migration/keeper/keeper.go b/x/migration/keeper/keeper.go index af25b6e3d..b4019db3f 100644 --- a/x/migration/keeper/keeper.go +++ b/x/migration/keeper/keeper.go @@ -20,6 +20,9 @@ type ( // the address capable of executing a MsgUpdateParams message. Typically, this // should be the x/gov module account. authority string + + accountKeeper types.AccountKeeper + bankKeeper types.BankKeeper } ) @@ -28,6 +31,8 @@ func NewKeeper( storeService store.KVStoreService, logger log.Logger, authority string, + accountKeeper types.AccountKeeper, + bankKeeper types.BankKeeper, ) Keeper { if _, err := sdk.AccAddressFromBech32(authority); err != nil { @@ -35,10 +40,12 @@ func NewKeeper( } return Keeper{ - cdc: cdc, - storeService: storeService, - authority: authority, - logger: logger, + cdc: cdc, + storeService: storeService, + authority: authority, + logger: logger, + accountKeeper: accountKeeper, + bankKeeper: bankKeeper, } } diff --git a/x/migration/keeper/msg_server_claim_morse_upokt_test.go b/x/migration/keeper/msg_server_claim_morse_upokt_test.go new file mode 100644 index 000000000..e6e32ed4c --- /dev/null +++ b/x/migration/keeper/msg_server_claim_morse_upokt_test.go @@ -0,0 +1,80 @@ +package keeper_test + +import ( + "encoding/binary" + "testing" + + "cosmossdk.io/depinject" + cometcrypto "github.com/cometbft/cometbft/crypto/ed25519" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/cosmos/gogoproto/proto" + "github.com/stretchr/testify/require" + + "github.com/pokt-network/poktroll/app/volatile" + "github.com/pokt-network/poktroll/pkg/client/query" + "github.com/pokt-network/poktroll/testutil/integration" + "github.com/pokt-network/poktroll/testutil/sample" + "github.com/pokt-network/poktroll/testutil/testmigration" + "github.com/pokt-network/poktroll/x/migration/types" +) + +func TestMsgServer_ClaimMorsePokt(t *testing.T) { + app := integration.NewCompleteIntegrationApp(t) + + numAccounts := 10 + _, accountState := testmigration.NewMorseStateExportAndAccountState(t, numAccounts) + + // Ensure that the MorseAccountState is set initially. + resAny, err := app.RunMsg(t, &types.MsgCreateMorseAccountState{ + Authority: authtypes.NewModuleAddress(govtypes.ModuleName).String(), + MorseAccountState: *accountState, + }) + require.NoError(t, err) + + createStateRes, ok := resAny.(*types.MsgCreateMorseAccountStateResponse) + require.True(t, ok) + t.Logf("createStateRes: %+v", createStateRes) + + shannonDestAddr := sample.AccAddress() + + deps := depinject.Supply(app.QueryHelper()) + bankClient, err := query.NewBankQuerier(deps) + require.NoError(t, err) + + balance, err := bankClient.GetBalance(app.GetSdkCtx(), shannonDestAddr) + require.NoError(t, err) + require.Equal(t, int64(0), balance.Amount.Int64()) + + // TODO_IN_THIS_COMMIT: comment or refactor testutil... + seedBz := make([]byte, 8) + binary.LittleEndian.PutUint64(seedBz, uint64(1)) + privKey := cometcrypto.GenPrivKeyFromSecret(seedBz) + morseDestAddr := privKey.PubKey().Address().String() + require.Equal(t, morseDestAddr, accountState.Accounts[0].Address.String()) + + morseClaimMsg := types.NewMsgClaimMorsePokt(shannonDestAddr, morseDestAddr, nil) + morseClaimMsgUnsignedBz, err := proto.Marshal(morseClaimMsg) + require.NoError(t, err) + + signature, err := privKey.Sign(morseClaimMsgUnsignedBz) + require.NoError(t, err) + + morseClaimMsg.MorseSignature = signature + resAny, err = app.RunMsg(t, morseClaimMsg) + require.NoError(t, err) + + expectedBalance := sdk.NewInt64Coin(volatile.DenomuPOKT, 1110111) + expectedStateHash, err := accountState.GetHash() + require.NoError(t, err) + + claimAccountRes, ok := resAny.(*types.MsgClaimMorsePoktResponse) + require.True(t, ok) + require.Equal(t, expectedStateHash, claimAccountRes.GetStateHash()) + require.Equal(t, expectedBalance, claimAccountRes.GetBalance()) + + balance, err = bankClient.GetBalance(app.GetSdkCtx(), shannonDestAddr) + require.NoError(t, err) + require.Equal(t, expectedBalance, balance) +} diff --git a/x/migration/module/module.go b/x/migration/module/module.go index 9632fab53..53cb8fc7d 100644 --- a/x/migration/module/module.go +++ b/x/migration/module/module.go @@ -202,6 +202,8 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { in.StoreService, in.Logger, authority.String(), + in.AccountKeeper, + in.BankKeeper, ) m := NewAppModule( in.Cdc, diff --git a/x/tokenomics/types/expected_keepers.go b/x/tokenomics/types/expected_keepers.go index 9d555f4e2..a43b72b40 100644 --- a/x/tokenomics/types/expected_keepers.go +++ b/x/tokenomics/types/expected_keepers.go @@ -9,6 +9,7 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" apptypes "github.com/pokt-network/poktroll/x/application/types" + migrationtypes "github.com/pokt-network/poktroll/x/migration/types" prooftypes "github.com/pokt-network/poktroll/x/proof/types" servicetypes "github.com/pokt-network/poktroll/x/service/types" sessiontypes "github.com/pokt-network/poktroll/x/session/types" @@ -98,3 +99,8 @@ type ServiceKeeper interface { GetParams(ctx context.Context) servicetypes.Params SetParams(ctx context.Context, params servicetypes.Params) error } + +type MigrationKeeper interface { + SetMorseAccountState(ctx context.Context, morseAccountState migrationtypes.MorseAccountState) + GetMorseAccountState(ctx context.Context) (migrationtypes.MorseAccountState, bool) +}