Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Morse->Shannon Migration] feat: implement claim Morse pokt #1059

Open
wants to merge 16 commits into
base: issues/1034/scaffold/msg_claim_morse_account
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ go_mockgen: ## Use `mockgen` to generate mocks used for testing purposes of all
go generate ./x/service/types/
go generate ./x/proof/types/
go generate ./x/tokenomics/types/
go generate ./x/migration/types/
find . -name interface.go | xargs -I {} go generate {}

.PHONY: go_testgen_fixtures
Expand Down
756 changes: 734 additions & 22 deletions api/poktroll/migration/event.pulsar.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions app/app_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ var (
{Account: sessionmoduletypes.ModuleName, Permissions: []string{authtypes.Minter, authtypes.Burner, authtypes.Staking}},
{Account: tokenomicsmoduletypes.ModuleName, Permissions: []string{authtypes.Minter, authtypes.Burner, authtypes.Staking}},
{Account: proofmoduletypes.ModuleName, Permissions: []string{authtypes.Minter, authtypes.Burner, authtypes.Staking}},
{Account: migrationmoduletypes.ModuleName, Permissions: []string{authtypes.Minter}},
// this line is used by starport scaffolding # stargate/app/maccPerms }
}

Expand Down
15 changes: 15 additions & 0 deletions proto/poktroll/migration/event.proto
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,18 @@ message EventImportMorseClaimableAccounts {
// NOTE: Application and supplier actor stakes are consolidated into their corresponding account balances.
uint64 num_accounts = 3 [(gogoproto.jsontag) = "num_accounts"];
}

// EventMorseAccountClaimed is emitted when a MorseAccount is claimed on-chain.
message EventMorseAccountClaimed {
// The height (on Shannon) at which the claim was executed (i.e. claimed).
int64 claimed_at_height = 1 [(gogoproto.jsontag) = "claimed_at_height"];

// The balance which was claimed.
cosmos.base.v1beta1.Coin claimed_balance = 2 [(gogoproto.jsontag) = "claimed_balance", (gogoproto.nullable) = false];

// The bech32-encoded address of the Shannon account to which the claimed balance will be minted.
string shannon_dest_address = 3 [(cosmos_proto.scalar) = "cosmos.AddressString", (gogoproto.jsontag) = "shannon_dest_address"];

// The hex-encoded address of the Morse account whose balance will be claimed.
string morse_src_address = 4 [(gogoproto.jsontag) = "morse_src_address"];
}
46 changes: 18 additions & 28 deletions tests/integration/application/application_transfer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"testing"

cosmostypes "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"

Expand Down Expand Up @@ -81,7 +80,7 @@ func (s *appTransferTestSuite) SetupTest() {
})

// Assert the onchain state shows the application 3 as NOT staked.
_, queryErr := s.GetAppQueryClient().GetApplication(s.SdkCtx(), s.app3)
_, queryErr := s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), s.app3)
require.ErrorContains(s.T(), queryErr, "application not found")
require.ErrorContains(s.T(), queryErr, s.app3)
}
Expand Down Expand Up @@ -110,7 +109,7 @@ func (s *appTransferTestSuite) TestSingleSourceToNonexistentDestinationSucceeds(
require.EqualValues(s.T(), expectedPendingTransfer, pendingTransfer)

// Query and assert application pending transfer field updated in the store.
foundApp1, err := s.GetAppQueryClient().GetApplication(s.SdkCtx(), s.app1)
foundApp1, err := s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), s.app1)
require.NoError(s.T(), err)
require.EqualValues(s.T(), expectedPendingTransfer, foundApp1.GetPendingTransfer())

Expand All @@ -129,7 +128,7 @@ func (s *appTransferTestSuite) TestSingleSourceToNonexistentDestinationSucceeds(
s.GetApp().NextBlocks(s.T(), int(blocksUntilTransferEndHeight)-1)

// Assert that app1 is in transfer period.
foundApp1, err = s.GetAppQueryClient().GetApplication(s.SdkCtx(), s.app1)
foundApp1, err = s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), s.app1)
require.NoError(s.T(), err)

require.Equal(s.T(), s.app1, foundApp1.GetAddress())
Expand All @@ -139,7 +138,7 @@ func (s *appTransferTestSuite) TestSingleSourceToNonexistentDestinationSucceeds(
s.GetApp().NextBlock(s.T())

// Query for and assert that the destination application was created.
foundApp3, err := s.GetAppQueryClient().GetApplication(s.SdkCtx(), s.app3)
foundApp3, err := s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), s.app3)
require.NoError(s.T(), err)

// Assert that the destination application was created with the correct state.
Expand All @@ -164,21 +163,18 @@ func (s *appTransferTestSuite) TestSingleSourceToNonexistentDestinationSucceeds(
s.shouldObserveTransferEndEvent(&foundApp3, s.app1)

// Assert that app1 is unstaked.
_, err = s.GetAppQueryClient().GetApplication(s.SdkCtx(), s.app1)
_, err = s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), s.app1)
require.ErrorContains(s.T(), err, "application not found")
require.ErrorContains(s.T(), err, s.app1)

// Assert that app1's bank balance has not changed.
balanceRes, err := s.GetBankQueryClient().Balance(s.SdkCtx(), &banktypes.QueryBalanceRequest{
Address: s.app1,
Denom: volatile.DenomuPOKT,
})
balance, err := s.GetBankQueryClient(s.T()).GetBalance(s.SdkCtx(), s.app1)
require.NoError(s.T(), err)
require.NotNil(s.T(), balanceRes)
require.NotNil(s.T(), balance)

require.EqualValues(s.T(),
cosmostypes.NewInt64Coin(volatile.DenomuPOKT, appFundAmount-stakeAmount),
*balanceRes.GetBalance(),
*balance,
)
}

Expand Down Expand Up @@ -228,7 +224,7 @@ func (s *appTransferTestSuite) TestMultipleSourceToSameNonexistentDestinationMer
require.EqualValues(s.T(), expectedPendingTransfer, pendingTransfer)

// Query and assert application pending transfer field updated in the store.
foundSrcApp, srcAppErr := s.GetAppQueryClient().GetApplication(s.SdkCtx(), expectedSrcBech32)
foundSrcApp, srcAppErr := s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), expectedSrcBech32)
require.NoError(s.T(), srcAppErr)
require.EqualValues(s.T(), expectedPendingTransfer, foundSrcApp.GetPendingTransfer())

Expand Down Expand Up @@ -257,7 +253,7 @@ func (s *appTransferTestSuite) TestMultipleSourceToSameNonexistentDestinationMer
s.GetApp().NextBlocks(s.T(), int(blocksUntilTransferEndHeight)-1)

// Assert that app1 is in transfer period.
foundApp1, err := s.GetAppQueryClient().GetApplication(s.SdkCtx(), s.app1)
foundApp1, err := s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), s.app1)
require.NoError(s.T(), err)

require.Equal(s.T(), s.app1, foundApp1.GetAddress())
Expand All @@ -267,7 +263,7 @@ func (s *appTransferTestSuite) TestMultipleSourceToSameNonexistentDestinationMer
s.GetApp().NextBlock(s.T())

// Assert that app3 is staked with the sum amount: app1 + app2.
foundApp3, err := s.GetAppQueryClient().GetApplication(s.SdkCtx(), s.app3)
foundApp3, err := s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), s.app3)
require.NoError(s.T(), err)

require.Equal(s.T(), s.app3, foundApp3.GetAddress())
Expand Down Expand Up @@ -308,30 +304,24 @@ func (s *appTransferTestSuite) TestMultipleSourceToSameNonexistentDestinationMer
require.Equal(s.T(), len(expectedApp3ServiceIds), len(foundApp3.GetServiceConfigs()))

// Assert that app1 is unstaked.
foundApp1, err = s.GetAppQueryClient().GetApplication(s.SdkCtx(), s.app1)
foundApp1, err = s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), s.app1)
require.ErrorContains(s.T(), err, "application not found")
require.ErrorContains(s.T(), err, s.app1)

// Assert that app2 is unstaked.
_, err = s.GetAppQueryClient().GetApplication(s.SdkCtx(), s.app2)
_, err = s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), s.app2)
require.ErrorContains(s.T(), err, "application not found")
require.ErrorContains(s.T(), err, s.app2)

// Assert that app1's bank balance has not changed
balRes, err := s.GetBankQueryClient().Balance(s.SdkCtx(), &banktypes.QueryBalanceRequest{
Address: s.app1,
Denom: volatile.DenomuPOKT,
})
balance, err := s.GetBankQueryClient(s.T()).GetBalance(s.SdkCtx(), s.app1)
require.NoError(s.T(), err)
require.Equal(s.T(), appFundAmount-stakeAmount, balRes.GetBalance().Amount.Int64())
require.Equal(s.T(), appFundAmount-stakeAmount, balance.Amount.Int64())

// Assert that app2's bank balance has not changed
balRes, err = s.GetBankQueryClient().Balance(s.SdkCtx(), &banktypes.QueryBalanceRequest{
Address: s.app2,
Denom: volatile.DenomuPOKT,
})
balance, err = s.GetBankQueryClient(s.T()).GetBalance(s.SdkCtx(), s.app2)
require.NoError(s.T(), err)
require.Equal(s.T(), appFundAmount-stakeAmount, balRes.GetBalance().Amount.Int64())
require.Equal(s.T(), appFundAmount-stakeAmount, balance.Amount.Int64())
}

// TODO_TEST:
Expand Down Expand Up @@ -391,7 +381,7 @@ func (s *appTransferTestSuite) setupStakeApps(appBech32ToServiceIdsMap map[strin
require.Equal(s.T(), stakeAmount, stakeAppRes.GetApplication().GetStake().Amount.Int64())

// Assert the onchain state shows the application as staked.
foundApp, queryErr := s.GetAppQueryClient().GetApplication(s.SdkCtx(), appBech32)
foundApp, queryErr := s.GetAppQueryClient(s.T()).GetApplication(s.SdkCtx(), appBech32)
require.NoError(s.T(), queryErr)
require.Equal(s.T(), appBech32, foundApp.GetAddress())
require.Equal(s.T(), stakeAmount, foundApp.GetStake().Amount.Int64())
Expand Down
100 changes: 100 additions & 0 deletions tests/integration/migration/morse_account_import_and_claim_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package migration

import (
"testing"

"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"

"github.com/pokt-network/poktroll/app/volatile"
"github.com/pokt-network/poktroll/testutil/integration/suites"
"github.com/pokt-network/poktroll/testutil/sample"
migrationtypes "github.com/pokt-network/poktroll/x/migration/types"
)

type MigrationModuleTestSuite struct {
suites.MigrationModuleSuite

// numMorseClaimableAccounts is the number of morse claimable accounts to
// generate when calling #GenerateMorseAccountState.
numMorseClaimableAccounts int
}

func (s *MigrationModuleTestSuite) SetupTest() {
// Initialize a new integration app for the suite.
s.NewApp(s.T())

s.numMorseClaimableAccounts = 10

// Assign the app to nested suites.
// TODO_UPNEXT(@bryanchriswhite, #1043): Initialize the app module suite.
// s.AppSuite.SetApp(s.GetApp())
}

func TestMigrationModuleSuite(t *testing.T) {
suite.Run(t, &MigrationModuleTestSuite{})
}

// TestImportMorseClaimableAccounts tests claiming of morse claimable accounts.
// It only claims account balances and does not test staking any actors as a result of claiming.
func (s *MigrationModuleTestSuite) TestImportMorseClaimableAccounts() {
s.GenerateMorseAccountState(s.T(), s.numMorseClaimableAccounts)
msgImportRes := s.ImportMorseClaimableAccounts(s.T())
morseAccountStateHash, err := s.GetAccountState(s.T()).GetHash()
require.NoError(s.T(), err)

expectedMsgImportRes := &migrationtypes.MsgImportMorseClaimableAccountsResponse{
StateHash: morseAccountStateHash,
NumAccounts: uint64(s.numMorseClaimableAccounts),
}
require.Equal(s.T(), expectedMsgImportRes, msgImportRes)
}

// TestClaimMorseAccount tests claiming of a MorseClaimableAccounts.
// It only exercises claiming of account balances and does not exercise
// the staking any actors as a result of claiming.
func (s *MigrationModuleTestSuite) TestClaimMorseAccount() {
s.GenerateMorseAccountState(s.T(), s.numMorseClaimableAccounts)
s.ImportMorseClaimableAccounts(s.T())

shannonDestAddr := sample.AccAddress()

bankClient := s.GetBankQueryClient(s.T())
shannonDestBalance, err := bankClient.GetBalance(s.SdkCtx(), shannonDestAddr)
require.NoError(s.T(), err)
require.True(s.T(), shannonDestBalance.IsZero())

morseSrcAddr, claimAccountRes := s.ClaimMorseAccount(s.T(), 1, shannonDestAddr)

expectedMorseClaimableAccount := s.GetAccountState(s.T()).Accounts[0]
expectedBalance := expectedMorseClaimableAccount.GetUnstakedBalance().
Add(expectedMorseClaimableAccount.GetApplicationStake()).
Add(expectedMorseClaimableAccount.GetSupplierStake())

expectedClaimAccountRes := &migrationtypes.MsgClaimMorseAccountResponse{
MorseSrcAddress: morseSrcAddr,
ClaimedBalance: expectedBalance,
ClaimedAtHeight: s.SdkCtx().BlockHeight() - 1,
}
require.Equal(s.T(), expectedClaimAccountRes, claimAccountRes)

// Assert that the MorseClaimableAccount was updated on-chain.
expectedMorseClaimableAccount.ShannonDestAddress = shannonDestAddr
expectedMorseClaimableAccount.ClaimedAtHeight = s.SdkCtx().BlockHeight() - 1
morseClaimableAccount := s.QueryMorseClaimableAccount(s.T(), morseSrcAddr)
require.Equal(s.T(), expectedMorseClaimableAccount, morseClaimableAccount)

// Assert that the shannonDestAddr account balance has been updated.
shannonDestBalance, err = bankClient.GetBalance(s.GetApp().GetSdkCtx(), shannonDestAddr)
require.NoError(s.T(), err)
require.Equal(s.T(), expectedBalance, *shannonDestBalance)

// Assert that the migration module account balance returns to zero.
migrationModuleAddress := authtypes.NewModuleAddress(migrationtypes.ModuleName).String()
migrationModuleBalance, err := bankClient.GetBalance(s.SdkCtx(), migrationModuleAddress)
require.NoError(s.T(), err)
require.Equal(s.T(), sdk.NewCoin(volatile.DenomuPOKT, math.ZeroInt()), *migrationModuleBalance)
}
58 changes: 32 additions & 26 deletions testutil/integration/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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(
Expand All @@ -287,6 +291,7 @@ func NewCompleteIntegrationApp(t *testing.T, opts ...IntegrationAppOptionFn) *Ap
prooftypes.StoreKey,
servicetypes.StoreKey,
authtypes.StoreKey,
migrationtypes.StoreKey,
)

// Prepare the codec
Expand Down Expand Up @@ -322,6 +327,7 @@ func NewCompleteIntegrationApp(t *testing.T, opts ...IntegrationAppOptionFn) *Ap
apptypes.ModuleName: {authtypes.Minter, authtypes.Burner, authtypes.Staking},
suppliertypes.ModuleName: {authtypes.Minter, authtypes.Burner, authtypes.Staking},
prooftypes.ModuleName: {authtypes.Minter, authtypes.Burner},
migrationtypes.ModuleName: {authtypes.Minter},
}

// Prepare the account keeper and module
Expand Down Expand Up @@ -512,6 +518,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)
Expand Down Expand Up @@ -544,6 +566,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
Expand All @@ -563,32 +586,11 @@ 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)
}

// 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
Expand Down Expand Up @@ -963,6 +965,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
Expand Down
Loading