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

[Supplier] Implement unbonding period #666

Merged
merged 20 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
95 changes: 79 additions & 16 deletions api/poktroll/shared/supplier.pulsar.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

67 changes: 67 additions & 0 deletions e2e/tests/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (
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"
shared "github.com/pokt-network/poktroll/x/shared"
sharedtypes "github.com/pokt-network/poktroll/x/shared/types"
suppliertypes "github.com/pokt-network/poktroll/x/supplier/types"
)
Expand Down Expand Up @@ -442,6 +443,28 @@ func (s *suite) AModuleEndBlockEventIsBroadcast(module, eventType string) {
s.waitForNewBlockEvent(newEventTypeMatchFn(module, eventType))
}

func (s *suite) TheSupplierForAccountIsUnbonding(accName string) {
_, ok := accNameToSupplierMap[accName]
require.True(s, ok, "supplier %s not found", accName)

s.waitForTxResultEvent(newEventMsgTypeMatchFn("supplier", "UnstakeSupplier"))

supplier := s.getSupplierInfo(accName)
require.NotEqual(s,
supplier.UnstakeCommitSessionEndHeight,
suppliertypes.SupplierNotUnstaking,
"supplier %s is not unbonding", accName,
)
}

func (s *suite) TheUserWaitsForUnbondingPeriodToFinish(accName string) {
_, ok := accNameToSupplierMap[accName]
require.True(s, ok, "supplier %s not found", accName)

unbondingHeight := s.getSupplierUnbondingHeight(accName)
red-0ne marked this conversation as resolved.
Show resolved Hide resolved
s.waitForBlockHeight(unbondingHeight)
}

func (s *suite) getStakedAmount(actorType, accName string) (int, bool) {
s.Helper()
args := []string{
Expand Down Expand Up @@ -566,6 +589,50 @@ func (s *suite) validateAmountChange(prevAmount, currAmount int, expectedAmountC

}

// getSupplierInfo returns the supplier information for a given supplier address
func (s *suite) getSupplierInfo(supplierAddr string) *sharedtypes.Supplier {
args := []string{
"query",
"supplier",
"show-supplier",
accNameToAddrMap[supplierAddr],
"--output=json",
}

res, err := s.pocketd.RunCommandOnHostWithRetry("", numQueryRetries, args...)
require.NoError(s, err, "error getting supplier %s", supplierAddr)
s.pocketd.result = res

var resp suppliertypes.QueryGetSupplierResponse
responseBz := []byte(strings.TrimSpace(res.Stdout))
s.cdc.MustUnmarshalJSON(responseBz, &resp)
return &resp.Supplier
}

// getSupplierUnbondingHeight returns the height at which the supplier will be unbonded.
func (s *suite) getSupplierUnbondingHeight(accName string) int64 {
supplier := s.getSupplierInfo(accName)

args := []string{
"query",
"shared",
"params",
"--output=json",
}

res, err := s.pocketd.RunCommandOnHostWithRetry("", numQueryRetries, args...)
require.NoError(s, err, "error getting supplier module params")
red-0ne marked this conversation as resolved.
Show resolved Hide resolved

var resp sharedtypes.QueryParamsResponse
responseBz := []byte(strings.TrimSpace(res.Stdout))
s.cdc.MustUnmarshalJSON(responseBz, &resp)
windowCloseHeight := shared.GetProofWindowCloseHeight(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we get this from the supplier field?

Copy link
Contributor Author

@red-0ne red-0ne Jul 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The supplier has the SessionEndHeight of the block at which the MsgUnstake tx was committed.
I'll try storing the UnbondingHeight to see if its better API.

The reason for storing UnstakeSessionEndHeight and not the windowCloseHeight is that we need the former to know whether the Supplier is still active or not.

Storing the additional windowCloseHeight/UnbondingHeight would be redundant since we can derive it from UnstakeSessionEndHeight.

As @bryanchriswhite suggested, Having a static function to get the UnbondingHeight should be the way to go.

&resp.Params,
int64(supplier.UnstakeCommitSessionEndHeight),
)
red-0ne marked this conversation as resolved.
Show resolved Hide resolved
return windowCloseHeight
}

// TODO_IMPROVE: use `sessionId` and `supplierName` since those are the two values
// used to create the primary composite key on-chain to uniquely distinguish relays.
func relayReferenceKey(appName, supplierName string) string {
Expand Down
29 changes: 29 additions & 0 deletions e2e/tests/session_steps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,35 @@ func (s *suite) waitForNewBlockEvent(
}
}

// waitForBlockHeight waits for a NewBlock event to be observed whose height is
// greater than or equal to the target height.
func (s *suite) waitForBlockHeight(targetHeight int64) {
Olshansk marked this conversation as resolved.
Show resolved Hide resolved
ctx, done := context.WithCancel(s.ctx)

// For each observed event, **asynchronously** check if it is greater than
// or equal to the target height
channel.ForEach[*block.CometNewBlockEvent](
ctx, s.newBlockEventsReplayClient.EventsSequence(ctx),
func(_ context.Context, newBlockEvent *block.CometNewBlockEvent) {
if newBlockEvent == nil {
return
}

if newBlockEvent.Data.Value.Block.Header.Height >= targetHeight {
done()
return
}
},
)

select {
case <-time.After(eventTimeout):
s.Fatalf("ERROR: timed out waiting for block height", targetHeight)
case <-ctx.Done():
s.Log("Success; height detected before timeout.")
}
}

// newEventTypeMatchFn returns a function that matches an event based on its type
// field. The type URL is constructed from the given module and eventType arguments
// where module is the module name and eventType is the protobuf message type name
Expand Down
5 changes: 2 additions & 3 deletions e2e/tests/stake_app.feature
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ Feature: Stake App Namespaces
Then the user should be able to see standard output containing "txhash:"
And the user should be able to see standard output containing "code: 0"
And the pocketd binary should exit without error
# TODO_TECHDEBT(@red-0ne): Wait for an admitted stake event instead of a time based waiting.
And the user should wait for "5" seconds
And the user should wait for the "application" module "StakeApplication" message to be submitted
Olshansk marked this conversation as resolved.
Show resolved Hide resolved
And the "application" for account "app2" is staked with "1000070" uPOKT
And the account balance of "app2" should be "1000070" uPOKT "less" than before

Expand All @@ -23,6 +22,6 @@ Feature: Stake App Namespaces
Then the user should be able to see standard output containing "txhash:"
And the user should be able to see standard output containing "code: 0"
And the pocketd binary should exit without error
And the user should wait for "5" seconds
And the user should wait for the "application" module "UnstakeApplication" message to be submitted
And the "application" for account "app2" is not staked
And the account balance of "app2" should be "1000070" uPOKT "more" than before
5 changes: 2 additions & 3 deletions e2e/tests/stake_gateway.feature
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ Feature: Stake Gateway Namespaces
Then the user should be able to see standard output containing "txhash:"
And the user should be able to see standard output containing "code: 0"
And the pocketd binary should exit without error
# TODO_TECHDEBT(@red-0ne): Replace these time-based waits with event listening waits
And the user should wait for "5" seconds
And the user should wait for the "gateway" module "StakeGateway" message to be submitted
And the "gateway" for account "gateway2" is staked with "1000070" uPOKT
And the account balance of "gateway2" should be "1000070" uPOKT "less" than before

Expand All @@ -21,6 +20,6 @@ Feature: Stake Gateway Namespaces
Then the user should be able to see standard output containing "txhash:"
And the user should be able to see standard output containing "code: 0"
And the pocketd binary should exit without error
And the user should wait for "5" seconds
And the user should wait for the "gateway" module "UnstakeGateway" message to be submitted
And the "gateway" for account "gateway2" is not staked
And the account balance of "gateway2" should be "1000070" uPOKT "more" than before
8 changes: 4 additions & 4 deletions e2e/tests/stake_supplier.feature
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ Feature: Stake Supplier Namespace
Then the user should be able to see standard output containing "txhash:"
And the user should be able to see standard output containing "code: 0"
And the pocketd binary should exit without error
# TODO_TECHDEBT(@red-0ne): Replace these time-based waits with event listening waits
And the user should wait for "5" seconds
And the user should wait for the "supplier" module "StakeSupplier" message to be submitted
And the "supplier" for account "supplier2" is staked with "1000070" uPOKT
And the account balance of "supplier2" should be "1000070" uPOKT "less" than before

Expand All @@ -23,6 +22,7 @@ Feature: Stake Supplier Namespace
Then the user should be able to see standard output containing "txhash:"
And the user should be able to see standard output containing "code: 0"
And the pocketd binary should exit without error
And the user should wait for "5" seconds
And the "supplier" for account "supplier2" is not staked
And the supplier for account "supplier2" is unbonding
When the user waits for "supplier2" unbonding period to finish
Then the "supplier" for account "supplier2" is not staked
And the account balance of "supplier2" should be "1000070" uPOKT "more" than before
3 changes: 3 additions & 0 deletions proto/poktroll/shared/supplier.proto
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,8 @@ message Supplier {
string address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; // The Bech32 address of the supplier using cosmos' ScalarDescriptor to ensure deterministic encoding
cosmos.base.v1beta1.Coin stake = 2; // The total amount of uPOKT the supplier has staked
repeated SupplierServiceConfig services = 3; // The service configs this supplier can support
// The session end height corresponding the the unstake tx commit height.
// If the supplier is not unstaking, this value will be 0.
uint64 unstake_commit_session_end_height = 4;
red-0ne marked this conversation as resolved.
Show resolved Hide resolved
}

Loading
Loading