-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Application] Enforce minimum stake when burning (#848)
## Summary Updates `ProcessTokenLogicModules()` logic to unbond applications whose stake is below the minimum **after** processing all TLMs. ## Dependencies - #809 - #843 - #844 - #845 - #847 ## Dependents - #849 - #850 - #857 - #852 - #861 - #851 - #863 ## Issue - #612 ## Type of change Select one or more from the following: - [x] New feature, functionality or library - [ ] Consensus breaking; add the `consensus-breaking` label if so. See #791 for details - [ ] Bug fix - [ ] Code health or cleanup - [ ] Documentation - [ ] Other (specify) ## Testing - [ ] **Documentation**: `make docusaurus_start`; only needed if you make doc changes - [x] **Unit Tests**: `make go_develop_and_test` - [ ] **LocalNet E2E Tests**: `make test_e2e` - [ ] **DevNet E2E Tests**: Add the `devnet-test-e2e` label to the PR. ## Sanity Checklist - [x] I have tested my changes using the available tooling - [x] I have commented my code - [x] I have performed a self-review of my own code; both comments & source code - [ ] I create and reference any new tickets, if applicable - [x] I have left TODOs throughout the codebase, if applicable --------- Co-authored-by: Redouane Lakrache <[email protected]> Co-authored-by: Daniel Olshansky <[email protected]> Co-authored-by: red-0ne <[email protected]>
- Loading branch information
1 parent
879401e
commit b60dac9
Showing
15 changed files
with
304 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
package application | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
cosmoslog "cosmossdk.io/log" | ||
"cosmossdk.io/math" | ||
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" | ||
|
||
"github.com/pokt-network/poktroll/app/volatile" | ||
"github.com/pokt-network/poktroll/cmd/poktrolld/cmd" | ||
_ "github.com/pokt-network/poktroll/pkg/polylog/polyzero" | ||
"github.com/pokt-network/poktroll/testutil/keeper" | ||
testproof "github.com/pokt-network/poktroll/testutil/proof" | ||
"github.com/pokt-network/poktroll/testutil/sample" | ||
apptypes "github.com/pokt-network/poktroll/x/application/types" | ||
prooftypes "github.com/pokt-network/poktroll/x/proof/types" | ||
sessiontypes "github.com/pokt-network/poktroll/x/session/types" | ||
"github.com/pokt-network/poktroll/x/shared" | ||
sharedtypes "github.com/pokt-network/poktroll/x/shared/types" | ||
) | ||
|
||
type applicationMinStakeTestSuite struct { | ||
suite.Suite | ||
|
||
ctx context.Context | ||
keepers keeper.TokenomicsModuleKeepers | ||
|
||
serviceId, | ||
appBech32, | ||
supplierBech32 string | ||
|
||
appStake *cosmostypes.Coin | ||
|
||
numRelays, | ||
numComputeUnitsPerRelay uint64 | ||
} | ||
|
||
func TestApplicationMinStakeTestSuite(t *testing.T) { | ||
cmd.InitSDKConfig() | ||
|
||
suite.Run(t, new(applicationMinStakeTestSuite)) | ||
} | ||
|
||
func (s *applicationMinStakeTestSuite) SetupTest() { | ||
s.keepers, s.ctx = keeper.NewTokenomicsModuleKeepers(s.T(), cosmoslog.NewNopLogger()) | ||
|
||
s.serviceId = "svc1" | ||
s.appBech32 = sample.AccAddress() | ||
s.supplierBech32 = sample.AccAddress() | ||
s.appStake = &apptypes.DefaultMinStake | ||
s.numRelays = 10 | ||
s.numComputeUnitsPerRelay = 1 | ||
|
||
// Set block height to 1. | ||
s.ctx = cosmostypes.UnwrapSDKContext(s.ctx).WithBlockHeight(1) | ||
} | ||
|
||
func (s *applicationMinStakeTestSuite) TestAppCannotStakeLessThanMinStake() { | ||
s.T().Skip("this case is well covered in x/application/keeper/msg_server_stake_application_test.go") | ||
} | ||
|
||
func (s *applicationMinStakeTestSuite) TestAppIsUnbondedIfBelowMinStakeWhenSettling() { | ||
// Assert that the application's initial bank balance is 0. | ||
appBalance := s.getAppBalance() | ||
require.Equal(s.T(), int64(0), appBalance.Amount.Int64()) | ||
|
||
// Add service 1 | ||
s.addService() | ||
|
||
// Stake an application for service 1 with min stake. | ||
s.stakeApp() | ||
|
||
// Stake a supplier for service 1. | ||
s.stakeSupplier() | ||
|
||
// Get the session header. | ||
sessionHeader := s.getSessionHeader() | ||
|
||
// Create a claim whose settlement amount drops the application below min stake | ||
claim := s.getClaim(sessionHeader) | ||
s.keepers.ProofKeeper.UpsertClaim(s.ctx, *claim) | ||
|
||
// Set the current height to the claim settlement height. | ||
sdkCtx := cosmostypes.UnwrapSDKContext(s.ctx) | ||
currentHeight := sdkCtx.BlockHeight() | ||
sharedParams := s.keepers.SharedKeeper.GetParams(s.ctx) | ||
currentSessionEndHeight := shared.GetSessionEndHeight(&sharedParams, currentHeight) | ||
claimSettlementHeight := currentSessionEndHeight + int64(sharedtypes.GetSessionEndToProofWindowCloseBlocks(&sharedParams)) + 1 | ||
sdkCtx = sdkCtx.WithBlockHeight(claimSettlementHeight) | ||
s.ctx = sdkCtx | ||
|
||
// Settle pending claims; this should cause the application to be unbonded. | ||
_, _, err := s.keepers.Keeper.SettlePendingClaims(sdkCtx) | ||
require.NoError(s.T(), err) | ||
|
||
// Assert that the application was unbonded. | ||
_, isAppFound := s.keepers.ApplicationKeeper.GetApplication(s.ctx, s.appBech32) | ||
require.False(s.T(), isAppFound) | ||
|
||
// Assert that the application's stake was returned to its bank balance. | ||
expectedAppBurn := math.NewInt(int64(s.numRelays * s.numComputeUnitsPerRelay * sharedtypes.DefaultComputeUnitsToTokensMultiplier)) | ||
expectedAppBalance := s.appStake.SubAmount(expectedAppBurn) | ||
appBalance = s.getAppBalance() | ||
require.Equal(s.T(), expectedAppBalance.Amount.Int64(), appBalance.Amount.Int64()) | ||
|
||
} | ||
|
||
// addService adds the test service to the service module state. | ||
func (s *applicationMinStakeTestSuite) addService() { | ||
s.keepers.ServiceKeeper.SetService(s.ctx, sharedtypes.Service{ | ||
Id: s.serviceId, | ||
ComputeUnitsPerRelay: 1, | ||
OwnerAddress: sample.AccAddress(), // random address. | ||
}) | ||
} | ||
|
||
// stakeApp stakes an application for service 1 with min stake. | ||
func (s *applicationMinStakeTestSuite) stakeApp() { | ||
s.keepers.ApplicationKeeper.SetApplication(s.ctx, apptypes.Application{ | ||
Address: s.appBech32, | ||
Stake: s.appStake, | ||
ServiceConfigs: []*sharedtypes.ApplicationServiceConfig{{ServiceId: s.serviceId}}, | ||
}) | ||
} | ||
|
||
// stakeSupplier stakes a supplier for service 1. | ||
func (s *applicationMinStakeTestSuite) stakeSupplier() { | ||
// TODO_UPNEXT(@bryanchriswhite, #612): Replace supplierStake with suppleirtypes.DefaultMinStake. | ||
supplierStake := cosmostypes.NewInt64Coin(volatile.DenomuPOKT, 1000000) // 1 POKT. | ||
s.keepers.SupplierKeeper.SetSupplier(s.ctx, sharedtypes.Supplier{ | ||
OwnerAddress: s.supplierBech32, | ||
OperatorAddress: s.supplierBech32, | ||
Stake: &supplierStake, | ||
Services: []*sharedtypes.SupplierServiceConfig{ | ||
{ | ||
ServiceId: s.serviceId, | ||
RevShare: []*sharedtypes.ServiceRevenueShare{ | ||
{ | ||
Address: s.supplierBech32, | ||
RevSharePercentage: 100, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
// getSessionHeader gets the session header for the test session. | ||
func (s *applicationMinStakeTestSuite) getSessionHeader() *sessiontypes.SessionHeader { | ||
sdkCtx := cosmostypes.UnwrapSDKContext(s.ctx) | ||
currentHeight := sdkCtx.BlockHeight() | ||
sessionRes, err := s.keepers.SessionKeeper.GetSession(s.ctx, &sessiontypes.QueryGetSessionRequest{ | ||
ApplicationAddress: s.appBech32, | ||
ServiceId: s.serviceId, | ||
BlockHeight: currentHeight, | ||
}) | ||
require.NoError(s.T(), err) | ||
|
||
return sessionRes.GetSession().GetHeader() | ||
} | ||
|
||
// getClaim creates a claim whose settlement amount drops the application below min stake. | ||
func (s *applicationMinStakeTestSuite) getClaim( | ||
sessionHeader *sessiontypes.SessionHeader, | ||
) *prooftypes.Claim { | ||
claimRoot := testproof.SmstRootWithSumAndCount(s.numRelays*s.numComputeUnitsPerRelay, s.numRelays) | ||
|
||
return &prooftypes.Claim{ | ||
SupplierOperatorAddress: s.supplierBech32, | ||
SessionHeader: sessionHeader, | ||
RootHash: claimRoot, | ||
} | ||
} | ||
|
||
// getAppBalance returns the bank module balance for the application. | ||
func (s *applicationMinStakeTestSuite) getAppBalance() *cosmostypes.Coin { | ||
appBalRes, err := s.keepers.BankKeeper.Balance(s.ctx, &banktypes.QueryBalanceRequest{ | ||
Address: s.appBech32, Denom: volatile.DenomuPOKT, | ||
}) | ||
require.NoError(s.T(), err) | ||
|
||
return appBalRes.GetBalance() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.