Skip to content

Commit

Permalink
Merge branch 'issues/657/merge/integration-app_x_transfer-period-base…
Browse files Browse the repository at this point in the history
…' into issues/657/chore/app-transfer-period

* issues/657/merge/integration-app_x_transfer-period-base:
  fixup! HEAD^
  fix: linter errors
  chore: review feedback improvements
  [SMST] feat: Use compact SMST proofs (#823)
  [SessionManager] Skip claims creation if supplier operator balance is too low (#817)
  chore: self-review improvements
  [Code Health] refactor: rename `ApplicationTransfer` msgs (#788)
  [Docs] Add operations documentation about proof submission fee (#806)
  [Testing] Fix non-idempotency in (and speed up) supplier staking tests (#815)
  • Loading branch information
bryanchriswhite committed Sep 24, 2024
2 parents 3dad80e + 1793eff commit 452f4ad
Show file tree
Hide file tree
Showing 48 changed files with 1,106 additions and 361 deletions.
2 changes: 1 addition & 1 deletion api/poktroll/proof/tx.pulsar.go

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

2 changes: 1 addition & 1 deletion api/poktroll/proof/types.pulsar.go

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

5 changes: 3 additions & 2 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -268,5 +268,6 @@ genesis:
claim_window_close_offset_blocks: 4
proof_window_open_offset_blocks: 0
proof_window_close_offset_blocks: 4
supplier_unbonding_period_sessions: 4
application_unbonding_period_sessions: 4
supplier_unbonding_period_sessions: 1
application_unbonding_period_sessions: 1
compute_units_to_tokens_multiplier: 42
82 changes: 80 additions & 2 deletions docusaurus/docs/operate/configs/relayminer_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ You can find a fully featured example configuration at [relayminer_config_full_e
- [Configuring Signing Keys](#configuring-signing-keys)
- [Example Configuration](#example-configuration)
- [Supported server types](#supported-server-types)
- [Payable Proof Submissions](#payable-proof-submissions)
- [Overview](#overview)
- [Key Requirements for Operators](#key-requirements-for-operators)
- [Recommendations for Supplier Operators](#recommendations-for-supplier-operators)

## Introduction

Expand Down Expand Up @@ -115,8 +119,9 @@ smt_store_path: <string>
_`Required`_ if `suppliers.*.signing_key_names` is not specified.

This configuration option specifies a list of key names from the keyring that the
`RelayMiner` will use to sign transactions. These key names are used to derive the public
key and the corresponding address, which are essential for interacting with POKT.
`RelayMiner` will use to sign transactions (i.e. `SupplierOperator`).
These key names are used to derive the public key and the corresponding address,
which are essential for interacting with POKT.
Each key name listed here must be present in the keyring used to start the
`RelayMiner` instance.

Expand Down Expand Up @@ -451,3 +456,76 @@ flowchart
## Supported server types

The list of supported server types can be found at [pkg/relayer/config/types.go](https://github.com/pokt-network/poktroll/tree/main/pkg/relayer/config/types.go#L8)

## Payable Proof Submissions

### Overview

Submitting `Proofs` requires the payment of a fee, which is defined by the
`proof_submission_fee` governance parameter.

This fee mechanism is designed to prevent spam attacks (e.g., Sybil bloat attacks)
by discouraging invalid or unnecessary `Proofs`.

Since `Proofs` are the most block space-consuming primitive in the Pocket Network,
this fee plays a crucial role in maintaining the integrity of the network.

<!-- TODO_MAINNET(@red-0ne): Add a link to a block in our explorer showcasing this. -->

### Key Requirements for Operators

Due to the probabilistic nature of the `Proof` requirement, `Supplier` operators must
ensure that they maintain sufficient funds to cover the submission fees for all
`Proof`s associated with the `Claim`s they plan to submit.

Failure to maintain adequate funds can result in missed submissions, which can
result in `Supplier` slashing if the `Proof` is required.

### Recommendations for Supplier Operators

- **Sufficient Balance**: Operators should regularly check their account balance
and ensure they have enough funds to cover the submission fees for `Proofs`.

The following command can be used to check the balance of a `Supplier` operator:
```bash
poktrolld query bank balance <supplier_operator_address> upokt --node https://shannon-testnet-grove-seed-rpc.poktroll.com
```
Which output would look like:
```yaml
balance:
amount: "109999000"
denom: upokt
```
- **Automated Monitoring**: It is highly recommended to implement balance monitoring
or alert systems to avoid running out of funds during critical periods.
<!-- TODO_POST_MAINNET(@okdas): Link to example alerts & infrastructure others can use. -->
- **Cost Awareness**: Operators should familiarize themselves with the current
`proof_submission_fee` and plan their funding accordingly, especially if they
anticipate submitting a higher volume of `Proofs`.

The following command can be used to check the current `proof_submission_fee`:
```bash
poktrolld query proof params --node https://shannon-testnet-grove-seed-rpc.poktroll.com
```
Which output would look like:
```yaml
proof_submission_fee:
amount: "1000000"
denom: upokt
```

The list of `Proof` governance parameters can be found at [proto/proof/params.proto](https://github.com/pokt-network/poktroll/blob/main/proto/poktroll/proof/params.proto)

:::warning

If you submit a claim but do not submit its corresponding proof, this could result in SLASHING!

Having insufficient funds could lead to rejected `Proof` submissions . This
can disrupt the operator’s participation in the Pocket Network. To maintain a
smooth operation, avoid being slashed, and earn your rewards, operators must plan
and manage their account balance as part of their operational procedures.

:::
4 changes: 2 additions & 2 deletions e2e/tests/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -776,8 +776,8 @@ func (s *suite) getSupplierUnbondingHeight(accName string) int64 {
var resp sharedtypes.QueryParamsResponse
responseBz := []byte(strings.TrimSpace(res.Stdout))
s.cdc.MustUnmarshalJSON(responseBz, &resp)
unbondingHeight := shared.GetSupplierUnbondingHeight(&resp.Params, supplier)
return unbondingHeight

return shared.GetSupplierUnbondingHeight(&resp.Params, supplier)
}

// getApplicationInfo returns the application information for a given application address.
Expand Down
4 changes: 2 additions & 2 deletions e2e/tests/params_tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (s *suite) sendAuthzExecTx(signingKeyName, txJSONFilePath string) {
}

// newTempUpdateParamsTxJSONFile creates & returns a new temp file with the JSON representation of a tx
// which contains a MsgUpdateParams to update **all module params** for each module & paramsMap
// which contains a MsgUpdateParams to update **all module params** for each module & paramsAnyMap
// in the given moduleParamsMap. The returned file is intended for use with the `authz exec` CLI
// subcommand: `poktrolld tx authz exec <tx_json_file>`.
func (s *suite) newTempUpdateParamsTxJSONFile(moduleParams moduleParamsMap) *os.File {
Expand All @@ -76,7 +76,7 @@ func (s *suite) newTempUpdateParamsTxJSONFile(moduleParams moduleParamsMap) *os.
}

// newTempUpdateParamTxJSONFile creates & returns a new temp file with the JSON representation of a tx
// which contains a MsgUpdateParam to update params **individually** for each module & paramsMap in the
// which contains a MsgUpdateParam to update params **individually** for each module & paramsAnyMap in the
// given moduleParamsMap. The returned file is intended for use with the `authz exec` CLI subcommand:
// `poktrolld tx authz exec <tx_json_file>`.
func (s *suite) newTempUpdateParamTxJSONFile(moduleParams moduleParamsMap) *os.File {
Expand Down
6 changes: 3 additions & 3 deletions e2e/tests/params_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ type (
paramNameKey = string
)

// paramsMap is a map of param names to param values.
type paramsMap map[paramNameKey]paramAny
// paramsAnyMap is a map of param names to param values.
type paramsAnyMap map[paramNameKey]paramAny

// moduleParamsMap is a map of module names to params maps.
type moduleParamsMap map[moduleNameKey]paramsMap
type moduleParamsMap map[moduleNameKey]paramsAnyMap

// paramAny is a struct that holds a param type and a param value.
type paramAny struct {
Expand Down
20 changes: 10 additions & 10 deletions e2e/tests/parse_params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ const (
paramTypeColIdx
)

// parseParamsTable parses a gocuke.DataTable into a paramsMap.
func (s *suite) parseParamsTable(table gocuke.DataTable) paramsMap {
// parseParamsTable parses a gocuke.DataTable into a paramsAnyMap.
func (s *suite) parseParamsTable(table gocuke.DataTable) paramsAnyMap {
s.Helper()

paramsMap := make(paramsMap)
paramsMap := make(paramsAnyMap)

// NB: skip the header row.
for rowIdx := 1; rowIdx < table.NumRows(); rowIdx++ {
Expand Down Expand Up @@ -78,9 +78,9 @@ func (s *suite) parseParam(table gocuke.DataTable, rowIdx int) paramAny {
}
}

// paramsMapToMsgUpdateParams converts a paramsMap into a MsgUpdateParams, which
// paramsMapToMsgUpdateParams converts a paramsAnyMap into a MsgUpdateParams, which
// it returns as a proto.Message/cosmostypes.Msg interface type.
func (s *suite) paramsMapToMsgUpdateParams(moduleName string, paramsMap paramsMap) (msgUpdateParams cosmostypes.Msg) {
func (s *suite) paramsMapToMsgUpdateParams(moduleName string, paramsMap paramsAnyMap) (msgUpdateParams cosmostypes.Msg) {
s.Helper()

switch moduleName {
Expand All @@ -104,7 +104,7 @@ func (s *suite) paramsMapToMsgUpdateParams(moduleName string, paramsMap paramsMa
return msgUpdateParams
}

func (s *suite) newTokenomicsMsgUpdateParams(params paramsMap) cosmostypes.Msg {
func (s *suite) newTokenomicsMsgUpdateParams(params paramsAnyMap) cosmostypes.Msg {
authority := authtypes.NewModuleAddress(s.granterName).String()

msgUpdateParams := &tokenomicstypes.MsgUpdateParams{
Expand All @@ -121,7 +121,7 @@ func (s *suite) newTokenomicsMsgUpdateParams(params paramsMap) cosmostypes.Msg {
return proto.Message(msgUpdateParams)
}

func (s *suite) newProofMsgUpdateParams(params paramsMap) cosmostypes.Msg {
func (s *suite) newProofMsgUpdateParams(params paramsAnyMap) cosmostypes.Msg {
authority := authtypes.NewModuleAddress(s.granterName).String()

msgUpdateParams := &prooftypes.MsgUpdateParams{
Expand All @@ -148,7 +148,7 @@ func (s *suite) newProofMsgUpdateParams(params paramsMap) cosmostypes.Msg {
return proto.Message(msgUpdateParams)
}

func (s *suite) newSharedMsgUpdateParams(params paramsMap) cosmostypes.Msg {
func (s *suite) newSharedMsgUpdateParams(params paramsAnyMap) cosmostypes.Msg {
authority := authtypes.NewModuleAddress(s.granterName).String()

msgUpdateParams := &sharedtypes.MsgUpdateParams{
Expand Down Expand Up @@ -183,7 +183,7 @@ func (s *suite) newSharedMsgUpdateParams(params paramsMap) cosmostypes.Msg {
return proto.Message(msgUpdateParams)
}

func (s *suite) newAppMsgUpdateParams(params paramsMap) cosmostypes.Msg {
func (s *suite) newAppMsgUpdateParams(params paramsAnyMap) cosmostypes.Msg {
authority := authtypes.NewModuleAddress(s.granterName).String()

msgUpdateParams := &apptypes.MsgUpdateParams{
Expand All @@ -203,7 +203,7 @@ func (s *suite) newAppMsgUpdateParams(params paramsMap) cosmostypes.Msg {
return proto.Message(msgUpdateParams)
}

func (s *suite) newServiceMsgUpdateParams(params paramsMap) cosmostypes.Msg {
func (s *suite) newServiceMsgUpdateParams(params paramsAnyMap) cosmostypes.Msg {
authority := authtypes.NewModuleAddress(s.granterName).String()

msgUpdateParams := &servicetypes.MsgUpdateParams{
Expand Down
9 changes: 8 additions & 1 deletion e2e/tests/stake_supplier.feature
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Feature: Stake Supplier Namespace

Scenario: User can stake and unstake a Supplier waiting for it to unbound
Scenario: User can stake a Supplier
Given the user has the pocketd binary installed
And the user verifies the "supplier" for account "supplier2" is not staked
And the account "supplier2" has a balance greater than "1000070" uPOKT
Expand All @@ -14,6 +14,8 @@ Feature: Stake Supplier Namespace

Scenario: User can unstake a Supplier
Given the user has the pocketd binary installed
# Reduce the application unbonding period to avoid timeouts and speed up scenarios.
And the "supplier" unbonding period param is successfully set to "1" sessions of "2" blocks
And the "supplier" for account "supplier2" is staked with "1000070" uPOKT
And an account exists for "supplier2"
When the user unstakes a "supplier" from the account "supplier2"
Expand All @@ -27,10 +29,15 @@ Feature: Stake Supplier Namespace

Scenario: User can restake a Supplier waiting for it to become active again
Given the user has the pocketd binary installed
# Reduce the application unbonding period to avoid timeouts and speed up scenarios.
And the "supplier" unbonding period param is successfully set to "1" sessions of "2" blocks
And the user verifies the "supplier" for account "supplier2" is not staked
Then the user stakes a "supplier" with "1000070" uPOKT for "anvil" service from the account "supplier2"
And the user should wait for the "supplier" module "StakeSupplier" message to be submitted
Then the user should see that the supplier for account "supplier2" is staked
But the session for application "app1" and service "anvil" does not contain "supplier2"
When the user waits for supplier "supplier2" to become active for service "anvil"
Then the session for application "app1" and service "anvil" contains the supplier "supplier2"
# Cleanup to make this feature idempotent.
And the user unstakes a "supplier" from the account "supplier2"
And the user waits for the supplier for account "supplier2" unbonding period to finish
100 changes: 100 additions & 0 deletions e2e/tests/stake_supplier_steps_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//go:build e2e

package e2e

import (
"reflect"
"strings"
"unicode"

"github.com/stretchr/testify/require"

sharedtypes "github.com/pokt-network/poktroll/x/shared/types"
)

func (s *suite) TheUnbondingPeriodParamIsSuccessfullySetToSessionsOfBlocks(
_ string,
unbondingPeriodSessions,
numBlocksPerSession int64,
) {
require.GreaterOrEqualf(s, numBlocksPerSession, int64(2),
"num_blocks_per_session MUST be at least 2 to satisfy parameter validation requirements")

paramModuleName := "shared"
granter := "gov"
grantee := "pnf"

// Ensure an authz grant is present such that this step may update parameters.
s.AnAuthzGrantFromTheAccountToTheAccountForEachModuleMsgupdateparamMessageExists(
granter, "module",
grantee, "user",
)

// NB: If new parameters are added to the shared module, they
// MUST be included here; otherwise, this step will fail.
sharedParams := sharedtypes.Params{
NumBlocksPerSession: uint64(numBlocksPerSession),
GracePeriodEndOffsetBlocks: 0,
ClaimWindowOpenOffsetBlocks: 0,
ClaimWindowCloseOffsetBlocks: 1,
ProofWindowOpenOffsetBlocks: 0,
ProofWindowCloseOffsetBlocks: 1,
SupplierUnbondingPeriodSessions: uint64(unbondingPeriodSessions),
ApplicationUnbondingPeriodSessions: uint64(unbondingPeriodSessions),
ComputeUnitsToTokensMultiplier: sharedtypes.DefaultComputeUnitsToTokensMultiplier,
}

// Convert params struct to the map type expected by
// s.sendAuthzExecToUpdateAllModuleParams().
paramsMap := paramsAnyMapFromParamsStruct(sharedParams)
s.sendAuthzExecToUpdateAllModuleParams(grantee, paramModuleName, paramsMap)

// Assert that the parameter values were updated.
s.AllModuleParamsShouldBeUpdated(paramModuleName)
}

// paramsAnyMapFromParamStruct construct a paramsAnyMap from any
// protobuf Param message type (tx.proto) using reflection.
func paramsAnyMapFromParamsStruct(paramStruct any) paramsAnyMap {
paramsMap := make(paramsAnyMap)
paramsReflectValue := reflect.ValueOf(paramStruct)
for i := 0; i < paramsReflectValue.NumField(); i++ {
fieldValue := paramsReflectValue.Field(i)
fieldStruct := paramsReflectValue.Type().Field(i)
paramName := toSnakeCase(fieldStruct.Name)

fieldTypeName := fieldStruct.Type.Name()
// TODO_IMPROVE: MsgUpdateParam currently only supports int64 and not uint64 value types.
if fieldTypeName == "uint64" {
fieldTypeName = "int64"
fieldValue = reflect.ValueOf(int64(fieldValue.Interface().(uint64)))
}

paramsMap[paramName] = paramAny{
name: paramName,
typeStr: fieldTypeName,
value: fieldValue.Interface(),
}
}
return paramsMap
}

func toSnakeCase(str string) string {
var result strings.Builder

for i, runeValue := range str {
if unicode.IsUpper(runeValue) {
// If it's not the first letter, add an underscore
if i > 0 {
result.WriteRune('_')
}
// Convert to lowercase
result.WriteRune(unicode.ToLower(runeValue))
} else {
// Otherwise, just append the rune as-is
result.WriteRune(runeValue)
}
}

return result.String()
}
Loading

0 comments on commit 452f4ad

Please sign in to comment.