From 78a74453d23c5fee0d7f15df0dd12d5039d6fa14 Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Mon, 28 Oct 2024 23:22:42 +0100 Subject: [PATCH 1/4] [Supplier] Add supplier staking fee (#883) ## Summary Replace the upstaking requirement with a staking fee when a stake is added or updated. The staking fee will become a governance parameter in a follow up PR. ## Issue - #853 ## Type of change Select one or more from the following: - [x] New feature, functionality or library ## Testing - [x] **Unit Tests**: `make go_develop_and_test` - [x] **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 --- e2e/tests/stake_supplier.feature | 5 ++-- testutil/keeper/supplier.go | 20 +++++++------ .../keeper/msg_server_stake_supplier.go | 29 +++++++++++++++---- .../keeper/msg_server_stake_supplier_test.go | 15 +++++++--- .../msg_server_unstake_supplier_test.go | 10 +++++-- 5 files changed, 55 insertions(+), 24 deletions(-) diff --git a/e2e/tests/stake_supplier.feature b/e2e/tests/stake_supplier.feature index de0440165..b24a579d9 100644 --- a/e2e/tests/stake_supplier.feature +++ b/e2e/tests/stake_supplier.feature @@ -2,8 +2,9 @@ Feature: Stake Supplier Namespace Scenario: User can stake a Supplier Given the user has the pocketd binary installed + # TODO_UPNEXT: Set the supplier stake fee once it is a param. And the user verifies the "supplier" for account "supplier2" is not staked - And the account "supplier2" has a balance greater than "1000070" uPOKT + And the account "supplier2" has a balance greater than "1000071" uPOKT When the user stakes a "supplier" with "1000070" uPOKT for "anvil" service from the account "supplier2" 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" @@ -11,7 +12,7 @@ Feature: Stake Supplier Namespace And the user should wait for the "supplier" module "StakeSupplier" message to be submitted And the user should wait for the "supplier" module "SupplierStaked" tx event to be broadcast And the "supplier" for account "supplier2" is staked with "1000070" uPOKT - And the account balance of "supplier2" should be "1000070" uPOKT "less" than before + And the account balance of "supplier2" should be "1000071" uPOKT "less" than before Scenario: User can unstake a Supplier Given the user has the pocketd binary installed diff --git a/testutil/keeper/supplier.go b/testutil/keeper/supplier.go index bef17530d..83527c27a 100644 --- a/testutil/keeper/supplier.go +++ b/testutil/keeper/supplier.go @@ -33,7 +33,7 @@ type SupplierModuleKeepers struct { *keeper.Keeper types.SharedKeeper // Tracks the amount of funds returned to the supplier owner when the supplier is unbonded. - SupplierUnstakedFundsMap map[string]int64 + SupplierBalanceMap map[string]int64 } func SupplierKeeper(t testing.TB) (SupplierModuleKeepers, context.Context) { @@ -53,17 +53,19 @@ func SupplierKeeper(t testing.TB) (SupplierModuleKeepers, context.Context) { cdc := codec.NewProtoCodec(registry) authority := authtypes.NewModuleAddress(govtypes.ModuleName) - // Set a simple map to track the where the supplier stake is returned when - // the supplier is unbonded. - supplierUnstakedFundsMap := make(map[string]int64) + // Set a simple map to track the suppliers balances. + supplierBalanceMap := make(map[string]int64) ctrl := gomock.NewController(t) mockBankKeeper := mocks.NewMockBankKeeper(ctrl) - mockBankKeeper.EXPECT().SendCoinsFromAccountToModule(gomock.Any(), gomock.Any(), types.ModuleName, gomock.Any()).AnyTimes() + mockBankKeeper.EXPECT().SendCoinsFromAccountToModule(gomock.Any(), gomock.Any(), types.ModuleName, gomock.Any()).AnyTimes(). + Do(func(ctx context.Context, addr sdk.AccAddress, module string, coins sdk.Coins) { + supplierBalanceMap[addr.String()] -= coins[0].Amount.Int64() + }) mockBankKeeper.EXPECT().SpendableCoins(gomock.Any(), gomock.Any()).AnyTimes() mockBankKeeper.EXPECT().SendCoinsFromModuleToAccount(gomock.Any(), types.ModuleName, gomock.Any(), gomock.Any()).AnyTimes(). Do(func(ctx context.Context, module string, addr sdk.AccAddress, coins sdk.Coins) { - supplierUnstakedFundsMap[addr.String()] += coins[0].Amount.Int64() + supplierBalanceMap[addr.String()] += coins[0].Amount.Int64() }) // Construct a real shared keeper. @@ -104,9 +106,9 @@ func SupplierKeeper(t testing.TB) (SupplierModuleKeepers, context.Context) { serviceKeeper.SetService(ctx, sharedtypes.Service{Id: "svcId2"}) supplierModuleKeepers := SupplierModuleKeepers{ - Keeper: &supplierKeeper, - SharedKeeper: sharedKeeper, - SupplierUnstakedFundsMap: supplierUnstakedFundsMap, + Keeper: &supplierKeeper, + SharedKeeper: sharedKeeper, + SupplierBalanceMap: supplierBalanceMap, } return supplierModuleKeepers, ctx diff --git a/x/supplier/keeper/msg_server_stake_supplier.go b/x/supplier/keeper/msg_server_stake_supplier.go index e128849f0..f8eb5f548 100644 --- a/x/supplier/keeper/msg_server_stake_supplier.go +++ b/x/supplier/keeper/msg_server_stake_supplier.go @@ -8,11 +8,19 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "github.com/pokt-network/poktroll/app/volatile" "github.com/pokt-network/poktroll/telemetry" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" "github.com/pokt-network/poktroll/x/supplier/types" ) +var ( + // TODO_BETA: Make supplier staking fee a governance parameter + // TODO_BETA(@red-0ne): Update supplier staking documentation to remove the upstaking + // requirement and introduce the staking fee. + SupplierStakingFee = sdk.NewInt64Coin(volatile.DenomuPOKT, 1) +) + func (k msgServer) StakeSupplier(ctx context.Context, msg *types.MsgStakeSupplier) (*types.MsgStakeSupplierResponse, error) { isSuccessful := false defer telemetry.EventSuccessCounter( @@ -104,9 +112,13 @@ func (k msgServer) StakeSupplier(ctx context.Context, msg *types.MsgStakeSupplie supplier.UnstakeSessionEndHeight = sharedtypes.SupplierNotUnstaking } - // MUST ALWAYS stake or upstake (> 0 delta) - if coinsToEscrow.IsZero() { - err = types.ErrSupplierInvalidStake.Wrapf("Signer %q must escrow more than 0 additional coins", msg.Signer) + // TODO_BETA: Remove requirement of MUST ALWAYS stake or upstake (>= 0 delta) + // TODO_POST_MAINNET: Should we allow stake decrease down to min stake? + if coinsToEscrow.IsNegative() { + err = types.ErrSupplierInvalidStake.Wrapf( + "Supplier signer %q stake (%s) must be greater than or equal to the current stake (%s)", + msg.Signer, msg.GetStake(), supplier.Stake, + ) logger.Info(fmt.Sprintf("WARN: %s", err)) return nil, status.Error(codes.InvalidArgument, err.Error()) } @@ -130,7 +142,8 @@ func (k msgServer) StakeSupplier(ctx context.Context, msg *types.MsgStakeSupplie } // Send the coins from the message signer account to the staked supplier pool - err = k.bankKeeper.SendCoinsFromAccountToModule(ctx, msgSignerAddress, types.ModuleName, []sdk.Coin{coinsToEscrow}) + stakeWithFee := sdk.NewCoins(coinsToEscrow.Add(SupplierStakingFee)) + err = k.bankKeeper.SendCoinsFromAccountToModule(ctx, msgSignerAddress, types.ModuleName, stakeWithFee) if err != nil { logger.Info(fmt.Sprintf("ERROR: could not send %v coins from %q to %q module account due to %v", coinsToEscrow, msgSignerAddress, types.ModuleName, err)) return nil, status.Error(codes.InvalidArgument, err.Error()) @@ -191,8 +204,12 @@ func (k msgServer) updateSupplier( return types.ErrSupplierInvalidStake.Wrapf("stake amount cannot be nil") } - if msg.Stake.IsLTE(*supplier.Stake) { - return types.ErrSupplierInvalidStake.Wrapf("stake amount %v must be higher than previous stake amount %v", msg.Stake, supplier.Stake) + // TODO_BETA: No longer require upstaking. Remove this check. + if msg.Stake.IsLT(*supplier.Stake) { + return types.ErrSupplierInvalidStake.Wrapf( + "stake amount %v must be greater than or equal than previous stake amount %v", + msg.Stake, supplier.Stake, + ) } supplier.Stake = msg.Stake diff --git a/x/supplier/keeper/msg_server_stake_supplier_test.go b/x/supplier/keeper/msg_server_stake_supplier_test.go index 5682425fe..25bf559a2 100644 --- a/x/supplier/keeper/msg_server_stake_supplier_test.go +++ b/x/supplier/keeper/msg_server_stake_supplier_test.go @@ -45,9 +45,16 @@ func TestMsgServer_StakeSupplier_SuccessfulCreateAndUpdate(t *testing.T) { require.Equal(t, "svcId", foundSupplier.Services[0].ServiceId) require.Len(t, foundSupplier.Services[0].Endpoints, 1) require.Equal(t, "http://localhost:8080", foundSupplier.Services[0].Endpoints[0].Url) - - // Prepare an updated supplier with a higher stake and a different URL for the service - updateMsg := stakeSupplierForServicesMsg(ownerAddr, operatorAddr, 2000000, "svcId2") + // Assert that the supplier's account balance was reduced by the staking fee + balanceDecrease := keeper.SupplierStakingFee.Amount.Int64() + foundSupplier.Stake.Amount.Int64() + // SupplierBalanceMap reflects the relative changes to the supplier's balance + // (i.e. it starts from 0 and can go below it). + // It is not using coins that enforce non-negativity of the balance nor account + // funding and lookups. + require.Equal(t, -balanceDecrease, supplierModuleKeepers.SupplierBalanceMap[ownerAddr]) + + // Prepare an updated supplier with the same stake and a different URL for the service + updateMsg := stakeSupplierForServicesMsg(ownerAddr, operatorAddr, 1000000, "svcId2") updateMsg.Services[0].Endpoints[0].Url = "http://localhost:8082" // Update the staked supplier @@ -56,7 +63,7 @@ func TestMsgServer_StakeSupplier_SuccessfulCreateAndUpdate(t *testing.T) { foundSupplier, isSupplierFound = supplierModuleKeepers.GetSupplier(ctx, operatorAddr) require.True(t, isSupplierFound) - require.Equal(t, int64(2000000), foundSupplier.Stake.Amount.Int64()) + require.Equal(t, int64(1000000), foundSupplier.Stake.Amount.Int64()) require.Len(t, foundSupplier.Services, 1) require.Equal(t, "svcId2", foundSupplier.Services[0].ServiceId) require.Len(t, foundSupplier.Services[0].Endpoints, 1) diff --git a/x/supplier/keeper/msg_server_unstake_supplier_test.go b/x/supplier/keeper/msg_server_unstake_supplier_test.go index 2ccee80d2..e27493381 100644 --- a/x/supplier/keeper/msg_server_unstake_supplier_test.go +++ b/x/supplier/keeper/msg_server_unstake_supplier_test.go @@ -226,15 +226,19 @@ func TestMsgServer_UnstakeSupplier_OperatorCanUnstake(t *testing.T) { unbondingHeight := sharedtypes.GetSupplierUnbondingHeight(&sharedParams, &foundSupplier) ctx = keepertest.SetBlockHeight(ctx, int64(unbondingHeight)) + // Balance decrease is the total amount deducted from the supplier's balance, including + // the initial stake and the staking fee. + balanceDecrease := keeper.SupplierStakingFee.Amount.Int64() + foundSupplier.Stake.Amount.Int64() // Ensure that the initial stake is not returned to the owner yet - require.Equal(t, int64(0), supplierModuleKeepers.SupplierUnstakedFundsMap[ownerAddr]) + require.Equal(t, -balanceDecrease, supplierModuleKeepers.SupplierBalanceMap[ownerAddr]) // Run the endblocker to unbond suppliers err = supplierModuleKeepers.EndBlockerUnbondSuppliers(ctx) require.NoError(t, err) - // Ensure that the initial stake is returned to the owner - require.Equal(t, initialStake, supplierModuleKeepers.SupplierUnstakedFundsMap[ownerAddr]) + // Ensure that the initial stake is returned to the owner while the staking fee + // remains deducted from the supplier's balance. + require.Equal(t, -keeper.SupplierStakingFee.Amount.Int64(), supplierModuleKeepers.SupplierBalanceMap[ownerAddr]) } func createStakeMsg(supplierOwnerAddr string, stakeAmount int64) *suppliertypes.MsgStakeSupplier { From 4d1a423fee7c17085777f9925f5f97db7a3a032d Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Tue, 29 Oct 2024 17:51:07 -0400 Subject: [PATCH 2/4] [Docs] Assign owners to all `TODO_BETA` (#898) ## Summary Assign owners to all `TODO_BETA` ```bash export EXCLUDE_GREP="--exclude-dir={.git,vendor,./docusaurus,.vscode,.idea} --exclude= grep -r ${EXCLUDE_GREP} TODO_BETA . | grep -v 'TODO_BETA()' | wc -l 44 ``` ## Issue NA --- .github/workflows/label-actions.yml | 2 +- Tiltfile | 1 - app/upgrades/historical.go | 2 +- app/volatile/constants.go | 2 +- config.yml | 8 +++---- .../develop/contributing/observability.md | 2 +- .../develop/developer_guide/debug_tips.md | 16 ++++++------- .../docs/develop/packages/client_package.md | 4 ++-- docusaurus/docs/explore/rpc.md | 4 ++-- .../docs/operate/run_a_node/appgate_server.md | 4 +--- .../operate/run_a_node/full_node_docker.md | 3 +-- .../docs/operate/run_a_node/relay_miner.md | 4 ++-- .../primitives/claim_and_proof_lifecycle.md | 2 +- e2e/tests/0_settlement.feature | 2 +- e2e/tests/session.feature | 2 +- localnet/kubernetes/anvil.yaml | 2 +- .../config/appgate_configs_reader.go | 2 +- pkg/appgateserver/server.go | 4 ++-- pkg/client/query/sharedquerier.go | 24 +++++++++---------- pkg/crypto/rings/client.go | 4 ++-- pkg/polylog/interface.go | 4 ++-- pkg/relayer/config/types.go | 2 +- pkg/relayer/proxy/relay_verifier.go | 4 ++-- pkg/relayer/session/claim.go | 4 ++-- pkg/relayer/session/proof.go | 4 ++-- .../service/relay_mining_difficulty_test.go | 2 +- x/application/keeper/auto_undelegate.go | 2 +- .../keeper/msg_server_stake_application.go | 2 +- .../keeper/msg_server_unstake_application.go | 3 ++- x/application/module/simulation.go | 12 +++++----- .../simulation/delegate_to_gateway.go | 2 +- x/application/simulation/stake_application.go | 2 +- .../simulation/transfer_application.go | 2 +- .../simulation/undelegate_from_gateway.go | 2 +- .../simulation/unstake_application.go | 2 +- x/application/simulation/update_param.go | 2 +- x/application/types/params.go | 4 ++-- .../keeper/msg_server_unstake_gateway.go | 2 +- x/gateway/module/simulation.go | 6 ++--- x/gateway/module/tx.go | 2 +- x/gateway/simulation/stake_gateway.go | 2 +- x/gateway/simulation/unstake_gateway.go | 2 +- x/gateway/simulation/update_param.go | 2 +- x/proof/keeper/msg_server_create_claim.go | 4 ++-- x/proof/keeper/msg_server_submit_proof.go | 12 +++++----- .../keeper/msg_server_submit_proof_test.go | 2 +- x/proof/keeper/proof_requirement_test.go | 2 +- x/proof/keeper/proof_validation.go | 2 +- x/proof/keeper/session.go | 2 +- x/proof/module/simulation.go | 6 ++--- x/proof/module/tx_create_claim.go | 2 +- x/proof/module/tx_submit_proof.go | 2 +- x/proof/simulation/create_claim.go | 2 +- x/proof/simulation/submit_proof.go | 2 +- x/proof/simulation/update_param.go | 2 +- x/proof/types/shared_query_client.go | 6 ++--- x/service/keeper/msg_server_add_service.go | 2 +- x/service/module/simulation.go | 2 +- x/service/module/tx_add_service.go | 4 ++-- x/service/simulation/add_service.go | 2 +- x/service/types/params.go | 2 +- x/service/types/relay.go | 2 +- x/session/keeper/session_hydrator.go | 7 +++--- x/session/module/module.go | 2 +- x/shared/module/simulation.go | 2 +- x/shared/simulation/update_param.go | 2 +- x/shared/types/service_configs.go | 2 +- x/shared/types/session.go | 8 +++---- .../keeper/msg_server_stake_supplier.go | 2 +- x/supplier/module/abci.go | 2 +- x/supplier/module/query.go | 2 +- x/supplier/module/simulation.go | 6 ++--- x/supplier/module/tx.go | 2 +- x/supplier/simulation/stake_supplier.go | 4 ++-- x/supplier/simulation/unstake_supplier.go | 2 +- x/supplier/simulation/update_param.go | 2 +- x/supplier/types/genesis.go | 2 +- .../keeper_settle_pending_claims_test.go | 2 +- x/tokenomics/keeper/settle_pending_claims.go | 2 +- x/tokenomics/keeper/token_logic_modules.go | 17 +++++++------ x/tokenomics/module/abci.go | 2 +- x/tokenomics/module/simulation.go | 2 +- x/tokenomics/module/tx_update_params.go | 2 +- x/tokenomics/simulation/update_param.go | 2 +- 84 files changed, 148 insertions(+), 153 deletions(-) diff --git a/.github/workflows/label-actions.yml b/.github/workflows/label-actions.yml index 00be8e40b..2b85941dc 100644 --- a/.github/workflows/label-actions.yml +++ b/.github/workflows/label-actions.yml @@ -18,5 +18,5 @@ jobs: action: runs-on: ubuntu-latest steps: - # TODO: switch to `dessant/label-actions@v3` when https://github.com/dessant/label-actions/pull/29 is merged. + # TODO_TECHDEBT: switch to `dessant/label-actions@v3` when https://github.com/dessant/label-actions/pull/29 is merged. - uses: okdas/label-actions@patch-1 diff --git a/Tiltfile b/Tiltfile index 6b701bd8a..cd9b4a177 100644 --- a/Tiltfile +++ b/Tiltfile @@ -47,7 +47,6 @@ localnet_config_defaults = { "count": 1, "delve": {"enabled": False}, }, - # TODO_BLOCKER(@red-0ne, #511): Add support for `REST` and enabled this. "ollama": { "enabled": False, "model": "qwen:0.5b", diff --git a/app/upgrades/historical.go b/app/upgrades/historical.go index 0c9d83861..2c0740652 100644 --- a/app/upgrades/historical.go +++ b/app/upgrades/historical.go @@ -4,7 +4,7 @@ package upgrades // separate file, and then move them to `historical.go` after a successful upgrade so the new nodes can still sync from // the genesis. -// TODO_CONSIDERATION: after we verify `State Sync` is fully functional, we can hypothetically remove old upgrades from +// TODO_TECHDEBT(@okdas): after we verify `State Sync` is fully functional, we can hypothetically remove old upgrades from // the codebase, as the nodes won't have to execute upgrades and will download the "snapshot" instead. Some other // blockchain networks do that (such as `evmos`: https://github.com/evmos/evmos/tree/main/app/upgrades). // Note that this may inhibit a full state sync from genesis. diff --git a/app/volatile/constants.go b/app/volatile/constants.go index 169e3789e..1c3033312 100644 --- a/app/volatile/constants.go +++ b/app/volatile/constants.go @@ -2,5 +2,5 @@ // re-organized or removed in future work. package volatile -// TODO_CLEANUP: Find a way to centralize the use of `upokt` throughout the codebase +// TODO_TECHDEBT: Find a way to centralize the use of `upokt` throughout the codebase const DenomuPOKT = "upokt" diff --git a/config.yml b/config.yml index 942614aca..73ea3a945 100644 --- a/config.yml +++ b/config.yml @@ -87,7 +87,7 @@ validators: app: # DEV_NOTE: Ignite does not carry over all defaults, so we are going to match `minimum-gas-prices` with `cmd/config.go`. # See the enhancement request here: https://github.com/ignite/cli/issues/4340 - # TODO(#794): turn on `minimum-gas-prices` back + # TODO_MAINNET(#794): turn on `minimum-gas-prices` back # minimum-gas-prices: 0.000000001upokt telemetry: enabled: true @@ -124,7 +124,7 @@ genesis: staking: params: bond_denom: upokt - # TODO_MAINNET(@Olshansk): Figure out what this should be on Shannon + # TODO_MAINNET: Figure out what this should be on Shannon # re-genesis. We're setting it to 1 for Alpha TestNet #1 so Grove # maintains the only validator until Alpha TestNet #2. max_validators: 1 @@ -235,8 +235,8 @@ genesis: params: # TODO_MAINNET: Determine realistic amount for minimum gateway stake amount. min_stake: - amount: "1000000" # 1 POKT - denom: upokt + amount: "1000000" # 1 POKT + denom: upokt gatewayList: - address: pokt15vzxjqklzjtlz7lahe8z2dfe9nm5vxwwmscne4 stake: diff --git a/docusaurus/docs/develop/contributing/observability.md b/docusaurus/docs/develop/contributing/observability.md index 8c5bb91c8..a1883b0e1 100644 --- a/docusaurus/docs/develop/contributing/observability.md +++ b/docusaurus/docs/develop/contributing/observability.md @@ -111,7 +111,7 @@ func (k msgServer) CreateClaim(...) (_ *types.MsgCreateClaimResponse, err error) ### Histogram -TODO: Add a code example, link to usage, and screenshot of the output. +TODO_DOCUMENT: Add a code example, link to usage, and screenshot of the output. ## Logs diff --git a/docusaurus/docs/develop/developer_guide/debug_tips.md b/docusaurus/docs/develop/developer_guide/debug_tips.md index 0ce4f0658..629fb97bd 100644 --- a/docusaurus/docs/develop/developer_guide/debug_tips.md +++ b/docusaurus/docs/develop/developer_guide/debug_tips.md @@ -14,11 +14,11 @@ If you have a tip you'd like to share with others, please open a PR to add it he - [`itest` - Investigating Flaky Tests](#itest---investigating-flaky-tests) - [`itest` Usage](#itest-usage) - [`itest` Example](#itest-example) - - [TODO: pprof](#todo-pprof) - - [TODO: dlv](#todo-dlv) - [`poktrolld query tx` - Investigating Failed Transactions](#poktrolld-query-tx---investigating-failed-transactions) - [`poktrolld query tx` Example](#poktrolld-query-tx-example) - + - [TODO_DOCUMENT: pprof](#todo_document-pprof) + - [TODO_DOCUMENT: dlv](#todo_document-dlv) + ## `itest` - Investigating Flaky Tests We developed a tool called `itest` to help with debugging flaky tests. It runs @@ -43,11 +43,11 @@ make itest 5 10 ./pkg/client/tx/... -- -run TxClient_SignAndBroadcast_Succeeds ## `poktrolld query tx` - Investigating Failed Transactions -_tl;dr Submitted Transaction != Committed Transaction_ +_tl;dr Submitted Transaction != Committed Transaction_ After a transaction (e.g. staking a new service) is successfully sent to an RPC node, we have to wait until the next block, when a proposer will try to commit to the network's state, to see if its valid. -If the transaction's (TX) state transition is invalid, it will not be committed. +If the transaction's (TX) state transition is invalid, it will not be committed. In other words, receiving a transaction (TX) hash from the `poktrolld` CLI doesn't mean it was committed. However, the transaction (TX) hash can be used to investigate the failed transaction. @@ -91,7 +91,7 @@ state transition. :::note -If you are reading this and the `9E4CA...` hash is no longer valid, we may have done a re-genesis of +If you are reading this and the `9E4CA...` hash is no longer valid, we may have done a re-genesis of TestNet at this point. Please consider updating with a new one! ::: @@ -115,6 +115,6 @@ The above command will produce the following output: ::: -### TODO: pprof +### TODO_DOCUMENT: pprof -### TODO: dlv +### TODO_DOCUMENT: dlv diff --git a/docusaurus/docs/develop/packages/client_package.md b/docusaurus/docs/develop/packages/client_package.md index cb2947d70..fe5e7ec33 100644 --- a/docusaurus/docs/develop/packages/client_package.md +++ b/docusaurus/docs/develop/packages/client_package.md @@ -118,13 +118,13 @@ go get github.com/pokt-network/poktroll/pkg/client ### Basic Example ```go -// TODO: Code example showcasing the use of TxClient or any other primary interface. +// TODO_DOCUMENT: Code example showcasing the use of TxClient or any other primary interface. ``` ### Advanced Usage ```go -// TODO: Example illustrating advanced features or edge cases of the package. +// TODO_DOCUMENT: Example illustrating advanced features or edge cases of the package. ``` ### Configuration diff --git a/docusaurus/docs/explore/rpc.md b/docusaurus/docs/explore/rpc.md index db5284514..4d1f7ec3d 100644 --- a/docusaurus/docs/explore/rpc.md +++ b/docusaurus/docs/explore/rpc.md @@ -29,8 +29,8 @@ poktrolld query block --type=height 0 --node https://shannon-testnet-grove-seed- ### gRPC -_TODO: Add a gRPC example_ +_TODO_TECHDEBT: Add a gRPC example_ ### REST -_TODO: Add a REST example_ +_TODO_TECHDEBT: Add a REST example_ diff --git a/docusaurus/docs/operate/run_a_node/appgate_server.md b/docusaurus/docs/operate/run_a_node/appgate_server.md index cf40e54cb..e0b63cbc5 100644 --- a/docusaurus/docs/operate/run_a_node/appgate_server.md +++ b/docusaurus/docs/operate/run_a_node/appgate_server.md @@ -39,8 +39,6 @@ Please see the [Hardware Requirements](./hardware_requirements.md#appgate-server Please refer to the `Deploying an AppGate Server` section in [poktroll-docker-compose-example](https://github.com/pokt-network/poktroll-docker-compose-example#deploying-an-appgate-server) GitHub repository on how to deploy an AppGate Server using `docker-compose`. -_TODO: Move over the relevant information from the `poktroll-docker-compose-example` repository into the docs_ - ## Kubernetes Example -_TODO: Provide an example using [strangelove-ventures/cosmos-operator](https://github.com/strangelove-ventures/cosmos-operator)._ +_TODO_DOCUMENT: Provide an example using [strangelove-ventures/cosmos-operator](https://github.com/strangelove-ventures/cosmos-operator)._ diff --git a/docusaurus/docs/operate/run_a_node/full_node_docker.md b/docusaurus/docs/operate/run_a_node/full_node_docker.md index aee02e3a8..13087c06e 100644 --- a/docusaurus/docs/operate/run_a_node/full_node_docker.md +++ b/docusaurus/docs/operate/run_a_node/full_node_docker.md @@ -20,7 +20,6 @@ In blockchain networks, a Full Node retains a complete copy of the ledger. You can visit the [Cosmos SDK documentation](https://docs.cosmos.network/main/user/run-node/run-node) for more information on Full Nodes. - ## Roles & Responsibilities It is usually responsible for: @@ -62,4 +61,4 @@ on how to deploy a Full Node using `docker-compose`. ## Kubernetes Example -_TODO: Provide an example using [strangelove-ventures/cosmos-operator](https://github.com/strangelove-ventures/cosmos-operator)._ +_TODO_DOCUMENT: Provide an example using [strangelove-ventures/cosmos-operator](https://github.com/strangelove-ventures/cosmos-operator)._ diff --git a/docusaurus/docs/operate/run_a_node/relay_miner.md b/docusaurus/docs/operate/run_a_node/relay_miner.md index 58e4b6014..b1f59be9d 100644 --- a/docusaurus/docs/operate/run_a_node/relay_miner.md +++ b/docusaurus/docs/operate/run_a_node/relay_miner.md @@ -38,8 +38,8 @@ Please see the [Hardware Requirements](./hardware_requirements.md#relayminer) pa Please refer to the `Deploying a RelayMiner` section in [poktroll-docker-compose-example](https://github.com/pokt-network/poktroll-docker-compose-example#deploying-a-relay-miner) GitHub repository on how to deploy an AppGate Server using `docker-compose`. -_TODO: Move over the relevant information from the `poktroll-docker-compose-example` repository into the docs_ +_TODO_DOCUMENT: Move over the relevant information from the `poktroll-docker-compose-example` repository into the docs_ ## Kubernetes Example -_TODO: Provide an example using [strangelove-ventures/cosmos-operator](https://github.com/strangelove-ventures/cosmos-operator)._ +_TODO_DOCUMENT: Provide an example using [strangelove-ventures/cosmos-operator](https://github.com/strangelove-ventures/cosmos-operator)._ diff --git a/docusaurus/docs/protocol/primitives/claim_and_proof_lifecycle.md b/docusaurus/docs/protocol/primitives/claim_and_proof_lifecycle.md index bac50f471..7617b5ce7 100644 --- a/docusaurus/docs/protocol/primitives/claim_and_proof_lifecycle.md +++ b/docusaurus/docs/protocol/primitives/claim_and_proof_lifecycle.md @@ -374,7 +374,7 @@ deep cryptographic validations needed: :::note -TODO: Link to tokenomics and data integrity checks for discussion once they are written. +TODO_DOCUMENT: Link to tokenomics and data integrity checks for discussion once they are written. ::: diff --git a/e2e/tests/0_settlement.feature b/e2e/tests/0_settlement.feature index 94c4de9cc..fb3e228d6 100644 --- a/e2e/tests/0_settlement.feature +++ b/e2e/tests/0_settlement.feature @@ -74,7 +74,7 @@ Feature: Tokenomics Namespace Then the account balance of "supplier1" should be "449" uPOKT "more" than before And the "application" stake of "app1" should be "420" uPOKT "less" than before - # TODO_ADDTEST: Implement the following scenarios + # TODO_TEST: Implement the following scenarios # Scenario: Supplier revenue shares are properly distributed # Scenario: TLM Mint=Burn when a valid claim is outside Max Limits # - Ensure over serviced event is submitted diff --git a/e2e/tests/session.feature b/e2e/tests/session.feature index d1c3ca1d4..df5f3f66a 100644 --- a/e2e/tests/session.feature +++ b/e2e/tests/session.feature @@ -22,7 +22,7 @@ Feature: Session Namespace And the user should wait for the "proof" module "ProofSubmitted" tx event to be broadcast Then the claim created by supplier "supplier1" for service "anvil" for application "app1" should be successfully settled -# TODO_BLOCKER(@red-0ne): Make sure to implement and validate this test +# TODO_MAINNET(@red-0ne): Make sure to implement and validate this test # One way to exercise this behavior is to close the `RelayMiner` port to prevent # the `RelayRequest` from being received and processed then reopen it after the # the defined number of blocks has passed. diff --git a/localnet/kubernetes/anvil.yaml b/localnet/kubernetes/anvil.yaml index 9b890ca75..551d39b2b 100644 --- a/localnet/kubernetes/anvil.yaml +++ b/localnet/kubernetes/anvil.yaml @@ -13,7 +13,7 @@ spec: labels: app: anvil spec: - # TODO: Add resource limits + # TODO_IMPROVE: Add resource limits containers: - name: anvil image: ghcr.io/foundry-rs/foundry:nightly-3fa02706ca732c994715ba42d923605692062375 diff --git a/pkg/appgateserver/config/appgate_configs_reader.go b/pkg/appgateserver/config/appgate_configs_reader.go index 1936835ab..29c8c8f20 100644 --- a/pkg/appgateserver/config/appgate_configs_reader.go +++ b/pkg/appgateserver/config/appgate_configs_reader.go @@ -7,7 +7,7 @@ import ( ) // YAMLAppGateServerConfig is the structure used to unmarshal the AppGateServer config file -// TODO_BETA: Rename self_signing parameter to `sovereign` in code, configs +// TODO_BETA(@red-0ne): Rename self_signing parameter to `sovereign` in code, configs // and documentation type YAMLAppGateServerConfig struct { ListeningEndpoint string `yaml:"listening_endpoint"` diff --git a/pkg/appgateserver/server.go b/pkg/appgateserver/server.go index 29d3af1ee..ede1be059 100644 --- a/pkg/appgateserver/server.go +++ b/pkg/appgateserver/server.go @@ -120,9 +120,9 @@ func NewAppGateServer( app.signingInformation.AppAddress = appAddress.String() } - // TODO_CONSIDERATION: Use app.listeningEndpoint scheme to determine which + // TODO_IMPROVE: Use app.listeningEndpoint scheme to determine which // kind of server to create (HTTP, HTTPS, TCP, UNIX, etc...) - // TODO_RESEARCH(#590): Currently, the communication between the AppGateServer and the + // TODO_IMPROVE(#590): Currently, the communication between the AppGateServer and the // RelayMiner uses HTTP. This could be changed to a more generic and performant // one, such as pure TCP. app.server = &http.Server{Addr: app.listeningEndpoint.Host} diff --git a/pkg/client/query/sharedquerier.go b/pkg/client/query/sharedquerier.go index d3f3308d9..06e0ed90a 100644 --- a/pkg/client/query/sharedquerier.go +++ b/pkg/client/query/sharedquerier.go @@ -60,10 +60,10 @@ func (sq *sharedQuerier) GetParams(ctx context.Context) (*sharedtypes.Params, er // GetClaimWindowOpenHeight returns the block height at which the claim window of // the session that includes queryHeight opens. // -// TODO_TECHDEBT(#543): We don't really want to have to query the params for every method call. +// TODO_MAINNET(#543): We don't really want to have to query the params for every method call. // Once `ModuleParamsClient` is implemented, use its replay observable's `#Last()` method // to get the most recently (asynchronously) observed (and cached) value. -// TODO_BLOCKER(@bryanchriswhite,#543): We also don't really want to use the current value of the params. Instead, +// TODO_MAINNET(@bryanchriswhite,#543): We also don't really want to use the current value of the params. Instead, // we should be using the value that the params had for the session which includes queryHeight. func (sq *sharedQuerier) GetClaimWindowOpenHeight(ctx context.Context, queryHeight int64) (int64, error) { sharedParams, err := sq.GetParams(ctx) @@ -76,10 +76,10 @@ func (sq *sharedQuerier) GetClaimWindowOpenHeight(ctx context.Context, queryHeig // GetProofWindowOpenHeight returns the block height at which the proof window of // the session that includes queryHeight opens. // -// TODO_TECHDEBT(#543): We don't really want to have to query the params for every method call. +// TODO_MAINNET(#543): We don't really want to have to query the params for every method call. // Once `ModuleParamsClient` is implemented, use its replay observable's `#Last()` method // to get the most recently (asynchronously) observed (and cached) value. -// TODO_BLOCKER(@bryanchriswhite,#543): We also don't really want to use the current value of the params. Instead, +// TODO_MAINNET(@bryanchriswhite,#543): We also don't really want to use the current value of the params. Instead, // we should be using the value that the params had for the session which includes queryHeight. func (sq *sharedQuerier) GetProofWindowOpenHeight(ctx context.Context, queryHeight int64) (int64, error) { sharedParams, err := sq.GetParams(ctx) @@ -94,10 +94,10 @@ func (sq *sharedQuerier) GetProofWindowOpenHeight(ctx context.Context, queryHeig // The grace period is the number of blocks after the session ends during which relays // SHOULD be included in the session which most recently ended. // -// TODO_TECHDEBT(#543): We don't really want to have to query the params for every method call. +// TODO_MAINNET(#543): We don't really want to have to query the params for every method call. // Once `ModuleParamsClient` is implemented, use its replay observable's `#Last()` method // to get the most recently (asynchronously) observed (and cached) value. -// TODO_BLOCKER(@bryanchriswhite, #543): We also don't really want to use the current value of the params. +// TODO_MAINNET(@bryanchriswhite, #543): We also don't really want to use the current value of the params. // Instead, we should be using the value that the params had for the session which includes queryHeight. func (sq *sharedQuerier) GetSessionGracePeriodEndHeight( ctx context.Context, @@ -113,10 +113,10 @@ func (sq *sharedQuerier) GetSessionGracePeriodEndHeight( // GetEarliestSupplierClaimCommitHeight returns the earliest block height at which a claim // for the session that includes queryHeight can be committed for a given supplier. // -// TODO_TECHDEBT(#543): We don't really want to have to query the params for every method call. +// TODO_MAINNET(#543): We don't really want to have to query the params for every method call. // Once `ModuleParamsClient` is implemented, use its replay observable's `#Last()` method // to get the most recently (asynchronously) observed (and cached) value. -// TODO_BLOCKER(@bryanchriswhite, #543): We also don't really want to use the current value of the params. +// TODO_MAINNET(@bryanchriswhite, #543): We also don't really want to use the current value of the params. // Instead, we should be using the value that the params had for the session which includes queryHeight. func (sq *sharedQuerier) GetEarliestSupplierClaimCommitHeight(ctx context.Context, queryHeight int64, supplierOperatorAddr string) (int64, error) { sharedParams, err := sq.GetParams(ctx) @@ -146,10 +146,10 @@ func (sq *sharedQuerier) GetEarliestSupplierClaimCommitHeight(ctx context.Contex // GetEarliestSupplierProofCommitHeight returns the earliest block height at which a proof // for the session that includes queryHeight can be committed for a given supplier. // -// TODO_TECHDEBT(#543): We don't really want to have to query the params for every method call. +// TODO_MAINNET(#543): We don't really want to have to query the params for every method call. // Once `ModuleParamsClient` is implemented, use its replay observable's `#Last()` method // to get the most recently (asynchronously) observed (and cached) value. -// TODO_BLOCKER(@bryanchriswhite, #543): We also don't really want to use the current value of the params. +// TODO_MAINNET(@bryanchriswhite, #543): We also don't really want to use the current value of the params. // Instead, we should be using the value that the params had for the session which includes queryHeight. func (sq *sharedQuerier) GetEarliestSupplierProofCommitHeight(ctx context.Context, queryHeight int64, supplierOperatorAddr string) (int64, error) { sharedParams, err := sq.GetParams(ctx) @@ -175,10 +175,10 @@ func (sq *sharedQuerier) GetEarliestSupplierProofCommitHeight(ctx context.Contex // GetComputeUnitsToTokensMultiplier returns the multiplier used to convert compute units to tokens. // -// TODO_TECHDEBT(#543): We don't really want to have to query the params for every method call. +// TODO_MAINNET(#543): We don't really want to have to query the params for every method call. // Once `ModuleParamsClient` is implemented, use its replay observable's `#Last()` method // to get the most recently (asynchronously) observed (and cached) value. -// TODO_BLOCKER(@bryanchriswhite, #543): We also don't really want to use the current value of the params. +// TODO_MAINNET(@bryanchriswhite, #543): We also don't really want to use the current value of the params. // Instead, we should be using the value that the params had for the session which includes queryHeight. func (sq *sharedQuerier) GetComputeUnitsToTokensMultiplier(ctx context.Context) (uint64, error) { sharedParams, err := sq.GetParams(ctx) diff --git a/pkg/crypto/rings/client.go b/pkg/crypto/rings/client.go index c33d5832e..8373be876 100644 --- a/pkg/crypto/rings/client.go +++ b/pkg/crypto/rings/client.go @@ -269,10 +269,10 @@ func (rc *ringClient) GetRingAddressesAtBlock( app *apptypes.Application, blockHeight int64, ) ([]string, error) { - // TODO_TECHDEBT(#543): We don't really want to have to query the params for every method call. + // TODO_MAINNET(#543): We don't really want to have to query the params for every method call. // Once `ModuleParamsClient` is implemented, use its replay observable's `#Last` method // to get the most recently (asynchronously) observed (and cached) value. - // TODO_BLOCKER(@bryanchriswhite, #543): We also don't really want to use the current value of the params. + // TODO_MAINNET(@bryanchriswhite, #543): We also don't really want to use the current value of the params. // Instead, we should be using the value that the params had for the session given by blockHeight. sharedParams, err := rc.sharedQuerier.GetParams(ctx) if err != nil { diff --git a/pkg/polylog/interface.go b/pkg/polylog/interface.go index b4ef28457..4f52edbbd 100644 --- a/pkg/polylog/interface.go +++ b/pkg/polylog/interface.go @@ -133,7 +133,7 @@ type Event interface { // To customize the key name, use the appropriate option from the respective // package when constructing a logger. // - // TODO_UPNEXT(@bryanchriswhite): ensure implementations' godoc examples cover + // TODO_POST_MAINNET(@bryanchriswhite): ensure implementations' godoc examples cover // options. Err(err error) Event @@ -141,7 +141,7 @@ type Event interface { // with the "time" key. To customize the key name, use the appropriate option // from the respective package when constructing a Logger. // - // TODO_UPNEXT(@bryanchriswhite): ensure implementations' godoc examples cover + // TODO_POST_MAINNET(@bryanchriswhite): ensure implementations' godoc examples cover // options. // // NOTE: It won't dedupe the "time" key if the Event (or *Context) has one diff --git a/pkg/relayer/config/types.go b/pkg/relayer/config/types.go index ba1411b14..8f72b0ff0 100644 --- a/pkg/relayer/config/types.go +++ b/pkg/relayer/config/types.go @@ -6,7 +6,7 @@ type RelayMinerServerType int const ( RelayMinerServerTypeHTTP RelayMinerServerType = iota - // TODO: Support other RelayMinerServerType: + // TODO_FUTURE: Support other RelayMinerServerType: // RelayMinerServerTypeHTTPS // RelayMinerServerTypeTCP // RelayMinerServerTypeUDP diff --git a/pkg/relayer/proxy/relay_verifier.go b/pkg/relayer/proxy/relay_verifier.go index f3b998c0f..a2df0f73a 100644 --- a/pkg/relayer/proxy/relay_verifier.go +++ b/pkg/relayer/proxy/relay_verifier.go @@ -102,10 +102,10 @@ func (rp *relayerProxy) getTargetSessionBlockHeight( currentHeight := rp.blockClient.LastBlock(ctx).Height() sessionEndHeight := relayRequest.Meta.SessionHeader.GetSessionEndBlockHeight() - // TODO_TECHDEBT(#543): We don't really want to have to query the params for every method call. + // TODO_MAINNET(#543): We don't really want to have to query the params for every method call. // Once `ModuleParamsClient` is implemented, use its replay observable's `#Last()` method // to get the most recently (asynchronously) observed (and cached) value. - // TODO_BLOCKER(@bryanchriswhite, #543): We also don't really want to use the current value of the params. + // TODO_MAINNET(@bryanchriswhite, #543): We also don't really want to use the current value of the params. // Instead, we should be using the value that the params had for the session given by sessionEndHeight. sharedParams, err := rp.sharedQuerier.GetParams(ctx) if err != nil { diff --git a/pkg/relayer/session/claim.go b/pkg/relayer/session/claim.go index ea508d1d8..61892f24c 100644 --- a/pkg/relayer/session/claim.go +++ b/pkg/relayer/session/claim.go @@ -104,10 +104,10 @@ func (rs *relayerSessionsManager) waitForEarliestCreateClaimsHeight( logger := rs.logger.With("session_end_height", sessionEndHeight) - // TODO_TECHDEBT(#543): We don't really want to have to query the params for every method call. + // TODO_MAINNET(#543): We don't really want to have to query the params for every method call. // Once `ModuleParamsClient` is implemented, use its replay observable's `#Last()` method // to get the most recently (asynchronously) observed (and cached) value. - // TODO_BLOCKER(@bryanchriswhite,#543): We also don't really want to use the current value of the params. Instead, + // TODO_MAINNET(@bryanchriswhite,#543): We also don't really want to use the current value of the params. Instead, // we should be using the value that the params had for the session which includes queryHeight. sharedParams, err := rs.sharedQueryClient.GetParams(ctx) if err != nil { diff --git a/pkg/relayer/session/proof.go b/pkg/relayer/session/proof.go index 9a1b61b03..f71341382 100644 --- a/pkg/relayer/session/proof.go +++ b/pkg/relayer/session/proof.go @@ -89,10 +89,10 @@ func (rs *relayerSessionsManager) waitForEarliestSubmitProofsHeightAndGeneratePr logger := rs.logger.With("session_end_height", sessionEndHeight) - // TODO_TECHDEBT(#543): We don't really want to have to query the params for every method call. + // TODO_MAINNET(#543): We don't really want to have to query the params for every method call. // Once `ModuleParamsClient` is implemented, use its replay observable's `#Last()` method // to get the most recently (asynchronously) observed (and cached) value. - // TODO_BLOCKER(@bryanchriswhite,#543): We also don't really want to use the current value of the params. Instead, + // TODO_MAINNET(@bryanchriswhite,#543): We also don't really want to use the current value of the params. Instead, // we should be using the value that the params had for the session which includes queryHeight. sharedParams, err := rs.sharedQueryClient.GetParams(ctx) if err != nil { diff --git a/tests/integration/service/relay_mining_difficulty_test.go b/tests/integration/service/relay_mining_difficulty_test.go index ffec64912..b907fa9fb 100644 --- a/tests/integration/service/relay_mining_difficulty_test.go +++ b/tests/integration/service/relay_mining_difficulty_test.go @@ -60,7 +60,7 @@ func TestUpdateRelayMiningDifficulty_NewServiceSeenForTheFirstTime(t *testing.T) trie := prepareSMST(t, sdkCtx, integrationApp, session, expectedNumRelays) // Compute the number of blocks to wait between different events - // TODO_BLOCKER(@bryanchriswhite): See this comment: https://github.com/pokt-network/poktroll/pull/610#discussion_r1645777322 + // TODO_BETA(@bryanchriswhite): See this comment: https://github.com/pokt-network/poktroll/pull/610#discussion_r1645777322 sessionEndHeight := session.Header.SessionEndBlockHeight earliestSupplierClaimCommitHeight := sharedtypes.GetEarliestSupplierClaimCommitHeight( &sharedParams, diff --git a/x/application/keeper/auto_undelegate.go b/x/application/keeper/auto_undelegate.go index e21ab2b4f..743bd7233 100644 --- a/x/application/keeper/auto_undelegate.go +++ b/x/application/keeper/auto_undelegate.go @@ -10,7 +10,7 @@ import ( // EndBlockerAutoUndelegateFromUnstakedGateways is called every block and handles // Application auto-undelegating from unstaked gateways. -// TODO_BLOCKER: Gateway unstaking should be delayed until the current block's +// TODO_BETA(@bryanchriswhite): Gateway unstaking should be delayed until the current block's // session end height to align with the application's pending undelegations. func (k Keeper) EndBlockerAutoUndelegateFromUnstakedGateways(ctx cosmostypes.Context) error { sdkCtx := cosmostypes.UnwrapSDKContext(ctx) diff --git a/x/application/keeper/msg_server_stake_application.go b/x/application/keeper/msg_server_stake_application.go index 49defb88b..2a6634a40 100644 --- a/x/application/keeper/msg_server_stake_application.go +++ b/x/application/keeper/msg_server_stake_application.go @@ -73,7 +73,7 @@ func (k msgServer) StakeApplication(ctx context.Context, msg *types.MsgStakeAppl // MUST ALWAYS have at least minimum stake. minStake := k.GetParams(ctx).MinStake - // TODO_CONSIDERATION: If we support multiple native tokens, we will need to + // TODO_POST_MAINNET: If we support multiple native tokens, we will need to // start checking the denom here. if msg.Stake.Amount.LT(minStake.Amount) { err = fmt.Errorf("application %q must stake at least %s", msg.GetAddress(), minStake) diff --git a/x/application/keeper/msg_server_unstake_application.go b/x/application/keeper/msg_server_unstake_application.go index e77f9a900..9a515c13f 100644 --- a/x/application/keeper/msg_server_unstake_application.go +++ b/x/application/keeper/msg_server_unstake_application.go @@ -12,7 +12,8 @@ import ( apptypes "github.com/pokt-network/poktroll/x/application/types" ) -// TODO(#489): Determine if an application needs an unbonding period after unstaking. +// UnstakeApplication kicks off the application unbonding process, at the end +// of which, it'll be fully unstaked. func (k msgServer) UnstakeApplication( ctx context.Context, msg *apptypes.MsgUnstakeApplication, diff --git a/x/application/module/simulation.go b/x/application/module/simulation.go index 1497b58b9..d78af4c66 100644 --- a/x/application/module/simulation.go +++ b/x/application/module/simulation.go @@ -24,27 +24,27 @@ var ( const ( opWeightMsgStakeApplication = "op_weight_msg_stake_application" - // TODO: Determine the simulation weight value + // TODO_TECHDEBT: Determine the simulation weight value defaultWeightMsgStakeApplication int = 100 opWeightMsgUnstakeApplication = "op_weight_msg_unstake_application" - // TODO: Determine the simulation weight value + // TODO_TECHDEBT: Determine the simulation weight value defaultWeightMsgUnstakeApplication int = 100 opWeightMsgDelegateToGateway = "op_weight_msg_delegate_to_gateway" - // TODO: Determine the simulation weight value + // TODO_TECHDEBT: Determine the simulation weight value defaultWeightMsgDelegateToGateway int = 100 opWeightMsgUndelegateFromGateway = "op_weight_msg_undelegate_from_gateway" - // TODO: Determine the simulation weight value + // TODO_TECHDEBT: Determine the simulation weight value defaultWeightMsgUndelegateFromGateway int = 100 opWeightMsgTransferApplication = "op_weight_msg_transfer_application" - // TODO: Determine the simulation weight value + // TODO_TECHDEBT: Determine the simulation weight value defaultWeightMsgTransferApplication int = 100 opWeightMsgUpdateParam = "op_weight_msg_update_param" - // TODO: Determine the simulation weight value + // TODO_TECHDEBT: Determine the simulation weight value defaultWeightMsgUpdateParam int = 100 // this line is used by starport scaffolding # simapp/module/const diff --git a/x/application/simulation/delegate_to_gateway.go b/x/application/simulation/delegate_to_gateway.go index f8230ef75..96d6efc0e 100644 --- a/x/application/simulation/delegate_to_gateway.go +++ b/x/application/simulation/delegate_to_gateway.go @@ -25,7 +25,7 @@ func SimulateMsgDelegateToGateway( GatewayAddress: simGatewayAccount.Address.String(), } - // TODO: Handling the DelegateToGateway simulation + // TODO_TECHDEBT: Handling the DelegateToGateway simulation return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "DelegateToGateway simulation not implemented"), nil, nil } diff --git a/x/application/simulation/stake_application.go b/x/application/simulation/stake_application.go index 9e5c94ca3..36d773fde 100644 --- a/x/application/simulation/stake_application.go +++ b/x/application/simulation/stake_application.go @@ -23,7 +23,7 @@ func SimulateMsgStakeApplication( Address: simAccount.Address.String(), } - // TODO: Handling the StakeApplication simulation + // TODO_TECHDEBT: Handling the StakeApplication simulation // See the documentation here to simulate application staking: https://docs.cosmos.network/main/learn/advanced/simulation return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(stakeMsg), "StakeApplication simulation not implemented"), nil, nil diff --git a/x/application/simulation/transfer_application.go b/x/application/simulation/transfer_application.go index ddd37d19c..9d99629d2 100644 --- a/x/application/simulation/transfer_application.go +++ b/x/application/simulation/transfer_application.go @@ -25,7 +25,7 @@ func SimulateMsgTransferApplication( DestinationAddress: simDstAppAccount.Address.String(), } - // TODO: Handling the TransferApplication simulation + // TODO_TECHDEBT: Handling the TransferApplication simulation return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "TransferApplication simulation not implemented"), nil, nil } diff --git a/x/application/simulation/undelegate_from_gateway.go b/x/application/simulation/undelegate_from_gateway.go index 5f6badb68..f778b2504 100644 --- a/x/application/simulation/undelegate_from_gateway.go +++ b/x/application/simulation/undelegate_from_gateway.go @@ -25,7 +25,7 @@ func SimulateMsgUndelegateFromGateway( GatewayAddress: simGatewayAccount.Address.String(), } - // TODO: Handling the UndelegateFromGateway simulation + // TODO_TECHDEBT: Handling the UndelegateFromGateway simulation return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "UndelegateFromGateway simulation not implemented"), nil, nil } diff --git a/x/application/simulation/unstake_application.go b/x/application/simulation/unstake_application.go index 80e337110..fceba04b3 100644 --- a/x/application/simulation/unstake_application.go +++ b/x/application/simulation/unstake_application.go @@ -23,7 +23,7 @@ func SimulateMsgUnstakeApplication( Address: simAccount.Address.String(), } - // TODO: Handling the UnstakeApplication simulation + // TODO_TECHDEBT: Handling the UnstakeApplication simulation return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "UnstakeApplication simulation not implemented"), nil, nil } diff --git a/x/application/simulation/update_param.go b/x/application/simulation/update_param.go index 9910027e8..cbaefadb7 100644 --- a/x/application/simulation/update_param.go +++ b/x/application/simulation/update_param.go @@ -23,7 +23,7 @@ func SimulateMsgUpdateParam( Authority: simAccount.Address.String(), } - // TODO: Handling the UpdateParam simulation + // TODO_TECHDEBT: Handling the UpdateParam simulation return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "UpdateParam simulation not implemented"), nil, nil } diff --git a/x/application/types/params.go b/x/application/types/params.go index 240c7ecd2..526b9d6cd 100644 --- a/x/application/types/params.go +++ b/x/application/types/params.go @@ -12,11 +12,11 @@ var ( KeyMaxDelegatedGateways = []byte("MaxDelegatedGateways") ParamMaxDelegatedGateways = "max_delegated_gateways" - // TODO_MAINNET: Determine the default value + // TODO_MAINNET(@olshansk): Determine the default value DefaultMaxDelegatedGateways uint64 = 7 KeyMinStake = []byte("MinStake") ParamMinStake = "min_stake" - // TODO_MAINNET: Determine the default value + // TODO_MAINNET(@olshansk): Determine the default value DefaultMinStake = cosmostypes.NewInt64Coin(volatile.DenomuPOKT, 1000000) // 1 POKT ) diff --git a/x/gateway/keeper/msg_server_unstake_gateway.go b/x/gateway/keeper/msg_server_unstake_gateway.go index 7aab1dc2f..2e09bec19 100644 --- a/x/gateway/keeper/msg_server_unstake_gateway.go +++ b/x/gateway/keeper/msg_server_unstake_gateway.go @@ -12,7 +12,7 @@ import ( "github.com/pokt-network/poktroll/x/gateway/types" ) -// TODO_BLOCKER(#489): Apps & gateways unbonding periods +// TODO_MAINNET(@bryanchriswhite): Implement Gateway unbonding periods func (k msgServer) UnstakeGateway( goCtx context.Context, msg *types.MsgUnstakeGateway, diff --git a/x/gateway/module/simulation.go b/x/gateway/module/simulation.go index 9b69e5bd0..7bc893005 100644 --- a/x/gateway/module/simulation.go +++ b/x/gateway/module/simulation.go @@ -24,15 +24,15 @@ var ( const ( opWeightMsgStakeGateway = "op_weight_msg_stake_gateway" - // TODO: Determine the simulation weight value + // TODO_TECHDEBT: Determine the simulation weight value defaultWeightMsgStakeGateway int = 100 opWeightMsgUnstakeGateway = "op_weight_msg_unstake_gateway" - // TODO: Determine the simulation weight value + // TODO_TECHDEBT: Determine the simulation weight value defaultWeightMsgUnstakeGateway int = 100 opWeightMsgUpdateParam = "op_weight_msg_update_param" - // TODO: Determine the simulation weight value + // TODO_TECHDEBT: Determine the simulation weight value defaultWeightMsgUpdateParam int = 100 // this line is used by starport scaffolding # simapp/module/const diff --git a/x/gateway/module/tx.go b/x/gateway/module/tx.go index a6b9cea86..1792814fa 100644 --- a/x/gateway/module/tx.go +++ b/x/gateway/module/tx.go @@ -10,7 +10,7 @@ import ( ) // GetTxCmd returns the transaction commands for this module -// TODO_MAINNET(#370): remove if custom query commands are consolidated into AutoCLI. +// TODO_TECHDEBT(#370): remove if custom query commands are consolidated into AutoCLI. func (am AppModule) GetTxCmd() *cobra.Command { cmd := &cobra.Command{ Use: types.ModuleName, diff --git a/x/gateway/simulation/stake_gateway.go b/x/gateway/simulation/stake_gateway.go index d7a818c5b..4c6b42b51 100644 --- a/x/gateway/simulation/stake_gateway.go +++ b/x/gateway/simulation/stake_gateway.go @@ -23,7 +23,7 @@ func SimulateMsgStakeGateway( Address: simAccount.Address.String(), } - // TODO: Handling the StakeGateway simulation + // TODO_TECHDEBT: Handling the StakeGateway simulation return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(stakeMsg), "StakeGateway simulation not implemented"), nil, nil } diff --git a/x/gateway/simulation/unstake_gateway.go b/x/gateway/simulation/unstake_gateway.go index 0f1f2f29c..9aa51cd59 100644 --- a/x/gateway/simulation/unstake_gateway.go +++ b/x/gateway/simulation/unstake_gateway.go @@ -23,7 +23,7 @@ func SimulateMsgUnstakeGateway( Address: simAccount.Address.String(), } - // TODO: Handling the UnstakeGateway simulation + // TODO_TECHDEBT: Handling the UnstakeGateway simulation return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "UnstakeGateway simulation not implemented"), nil, nil } diff --git a/x/gateway/simulation/update_param.go b/x/gateway/simulation/update_param.go index ec392f99a..f33530e95 100644 --- a/x/gateway/simulation/update_param.go +++ b/x/gateway/simulation/update_param.go @@ -23,7 +23,7 @@ func SimulateMsgUpdateParam( Authority: simAccount.Address.String(), } - // TODO: Handling the UpdateParam simulation + // TODO_TECHDEBT: Handling the UpdateParam simulation return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "UpdateParam simulation not implemented"), nil, nil } diff --git a/x/proof/keeper/msg_server_create_claim.go b/x/proof/keeper/msg_server_create_claim.go index 6bfa498d5..01a5f509a 100644 --- a/x/proof/keeper/msg_server_create_claim.go +++ b/x/proof/keeper/msg_server_create_claim.go @@ -126,7 +126,7 @@ func (k msgServer) CreateClaim( Claim: &claim, NumRelays: numRelays, NumClaimedComputeUnits: numClaimComputeUnits, - // TODO_FOLLOWUP: Add NumEstimatedComputeUnits and ClaimedAmountUpokt + // TODO_BETA(@red-0ne): Add NumEstimatedComputeUnits and ClaimedAmountUpokt }, ) case false: @@ -135,7 +135,7 @@ func (k msgServer) CreateClaim( Claim: &claim, NumRelays: numRelays, NumClaimedComputeUnits: numClaimComputeUnits, - // TODO_FOLLOWUP: Add NumEstimatedComputeUnits and ClaimedAmountUpokt + // TODO_BETA(@red-0ne): Add NumEstimatedComputeUnits and ClaimedAmountUpokt }, ) } diff --git a/x/proof/keeper/msg_server_submit_proof.go b/x/proof/keeper/msg_server_submit_proof.go index 625c29e68..6496a3f30 100644 --- a/x/proof/keeper/msg_server_submit_proof.go +++ b/x/proof/keeper/msg_server_submit_proof.go @@ -143,7 +143,7 @@ func (k msgServer) SubmitProof( Proof: &proof, NumRelays: numRelays, NumClaimedComputeUnits: numClaimComputeUnits, - // TODO_FOLLOWUP: Add NumEstimatedComputeUnits and ClaimedAmountUpokt + // TODO_BETA(@red-0ne): Add NumEstimatedComputeUnits and ClaimedAmountUpokt }, ) case false: @@ -153,7 +153,7 @@ func (k msgServer) SubmitProof( Proof: &proof, NumRelays: numRelays, NumClaimedComputeUnits: numClaimComputeUnits, - // TODO_FOLLOWUP: Add NumEstimatedComputeUnits and ClaimedAmountUpokt + // TODO_BETA(@red-0ne): Add NumEstimatedComputeUnits and ClaimedAmountUpokt }, ) } @@ -212,7 +212,7 @@ func (k Keeper) deductProofSubmissionFee(ctx context.Context, supplierOperatorAd // ProofRequirementForClaim checks if a proof is required for a claim. // If it is not, the claim will be settled without a proof. // If it is, the claim will only be settled if a valid proof is available. -// TODO_BLOCKER(@olshansk, #419): Document safety assumptions of the probabilistic proofs mechanism. +// TODO_BETA(@olshansk): Document safety assumptions of the probabilistic proofs mechanism. func (k Keeper) ProofRequirementForClaim(ctx context.Context, claim *types.Claim) (_ types.ProofRequirementReason, err error) { logger := k.logger.With("method", "proofRequirementForClaim") @@ -241,9 +241,9 @@ func (k Keeper) ProofRequirementForClaim(ctx context.Context, claim *types.Claim } // Require a proof if the claim's compute units meets or exceeds the threshold. - // TODO_MAINNET(@olshansk, @red-0ne): Should the threshold be dependant on the stake as well + // TODO_BETA(@red-0ne): Should the threshold be dependant on the stake as well // so we slash proportional to the compute units? - // TODO_IMPROVE(@red-0ne): It might make sense to include whether there was a proof + // TODO_BETA(@red-0ne): It might make sense to include whether there was a proof // submission error downstream from here. This would require a more comprehensive metrics API. if claimeduPOKT.Amount.GTE(proofParams.GetProofRequirementThreshold().Amount) { requirementReason = types.ProofRequirementReason_THRESHOLD @@ -309,7 +309,7 @@ func (k Keeper) getProofRequirementSeedBlockHash( proofWindowOpenHeight := sharedtypes.GetProofWindowOpenHeight(sharedParams, sessionEndHeight) proofWindowOpenBlockHash := k.sessionKeeper.GetBlockHash(ctx, proofWindowOpenHeight) - // TODO_TECHDEBT(@red-0ne): Update the method header of this function to accept (sharedParams, Claim, BlockHash). + // TODO_BETA(@red-0ne): Update the method header of this function to accept (sharedParams, Claim, BlockHash). // After doing so, please review all calling sites and simplify them accordingly. earliestSupplierProofCommitHeight := sharedtypes.GetEarliestSupplierProofCommitHeight( sharedParams, diff --git a/x/proof/keeper/msg_server_submit_proof_test.go b/x/proof/keeper/msg_server_submit_proof_test.go index a0ba84b44..3e6193e9d 100644 --- a/x/proof/keeper/msg_server_submit_proof_test.go +++ b/x/proof/keeper/msg_server_submit_proof_test.go @@ -238,7 +238,7 @@ func TestMsgServer_SubmitProof_Success(t *testing.T) { require.EqualValues(t, &proofs[0], proofSubmittedEvent.GetProof()) require.Equal(t, uint64(numRelays), proofSubmittedEvent.GetNumRelays()) require.Equal(t, uint64(numClaimComputeUnits), proofSubmittedEvent.GetNumClaimedComputeUnits()) - // TODO_FOLLOWUP: Add NumEstimatedComputeUnits and ClaimedAmountUpokt assertions + // TODO_BETA(@red-0ne): Add NumEstimatedComputeUnits and ClaimedAmountUpokt assertions }) } } diff --git a/x/proof/keeper/proof_requirement_test.go b/x/proof/keeper/proof_requirement_test.go index fb413e564..054080c0e 100644 --- a/x/proof/keeper/proof_requirement_test.go +++ b/x/proof/keeper/proof_requirement_test.go @@ -34,7 +34,7 @@ func TestKeeper_IsProofRequired(t *testing.T) { numTrueSamples atomic.Int64 ) - // TODO_BETA(@bryanchriswhite): This test is periodically flaky but theoretically shouldn't be. + // TODO_TECHDEBT(@bryanchriswhite): This test is periodically flaky but theoretically shouldn't be. // What can we do to increase it's consistency without diving tolerance by 2? sampleSize := poktrand.RequiredSampleSize(float64(probability), tolerance/2, confidence) diff --git a/x/proof/keeper/proof_validation.go b/x/proof/keeper/proof_validation.go index 46a0af656..614c5cf03 100644 --- a/x/proof/keeper/proof_validation.go +++ b/x/proof/keeper/proof_validation.go @@ -246,7 +246,7 @@ func (k Keeper) validateClosestPath( // be received before proceeding. proofPathSeedBlockHash := k.sessionKeeper.GetBlockHash(ctx, earliestSupplierProofCommitHeight-1) - // TODO_BETA: Investigate "proof for the path provided does not match one expected by the on-chain protocol" + // TODO_BETA(@red-0ne): Investigate "proof for the path provided does not match one expected by the on-chain protocol" // error that may occur due to block height differing from the off-chain part. k.logger.Info("E2E_DEBUG: height for block hash when verifying the proof", earliestSupplierProofCommitHeight, sessionHeader.GetSessionId()) diff --git a/x/proof/keeper/session.go b/x/proof/keeper/session.go index 0d8bb446a..9d33d76c6 100644 --- a/x/proof/keeper/session.go +++ b/x/proof/keeper/session.go @@ -105,7 +105,7 @@ func (k Keeper) validateClaimWindow( currentHeight := sdkCtx.BlockHeight() // Ensure the current block height is ON or AFTER the supplier's earliest claim commit height. - // TODO_BLOCKER(@bryanchriswhite, @red-0ne): Enforce an additional "latest + // TODO_MAINNET(@bryanchriswhite, @red-0ne): Enforce an additional "latest // supplier claim/proof commit offset" such that all suppliers have the same // "supplier claim/proof commit window" size. // See: https://github.com/pokt-network/poktroll/pull/620/files#r1656548473. diff --git a/x/proof/module/simulation.go b/x/proof/module/simulation.go index ff38e4758..3cc2a02f3 100644 --- a/x/proof/module/simulation.go +++ b/x/proof/module/simulation.go @@ -24,15 +24,15 @@ var ( const ( opWeightMsgCreateClaim = "op_weight_msg_create_claim" - // TODO: Determine the simulation weight value + // TODO_TECHDEBT: Determine the simulation weight value defaultWeightMsgCreateClaim int = 100 opWeightMsgSubmitProof = "op_weight_msg_submit_proof" - // TODO: Determine the simulation weight value + // TODO_TECHDEBT: Determine the simulation weight value defaultWeightMsgSubmitProof int = 100 opWeightMsgUpdateParam = "op_weight_msg_update_param" - // TODO: Determine the simulation weight value + // TODO_TECHDEBT: Determine the simulation weight value defaultWeightMsgUpdateParam int = 100 // this line is used by starport scaffolding # simapp/module/const diff --git a/x/proof/module/tx_create_claim.go b/x/proof/module/tx_create_claim.go index b2d57615c..32622041c 100644 --- a/x/proof/module/tx_create_claim.go +++ b/x/proof/module/tx_create_claim.go @@ -14,7 +14,7 @@ import ( sessiontypes "github.com/pokt-network/poktroll/x/session/types" ) -// TODO(@bryanchriswhite): Add unit tests for the CLI command when implementing the business logic. +// TODO_TEST(@bryanchriswhite): Add unit tests for the CLI command when implementing the business logic. func CmdCreateClaim() *cobra.Command { cmd := &cobra.Command{ diff --git a/x/proof/module/tx_submit_proof.go b/x/proof/module/tx_submit_proof.go index d1b161052..72aa20d00 100644 --- a/x/proof/module/tx_submit_proof.go +++ b/x/proof/module/tx_submit_proof.go @@ -15,7 +15,7 @@ import ( sessiontypes "github.com/pokt-network/poktroll/x/session/types" ) -// TODO(@bryanchriswhite): Add unit tests for the CLI command when implementing the business logic. +// TODO_TECHDEBT(@bryanchriswhite): Add unit tests for the CLI command when implementing the business logic. var _ = strconv.Itoa(0) diff --git a/x/proof/simulation/create_claim.go b/x/proof/simulation/create_claim.go index 0f6bd5419..a953935ef 100644 --- a/x/proof/simulation/create_claim.go +++ b/x/proof/simulation/create_claim.go @@ -22,7 +22,7 @@ func SimulateMsgCreateClaim( SupplierOperatorAddress: simAccount.Address.String(), } - // TODO: Handling the CreateClaim simulation + // TODO_TECHDEBT: Handling the CreateClaim simulation return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "CreateClaim simulation not implemented"), nil, nil } diff --git a/x/proof/simulation/submit_proof.go b/x/proof/simulation/submit_proof.go index b7261296c..84b4acef4 100644 --- a/x/proof/simulation/submit_proof.go +++ b/x/proof/simulation/submit_proof.go @@ -22,7 +22,7 @@ func SimulateMsgSubmitProof( SupplierOperatorAddress: simAccount.Address.String(), } - // TODO: Handling the SubmitProof simulation + // TODO_TECHDEBT: Handling the SubmitProof simulation return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "SubmitProof simulation not implemented"), nil, nil } diff --git a/x/proof/simulation/update_param.go b/x/proof/simulation/update_param.go index 3f7198f1c..3f617a169 100644 --- a/x/proof/simulation/update_param.go +++ b/x/proof/simulation/update_param.go @@ -22,7 +22,7 @@ func SimulateMsgUpdateParam( Authority: simAccount.Address.String(), } - // TODO: Handling the UpdateParam simulation + // TODO_TECHDEBT: Handling the UpdateParam simulation return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "UpdateParam simulation not implemented"), nil, nil } diff --git a/x/proof/types/shared_query_client.go b/x/proof/types/shared_query_client.go index df05ec113..574735e7e 100644 --- a/x/proof/types/shared_query_client.go +++ b/x/proof/types/shared_query_client.go @@ -42,7 +42,7 @@ func (sqc *SharedKeeperQueryClient) GetParams( // The grace period is the number of blocks after the session ends during which relays // SHOULD be included in the session which most recently ended. // -// TODO_BLOCKER(@bryanchriswhite, #543): We don't really want to use the current value of the params. +// TODO_MAINNET(@bryanchriswhite, #543): We don't really want to use the current value of the params. // Instead, we should be using the value that the params had for the session given by blockHeight. func (sqc *SharedKeeperQueryClient) GetSessionGracePeriodEndHeight( ctx context.Context, @@ -55,7 +55,7 @@ func (sqc *SharedKeeperQueryClient) GetSessionGracePeriodEndHeight( // GetClaimWindowOpenHeight returns the block height at which the claim window of // the session that includes queryHeight opens. // -// TODO_BLOCKER(@bryanchriswhite, #543): We don't really want to use the current value of the params. +// TODO_MAINNET(@bryanchriswhite, #543): We don't really want to use the current value of the params. // Instead, we should be using the value that the params had for the session given by blockHeight. func (sqc *SharedKeeperQueryClient) GetClaimWindowOpenHeight( ctx context.Context, @@ -68,7 +68,7 @@ func (sqc *SharedKeeperQueryClient) GetClaimWindowOpenHeight( // GetProofWindowOpenHeight returns the block height at which the proof window of // the session that includes queryHeight opens. // -// TODO_BLOCKER(@bryanchriswhite, #543): We don't really want to use the current value of the params. +// TODO_MAINNET(@bryanchriswhite, #543): We don't really want to use the current value of the params. // Instead, we should be using the value that the params had for the session given by blockHeight. func (sqc *SharedKeeperQueryClient) GetProofWindowOpenHeight( ctx context.Context, diff --git a/x/service/keeper/msg_server_add_service.go b/x/service/keeper/msg_server_add_service.go index 6df0bb60c..52fe8365e 100644 --- a/x/service/keeper/msg_server_add_service.go +++ b/x/service/keeper/msg_server_add_service.go @@ -47,7 +47,7 @@ func (k msgServer) AddService( ) } return nil, types.ErrServiceAlreadyExists.Wrapf( - "TODO(@adshmh): This is an ephemeral state of the code. Once we s/AddService/UpdateService/g, add the business logic here for updates here.", + "TODO_MAINNET(@red-0ne): This is an ephemeral state of the code. Once we s/AddService/UpdateService/g, add the business logic here for updates here.", ) } diff --git a/x/service/module/simulation.go b/x/service/module/simulation.go index 770624242..6853680b2 100644 --- a/x/service/module/simulation.go +++ b/x/service/module/simulation.go @@ -24,7 +24,7 @@ var ( const ( opWeightMsgAddService = "op_weight_msg_add_service" - // TODO: Determine the simulation weight value + // TODO_TECHDEBT: Determine the simulation weight value defaultWeightMsgAddService int = 100 // this line is used by starport scaffolding # simapp/module/const diff --git a/x/service/module/tx_add_service.go b/x/service/module/tx_add_service.go index dc5b6c911..e0e85fa1d 100644 --- a/x/service/module/tx_add_service.go +++ b/x/service/module/tx_add_service.go @@ -1,6 +1,6 @@ package service -// TODO_BETA: Add `UpdateService` or modify `AddService` to `UpsertService` to allow service owners +// TODO_MAINNET(@red-0ne): Add `UpdateService` or modify `AddService` to `UpsertService` to allow service owners // to update parameters of existing services. This will requiring updating `proto/poktroll/service/tx.proto` and // all downstream code paths. import ( @@ -18,7 +18,7 @@ import ( var _ = strconv.Itoa(0) -// TODO_UPNEXT: Change `add-service` to `update-service` so the source owner can +// TODO_MAINNET(@red-0ne): Change `add-service` to `update-service` so the source owner can // update the compute units per relay for an existing service. Make it possible // to update a service (e.g. update # of compute units per relay). This will require // search for all variations of `AddService` in the codebase (filenames, helpers, etc...), diff --git a/x/service/simulation/add_service.go b/x/service/simulation/add_service.go index dc9a13c30..022a81e9a 100644 --- a/x/service/simulation/add_service.go +++ b/x/service/simulation/add_service.go @@ -23,7 +23,7 @@ func SimulateMsgAddService( OwnerAddress: simAccount.Address.String(), } - // TODO: Handling the AddService simulation + // TODO_TECHDEBT: Handling the AddService simulation return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "AddService simulation not implemented"), nil, nil } diff --git a/x/service/types/params.go b/x/service/types/params.go index a454d86f1..b9bc3026b 100644 --- a/x/service/types/params.go +++ b/x/service/types/params.go @@ -10,7 +10,7 @@ import ( // DefaultAddServiceFee is the default value for the add service fee // parameter in the genesis state of the service module. -// TODO_BETA: Revisit default param values for service fee +// TODO_MAINNET: Revisit default param values for service fee var ( _ paramtypes.ParamSet = (*Params)(nil) diff --git a/x/service/types/relay.go b/x/service/types/relay.go index 1200c6697..2824538de 100644 --- a/x/service/types/relay.go +++ b/x/service/types/relay.go @@ -82,7 +82,7 @@ func (res RelayResponse) GetSignableBytesHash() ([protocol.RelayHasherSize]byte, // and SupplierOperatorSignature fields. // TODO_TEST: Add tests for RelayResponse validation func (res *RelayResponse) ValidateBasic() error { - // TODO: if a client gets a response with an invalid/incomplete + // TODO_POST_MAINNET: if a client gets a response with an invalid/incomplete // SessionHeader, consider sending an on-chain challenge, lowering their // QoS, or other future work. diff --git a/x/session/keeper/session_hydrator.go b/x/session/keeper/session_hydrator.go index bde2f6dbf..5f259aa78 100644 --- a/x/session/keeper/session_hydrator.go +++ b/x/session/keeper/session_hydrator.go @@ -60,7 +60,6 @@ func NewSessionHydrator( // GetSession implements of the exposed `UtilityModule.GetSession` function // TECHDEBT(#519,#348): Add custom error types depending on the type of issue that occurred and assert on them in the unit tests. -// TODO_BETA: Consider returning an error if the application's stake has become very low. func (k Keeper) HydrateSession(ctx context.Context, sh *sessionHydrator) (*types.Session, error) { logger := k.Logger().With("method", "hydrateSession") @@ -102,8 +101,8 @@ func (k Keeper) hydrateSessionMetadata(ctx context.Context, sh *sessionHydrator) ) } - // TODO_BLOCKER(@bryanchriswhite, #543): If the num_blocks_per_session param has ever been changed, - // this function may cause unexpected behavior for historical sessions. + // TODO_MAINNET(@bryanchriswhite, #543): If the num_blocks_per_session param + // has ever been changed, this function may cause unexpected behavior for historical sessions. sharedParams := k.sharedKeeper.GetParams(ctx) sh.session.NumBlocksPerSession = int64(sharedParams.NumBlocksPerSession) sh.session.SessionNumber = sharedtypes.GetSessionNumber(&sharedParams, sh.blockHeight) @@ -220,7 +219,7 @@ func (k Keeper) hydrateSessionSuppliers(ctx context.Context, sh *sessionHydrator return nil } -// TODO_BETA: We are using a `Go` native implementation for a pseudo-random +// TODO_MAINNET: We are using a `Go` native implementation for a pseudo-random // number generator. In order for it to be language agnostic, a general purpose // algorithm MUST be used. pseudoRandomSelection returns a random subset of the // candidates. diff --git a/x/session/module/module.go b/x/session/module/module.go index 3738b5331..86c88be84 100644 --- a/x/session/module/module.go +++ b/x/session/module/module.go @@ -149,7 +149,7 @@ func (am AppModule) BeginBlock(_ context.Context) error { // EndBlock contains the logic that is automatically triggered at the end of each block. // The end block implementation is optional. -// TODO_TECHDEBT( @red-0ne): Add unit/integration tests for this. +// TODO_TEST( @red-0ne): Add unit/integration tests for this. func (am AppModule) EndBlock(ctx context.Context) error { logger := am.keeper.Logger().With("EndBlock", "SessionModuleEndBlock") sdkCtx := sdk.UnwrapSDKContext(ctx) diff --git a/x/shared/module/simulation.go b/x/shared/module/simulation.go index a01d2077e..4e580e541 100644 --- a/x/shared/module/simulation.go +++ b/x/shared/module/simulation.go @@ -24,7 +24,7 @@ var ( const ( opWeightMsgUpdateParam = "op_weight_msg_update_param" - // TODO: Determine the simulation weight value + // TODO_TECHDEBT: Determine the simulation weight value defaultWeightMsgUpdateParam int = 100 // this line is used by starport scaffolding # simapp/module/const diff --git a/x/shared/simulation/update_param.go b/x/shared/simulation/update_param.go index 6ea20fe4e..983e35eff 100644 --- a/x/shared/simulation/update_param.go +++ b/x/shared/simulation/update_param.go @@ -23,7 +23,7 @@ func SimulateMsgUpdateParam( Authority: simAccount.Address.String(), } - // TODO: Handling the UpdateParam simulation + // TODO_TECHDEBT: Handling the UpdateParam simulation return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "UpdateParam simulation not implemented"), nil, nil } diff --git a/x/shared/types/service_configs.go b/x/shared/types/service_configs.go index 2538d3152..122a10241 100644 --- a/x/shared/types/service_configs.go +++ b/x/shared/types/service_configs.go @@ -72,7 +72,7 @@ func ValidateSupplierServiceConfigs(services []*SupplierServiceConfig) error { return fmt.Errorf("endpoint.RpcType is not a valid RPCType: %v", serviceConfig) } - // TODO_MAINNET(@okdas)/TODO_DISCUSS: Either add validation for `endpoint.Configs` (can be a part of + // TODO_MAINNET(@okdas): Either add validation for `endpoint.Configs` (can be a part of // `parseEndpointConfigs`), or change the config structure to be more clear about what is expected here // as currently, this is just a map[string]string, when values can be other types. // if endpoint.Configs == nil { diff --git a/x/shared/types/session.go b/x/shared/types/session.go index 6aedd87e5..ea75a0e3b 100644 --- a/x/shared/types/session.go +++ b/x/shared/types/session.go @@ -11,7 +11,7 @@ func GetSessionStartHeight(sharedParams *Params, queryHeight int64) int64 { numBlocksPerSession := int64(sharedParams.GetNumBlocksPerSession()) - // TODO_BLOCKER(@bryanchriswhite, #543): If the num_blocks_per_session param has ever been changed, + // TODO_BETA(@bryanchriswhite, #543): If the num_blocks_per_session param has ever been changed, // this function may cause unexpected behavior. return queryHeight - ((queryHeight - 1) % numBlocksPerSession) } @@ -44,7 +44,7 @@ func GetSessionNumber(sharedParams *Params, queryHeight int64) int64 { numBlocksPerSession := int64(sharedParams.GetNumBlocksPerSession()) - // TODO_BLOCKER(@bryanchriswhite, #543): If the num_blocks_per_session param has ever been changed, + // TODO_MAINNET(@bryanchriswhite, #543): If the num_blocks_per_session param has ever been changed, // this function may cause unexpected behavior. return ((queryHeight - 1) / numBlocksPerSession) + 1 } @@ -99,7 +99,7 @@ func GetProofWindowCloseHeight(sharedParams *Params, queryHeight int64) int64 { // GetEarliestSupplierClaimCommitHeight returns the earliest block height at which a claim // for the session that includes queryHeight can be committed for a given supplier // and the passed sharedParams. -// TODO_CLEANUP_DELETE(@red-0ne, @olshansk): Having claim distribution windows was +// TODO_TECHDEBT(@red-0ne): Having claim distribution windows was // a requirement that was never determined to be necessary, but implemented regardless. // We are keeping around the functions but TBD whether it is deemed necessary. The results // of #711 are tengentially related to this requirement, after which the functions, @@ -126,7 +126,7 @@ func GetEarliestSupplierClaimCommitHeight( // GetEarliestSupplierProofCommitHeight returns the earliest block height at which a proof // for the session that includes queryHeight can be committed for a given supplier // and the passed sharedParams. -// TODO_CLEANUP_DELETE(@red-0ne, @olshansk): Having proof distribution windows was +// TODO_TECHDEBT(@red-0ne): Having proof distribution windows was // a requirement that was never determined to be necessary, but implemented regardless. // We are keeping around the functions but TBD whether it is deemed necessary. The results // of #711 are tengentially related to this requirement, after which the functions, diff --git a/x/supplier/keeper/msg_server_stake_supplier.go b/x/supplier/keeper/msg_server_stake_supplier.go index f8eb5f548..a23392fd6 100644 --- a/x/supplier/keeper/msg_server_stake_supplier.go +++ b/x/supplier/keeper/msg_server_stake_supplier.go @@ -228,7 +228,7 @@ func (k msgServer) updateSupplier( // Update activation height for services update. New services are activated at the // end of the current session, while existing ones keep their activation height. - // TODO_CONSIDERAION: Service removal should take effect at the beginning of the + // TODO_MAINNET: Service removal should take effect at the beginning of the // next session, otherwise sessions that are fetched at their start height may // still include Suppliers that no longer provide the services they removed. // For the same reason, any SupplierEndpoint change should take effect at the diff --git a/x/supplier/module/abci.go b/x/supplier/module/abci.go index 86e463ea5..095e33501 100644 --- a/x/supplier/module/abci.go +++ b/x/supplier/module/abci.go @@ -8,7 +8,7 @@ import ( // EndBlocker is called every block and handles supplier related updates. func EndBlocker(ctx sdk.Context, k keeper.Keeper) error { - // TODO_IMPROVE(@red-0ne): Add logs and/or telemetry on the number of unbonded suppliers. + // TODO_IMPROVE: Add logs and/or telemetry on the number of unbonded suppliers. if err := k.EndBlockerUnbondSuppliers(ctx); err != nil { return err } diff --git a/x/supplier/module/query.go b/x/supplier/module/query.go index 7802db00e..b49ebf142 100644 --- a/x/supplier/module/query.go +++ b/x/supplier/module/query.go @@ -10,7 +10,7 @@ import ( ) // GetQueryCmd returns the cli query commands for this module -// TODO_MAINNET(#370): remove if custom query commands are consolidated into AutoCLI. +// TODO_TECHDEBT(#370): remove if custom query commands are consolidated into AutoCLI. func (am AppModule) GetQueryCmd() *cobra.Command { // Group supplier queries under a subcommand cmd := &cobra.Command{ diff --git a/x/supplier/module/simulation.go b/x/supplier/module/simulation.go index 3f0c913e2..16a45c896 100644 --- a/x/supplier/module/simulation.go +++ b/x/supplier/module/simulation.go @@ -24,15 +24,15 @@ var ( const ( opWeightMsgStakeSupplier = "op_weight_msg_stake_supplier" - // TODO: Determine the simulation weight value + // TODO_TECHDEBT: Determine the simulation weight value defaultWeightMsgStakeSupplier int = 100 opWeightMsgUnstakeSupplier = "op_weight_msg_unstake_supplier" - // TODO: Determine the simulation weight value + // TODO_TECHDEBT: Determine the simulation weight value defaultWeightMsgUnstakeSupplier int = 100 opWeightMsgUpdateParam = "op_weight_msg_update_param" - // TODO: Determine the simulation weight value + // TODO_TECHDEBT: Determine the simulation weight value defaultWeightMsgUpdateParam int = 100 // this line is used by starport scaffolding # simapp/module/const diff --git a/x/supplier/module/tx.go b/x/supplier/module/tx.go index 78d16f011..50bd4dde2 100644 --- a/x/supplier/module/tx.go +++ b/x/supplier/module/tx.go @@ -10,7 +10,7 @@ import ( ) // GetTxCmd returns the transaction commands for this module -// TODO_MAINNET(#370): remove if custom query commands are consolidated into AutoCLI. +// TODO_TECHDEBT: remove if custom query commands are consolidated into AutoCLI. func (am AppModule) GetTxCmd() *cobra.Command { cmd := &cobra.Command{ Use: types.ModuleName, diff --git a/x/supplier/simulation/stake_supplier.go b/x/supplier/simulation/stake_supplier.go index 144236c9c..3b01e55bd 100644 --- a/x/supplier/simulation/stake_supplier.go +++ b/x/supplier/simulation/stake_supplier.go @@ -21,10 +21,10 @@ func SimulateMsgStakeSupplier( simAccount, _ := simtypes.RandomAcc(r, accs) msg := &types.MsgStakeSupplier{ OperatorAddress: simAccount.Address.String(), - // TODO: Update all stake message fields + // TODO_TECHDEBT: Update all stake message fields } - // TODO: Handling the StakeSupplier simulation + // TODO_TECHDEBT: Handling the StakeSupplier simulation return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "StakeSupplier simulation not implemented"), nil, nil } diff --git a/x/supplier/simulation/unstake_supplier.go b/x/supplier/simulation/unstake_supplier.go index 16843fb06..00619bffd 100644 --- a/x/supplier/simulation/unstake_supplier.go +++ b/x/supplier/simulation/unstake_supplier.go @@ -23,7 +23,7 @@ func SimulateMsgUnstakeSupplier( OperatorAddress: simAccount.Address.String(), } - // TODO: Handling the UnstakeSupplier simulation + // TODO_TECHDEBT: Handling the UnstakeSupplier simulation return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "UnstakeSupplier simulation not implemented"), nil, nil } diff --git a/x/supplier/simulation/update_param.go b/x/supplier/simulation/update_param.go index cf9b8aa8e..03a062849 100644 --- a/x/supplier/simulation/update_param.go +++ b/x/supplier/simulation/update_param.go @@ -23,7 +23,7 @@ func SimulateMsgUpdateParam( Authority: simAccount.Address.String(), } - // TODO: Handling the UpdateParam simulation + // TODO_TECHDEBT: Handling the UpdateParam simulation return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "UpdateParam simulation not implemented"), nil, nil } diff --git a/x/supplier/types/genesis.go b/x/supplier/types/genesis.go index d63612fd1..95524ca95 100644 --- a/x/supplier/types/genesis.go +++ b/x/supplier/types/genesis.go @@ -32,7 +32,7 @@ func (gs GenesisState) Validate() error { // Check that the stake value for the suppliers is valid for _, supplier := range gs.SupplierList { - // TODO_MAINNET: Consider creating shared helpers across the board for stake validation, + // TODO_TECHDEBT: Consider creating shared helpers across the board for stake validation, // similar to how we have `ValidateAppServiceConfigs` below if supplier.Stake == nil { return ErrSupplierInvalidStake.Wrapf("nil stake amount for supplier") diff --git a/x/tokenomics/keeper/keeper_settle_pending_claims_test.go b/x/tokenomics/keeper/keeper_settle_pending_claims_test.go index aebde6324..4f49ed939 100644 --- a/x/tokenomics/keeper/keeper_settle_pending_claims_test.go +++ b/x/tokenomics/keeper/keeper_settle_pending_claims_test.go @@ -43,7 +43,7 @@ func init() { cmd.InitSDKConfig() } -// TODO_TECHDEBT(@olshansk): Consolidate the setup for all tests that use TokenomicsModuleKeepers +// TODO_TECHDEBT: Consolidate the setup for all tests that use TokenomicsModuleKeepers type TestSuite struct { suite.Suite diff --git a/x/tokenomics/keeper/settle_pending_claims.go b/x/tokenomics/keeper/settle_pending_claims.go index e4d0a7814..fd314d9b2 100644 --- a/x/tokenomics/keeper/settle_pending_claims.go +++ b/x/tokenomics/keeper/settle_pending_claims.go @@ -128,7 +128,7 @@ func (k Keeper) SettlePendingClaims(ctx sdk.Context) ( // If the proof is missing or invalid -> expire it if expirationReason != tokenomicstypes.ClaimExpirationReason_EXPIRATION_REASON_UNSPECIFIED { - // TODO_BETA(@red-0ne, @olshansk): Slash the supplier in proportion + // TODO_BETA(@red-0ne): Slash the supplier in proportion // to their stake. Consider allowing suppliers to RemoveClaim via a new // message in case it was sent by accident diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index c50cb0f92..6272d33d3 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -27,7 +27,7 @@ import ( var ( // Governance parameters for the TLMGlobalMint module - // TODO_UPNEXT(@olshansk, #732): Make this a governance parameter and give it a non-zero value + tests. + // TODO_BETA(@red-0ne): Make this a governance parameter and give it a non-zero value + tests. MintPerClaimedTokenGlobalInflation = 0.1 ) @@ -115,7 +115,7 @@ func init() { panic("mint allocation percentages do not add to 1.0") } - // TODO_UPNEXT(@Olshansk): Ensure that if `TLMGlobalMint` is present in the map, + // TODO_BETA(@red-0ne): Ensure that if `TLMGlobalMint` is present in the map, // then TLMGlobalMintReimbursementRequest will need to be there too. } @@ -292,8 +292,7 @@ func (k Keeper) ProcessTokenLogicModules( logger.Info(fmt.Sprintf("Finished TLM processing: %q", tlm)) } - // TODO_CONSIDERATION: If we support multiple native tokens, we will need to - // start checking the denom here. + // TODO_POST_MAINNET: If we support multiple native tokens, we will need to start checking the denom here. sessionEndHeight := sharedtypes.GetSessionEndHeight(&sharedParams, cosmostypes.UnwrapSDKContext(ctx).BlockHeight()) if application.Stake.Amount.LT(apptypes.DefaultMinStake.Amount) { // Mark the application as unbonding if it has less than the minimum stake. @@ -406,7 +405,7 @@ func (k Keeper) TokenLogicModuleGlobalMint( logger := k.Logger().With("method", "TokenLogicModuleGlobalMint") if MintPerClaimedTokenGlobalInflation == 0 { - // TODO_UPNEXT(@olshansk): Make sure to skip GMRR TLM in this case as well. + // TODO_BETA(@red-0ne): Make sure to skip GMRR TLM in this case as well. logger.Warn("global inflation is set to zero. Skipping Global Mint TLM.") return nil } @@ -567,7 +566,7 @@ func (k Keeper) ensureClaimAmountLimits( ) { logger = logger.With("helper", "ensureClaimAmountLimits") - // TODO_BETA_OR_MAINNET(@red-0ne): The application stake gets reduced with every claim + // TODO_BETA(@red-0ne): The application stake gets reduced with every claim // settlement. Relay miners use the appStake at the beginning of a session to determine // the maximum amount they can claim. We need to somehow access and propagate this // value (via context?) so it is the same for all TLM processors for each claim. @@ -668,7 +667,7 @@ func (k Keeper) distributeSupplierRewardsToShareHolders( // the settlement amount for a particular claim(s) or session(s). func calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin sdk.Coin) (sdk.Coin, big.Float) { // Determine how much new uPOKT to mint based on global per claim inflation. - // TODO_MAINNET: Consider using fixed point arithmetic for deterministic results. + // TODO_MAINNET(@red-0ne): Consider using fixed point arithmetic for deterministic results. settlementAmtFloat := new(big.Float).SetUint64(settlementCoin.Amount.Uint64()) newMintAmtFloat := new(big.Float).Mul(settlementAmtFloat, big.NewFloat(MintPerClaimedTokenGlobalInflation)) // DEV_NOTE: If new mint is less than 1 and more than 0, ceil it to 1 so that @@ -683,7 +682,7 @@ func calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin sdk // calculateAllocationAmount does big float arithmetic to determine the absolute // amount from amountFloat based on the allocation percentage provided. -// TODO_MAINNET(@bryanchriswhite): Measure and limit the precision loss here. +// TODO_MAINNET(@red-0ne): Measure and limit the precision loss here. func calculateAllocationAmount( amountFloat *big.Float, allocationPercentage float64, @@ -704,7 +703,7 @@ func GetShareAmountMap( totalDistributed := uint64(0) shareAmountMap = make(map[string]uint64, len(serviceRevShare)) for _, revShare := range serviceRevShare { - // TODO_MAINNET: Consider using fixed point arithmetic for deterministic results. + // TODO_MAINNET(@red-0ne): Consider using fixed point arithmetic for deterministic results. sharePercentageFloat := big.NewFloat(float64(revShare.RevSharePercentage) / 100) amountToDistributeFloat := big.NewFloat(float64(amountToDistribute)) shareAmount, _ := big.NewFloat(0).Mul(amountToDistributeFloat, sharePercentageFloat).Uint64() diff --git a/x/tokenomics/module/abci.go b/x/tokenomics/module/abci.go index c74e22737..8140263c9 100644 --- a/x/tokenomics/module/abci.go +++ b/x/tokenomics/module/abci.go @@ -66,7 +66,7 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) (err error) { expiredResult.NumComputeUnits, err, ) - // TODO_IMPROVE(#observability): Add a counter for expired compute units. + // TODO_POST_MAINNET: Add a counter for expired compute units. }() // Update the relay mining difficulty for every service that settled pending diff --git a/x/tokenomics/module/simulation.go b/x/tokenomics/module/simulation.go index 34b5d53d0..8c1da6012 100644 --- a/x/tokenomics/module/simulation.go +++ b/x/tokenomics/module/simulation.go @@ -24,7 +24,7 @@ var ( const ( opWeightMsgUpdateParam = "op_weight_msg_update_param" - // TODO: Determine the simulation weight value + // TODO_TECHDEBT: Determine the simulation weight value defaultWeightMsgUpdateParam int = 100 // this line is used by starport scaffolding # simapp/module/const diff --git a/x/tokenomics/module/tx_update_params.go b/x/tokenomics/module/tx_update_params.go index 7ae94faed..43aae6072 100644 --- a/x/tokenomics/module/tx_update_params.go +++ b/x/tokenomics/module/tx_update_params.go @@ -13,7 +13,7 @@ import ( var _ = strconv.Itoa(0) -// TODO_BLOCKER(@bryanchriswhite, #322): Update the CLI once we determine settle on how to maintain and update parameters. +// TODO_POST_MAINNET(@bryanchriswhite, #322): Update the CLI once we determine settle on how to maintain and update parameters. func CmdUpdateParams() *cobra.Command { cmd := &cobra.Command{ Use: "update-params", diff --git a/x/tokenomics/simulation/update_param.go b/x/tokenomics/simulation/update_param.go index fbf4bd7a6..2ee6dfc83 100644 --- a/x/tokenomics/simulation/update_param.go +++ b/x/tokenomics/simulation/update_param.go @@ -23,7 +23,7 @@ func SimulateMsgUpdateParam( Authority: simAccount.Address.String(), } - // TODO: Handling the UpdateParam simulation + // TODO_TECHDEBT: Handling the UpdateParam simulation return simtypes.NoOpMsg(types.ModuleName, sdk.MsgTypeURL(msg), "UpdateParam simulation not implemented"), nil, nil } From ff764308c0478a4323335aad5591372ffefd3053 Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Wed, 30 Oct 2024 21:56:21 +0100 Subject: [PATCH 3/4] [Tokenomics] Implement Global Mint Reimbursement Request (#878) ## Summary This PR adds * GMRR TLM * Ensures that the application has enough funds to cover for it. * Deducts the total global mint amount from the application's stake. * Sends the global mint amount from the application module account to the tokenomics module account to the PNF account. * The application still gets its global inflation share sent to its account. ## Issue - #732 ## Type of change Select one or more from the following: - [x] New feature, functionality or library ## Testing - [x] **Unit Tests**: `make go_develop_and_test` - [x] **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: Daniel Olshansky --- api/poktroll/tokenomics/event.pulsar.go | 953 +++++++++++++++++- e2e/tests/0_settlement.feature | 14 +- proto/poktroll/tokenomics/event.proto | 11 + .../integration/application/min_stake_test.go | 14 +- .../relay_mining_integration_test.go | 9 +- testutil/keeper/tokenomics.go | 45 +- x/tokenomics/keeper/settle_pending_claims.go | 47 +- x/tokenomics/keeper/token_logic_modules.go | 238 ++++- .../keeper/token_logic_modules_test.go | 83 +- x/tokenomics/types/errors.go | 1 + x/tokenomics/types/event.pb.go | 533 +++++++++- 11 files changed, 1765 insertions(+), 183 deletions(-) diff --git a/api/poktroll/tokenomics/event.pulsar.go b/api/poktroll/tokenomics/event.pulsar.go index 507b21ed9..cf18db79d 100644 --- a/api/poktroll/tokenomics/event.pulsar.go +++ b/api/poktroll/tokenomics/event.pulsar.go @@ -2616,6 +2616,761 @@ func (x *fastReflection_EventSupplierSlashed) ProtoMethods() *protoiface.Methods } } +var ( + md_EventApplicationReimbursementRequest protoreflect.MessageDescriptor + fd_EventApplicationReimbursementRequest_application_addr protoreflect.FieldDescriptor + fd_EventApplicationReimbursementRequest_supplier_operator_addr protoreflect.FieldDescriptor + fd_EventApplicationReimbursementRequest_supplier_owner_addr protoreflect.FieldDescriptor + fd_EventApplicationReimbursementRequest_service_id protoreflect.FieldDescriptor + fd_EventApplicationReimbursementRequest_session_id protoreflect.FieldDescriptor + fd_EventApplicationReimbursementRequest_amount protoreflect.FieldDescriptor +) + +func init() { + file_poktroll_tokenomics_event_proto_init() + md_EventApplicationReimbursementRequest = File_poktroll_tokenomics_event_proto.Messages().ByName("EventApplicationReimbursementRequest") + fd_EventApplicationReimbursementRequest_application_addr = md_EventApplicationReimbursementRequest.Fields().ByName("application_addr") + fd_EventApplicationReimbursementRequest_supplier_operator_addr = md_EventApplicationReimbursementRequest.Fields().ByName("supplier_operator_addr") + fd_EventApplicationReimbursementRequest_supplier_owner_addr = md_EventApplicationReimbursementRequest.Fields().ByName("supplier_owner_addr") + fd_EventApplicationReimbursementRequest_service_id = md_EventApplicationReimbursementRequest.Fields().ByName("service_id") + fd_EventApplicationReimbursementRequest_session_id = md_EventApplicationReimbursementRequest.Fields().ByName("session_id") + fd_EventApplicationReimbursementRequest_amount = md_EventApplicationReimbursementRequest.Fields().ByName("amount") +} + +var _ protoreflect.Message = (*fastReflection_EventApplicationReimbursementRequest)(nil) + +type fastReflection_EventApplicationReimbursementRequest EventApplicationReimbursementRequest + +func (x *EventApplicationReimbursementRequest) ProtoReflect() protoreflect.Message { + return (*fastReflection_EventApplicationReimbursementRequest)(x) +} + +func (x *EventApplicationReimbursementRequest) slowProtoReflect() protoreflect.Message { + mi := &file_poktroll_tokenomics_event_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_EventApplicationReimbursementRequest_messageType fastReflection_EventApplicationReimbursementRequest_messageType +var _ protoreflect.MessageType = fastReflection_EventApplicationReimbursementRequest_messageType{} + +type fastReflection_EventApplicationReimbursementRequest_messageType struct{} + +func (x fastReflection_EventApplicationReimbursementRequest_messageType) Zero() protoreflect.Message { + return (*fastReflection_EventApplicationReimbursementRequest)(nil) +} +func (x fastReflection_EventApplicationReimbursementRequest_messageType) New() protoreflect.Message { + return new(fastReflection_EventApplicationReimbursementRequest) +} +func (x fastReflection_EventApplicationReimbursementRequest_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_EventApplicationReimbursementRequest +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_EventApplicationReimbursementRequest) Descriptor() protoreflect.MessageDescriptor { + return md_EventApplicationReimbursementRequest +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_EventApplicationReimbursementRequest) Type() protoreflect.MessageType { + return _fastReflection_EventApplicationReimbursementRequest_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_EventApplicationReimbursementRequest) New() protoreflect.Message { + return new(fastReflection_EventApplicationReimbursementRequest) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_EventApplicationReimbursementRequest) Interface() protoreflect.ProtoMessage { + return (*EventApplicationReimbursementRequest)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_EventApplicationReimbursementRequest) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.ApplicationAddr != "" { + value := protoreflect.ValueOfString(x.ApplicationAddr) + if !f(fd_EventApplicationReimbursementRequest_application_addr, value) { + return + } + } + if x.SupplierOperatorAddr != "" { + value := protoreflect.ValueOfString(x.SupplierOperatorAddr) + if !f(fd_EventApplicationReimbursementRequest_supplier_operator_addr, value) { + return + } + } + if x.SupplierOwnerAddr != "" { + value := protoreflect.ValueOfString(x.SupplierOwnerAddr) + if !f(fd_EventApplicationReimbursementRequest_supplier_owner_addr, value) { + return + } + } + if x.ServiceId != "" { + value := protoreflect.ValueOfString(x.ServiceId) + if !f(fd_EventApplicationReimbursementRequest_service_id, value) { + return + } + } + if x.SessionId != "" { + value := protoreflect.ValueOfString(x.SessionId) + if !f(fd_EventApplicationReimbursementRequest_session_id, value) { + return + } + } + if x.Amount != nil { + value := protoreflect.ValueOfMessage(x.Amount.ProtoReflect()) + if !f(fd_EventApplicationReimbursementRequest_amount, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_EventApplicationReimbursementRequest) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": + return x.ApplicationAddr != "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_operator_addr": + return x.SupplierOperatorAddr != "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_owner_addr": + return x.SupplierOwnerAddr != "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": + return x.ServiceId != "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": + return x.SessionId != "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": + return x.Amount != nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) + } + panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_EventApplicationReimbursementRequest) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": + x.ApplicationAddr = "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_operator_addr": + x.SupplierOperatorAddr = "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_owner_addr": + x.SupplierOwnerAddr = "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": + x.ServiceId = "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": + x.SessionId = "" + case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": + x.Amount = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) + } + panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_EventApplicationReimbursementRequest) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": + value := x.ApplicationAddr + return protoreflect.ValueOfString(value) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_operator_addr": + value := x.SupplierOperatorAddr + return protoreflect.ValueOfString(value) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_owner_addr": + value := x.SupplierOwnerAddr + return protoreflect.ValueOfString(value) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": + value := x.ServiceId + return protoreflect.ValueOfString(value) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": + value := x.SessionId + return protoreflect.ValueOfString(value) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": + value := x.Amount + return protoreflect.ValueOfMessage(value.ProtoReflect()) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) + } + panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_EventApplicationReimbursementRequest) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": + x.ApplicationAddr = value.Interface().(string) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_operator_addr": + x.SupplierOperatorAddr = value.Interface().(string) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_owner_addr": + x.SupplierOwnerAddr = value.Interface().(string) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": + x.ServiceId = value.Interface().(string) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": + x.SessionId = value.Interface().(string) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": + x.Amount = value.Message().Interface().(*v1beta1.Coin) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) + } + panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_EventApplicationReimbursementRequest) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": + if x.Amount == nil { + x.Amount = new(v1beta1.Coin) + } + return protoreflect.ValueOfMessage(x.Amount.ProtoReflect()) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": + panic(fmt.Errorf("field application_addr of message poktroll.tokenomics.EventApplicationReimbursementRequest is not mutable")) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_operator_addr": + panic(fmt.Errorf("field supplier_operator_addr of message poktroll.tokenomics.EventApplicationReimbursementRequest is not mutable")) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_owner_addr": + panic(fmt.Errorf("field supplier_owner_addr of message poktroll.tokenomics.EventApplicationReimbursementRequest is not mutable")) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": + panic(fmt.Errorf("field service_id of message poktroll.tokenomics.EventApplicationReimbursementRequest is not mutable")) + case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": + panic(fmt.Errorf("field session_id of message poktroll.tokenomics.EventApplicationReimbursementRequest is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) + } + panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_EventApplicationReimbursementRequest) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "poktroll.tokenomics.EventApplicationReimbursementRequest.application_addr": + return protoreflect.ValueOfString("") + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_operator_addr": + return protoreflect.ValueOfString("") + case "poktroll.tokenomics.EventApplicationReimbursementRequest.supplier_owner_addr": + return protoreflect.ValueOfString("") + case "poktroll.tokenomics.EventApplicationReimbursementRequest.service_id": + return protoreflect.ValueOfString("") + case "poktroll.tokenomics.EventApplicationReimbursementRequest.session_id": + return protoreflect.ValueOfString("") + case "poktroll.tokenomics.EventApplicationReimbursementRequest.amount": + m := new(v1beta1.Coin) + return protoreflect.ValueOfMessage(m.ProtoReflect()) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: poktroll.tokenomics.EventApplicationReimbursementRequest")) + } + panic(fmt.Errorf("message poktroll.tokenomics.EventApplicationReimbursementRequest does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_EventApplicationReimbursementRequest) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in poktroll.tokenomics.EventApplicationReimbursementRequest", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_EventApplicationReimbursementRequest) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_EventApplicationReimbursementRequest) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_EventApplicationReimbursementRequest) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_EventApplicationReimbursementRequest) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*EventApplicationReimbursementRequest) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + l = len(x.ApplicationAddr) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.SupplierOperatorAddr) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.SupplierOwnerAddr) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.ServiceId) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + l = len(x.SessionId) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.Amount != nil { + l = options.Size(x.Amount) + n += 1 + l + runtime.Sov(uint64(l)) + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*EventApplicationReimbursementRequest) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if x.Amount != nil { + encoded, err := options.Marshal(x.Amount) + if err != nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, err + } + i -= len(encoded) + copy(dAtA[i:], encoded) + i = runtime.EncodeVarint(dAtA, i, uint64(len(encoded))) + i-- + dAtA[i] = 0x32 + } + if len(x.SessionId) > 0 { + i -= len(x.SessionId) + copy(dAtA[i:], x.SessionId) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.SessionId))) + i-- + dAtA[i] = 0x2a + } + if len(x.ServiceId) > 0 { + i -= len(x.ServiceId) + copy(dAtA[i:], x.ServiceId) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ServiceId))) + i-- + dAtA[i] = 0x22 + } + if len(x.SupplierOwnerAddr) > 0 { + i -= len(x.SupplierOwnerAddr) + copy(dAtA[i:], x.SupplierOwnerAddr) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.SupplierOwnerAddr))) + i-- + dAtA[i] = 0x1a + } + if len(x.SupplierOperatorAddr) > 0 { + i -= len(x.SupplierOperatorAddr) + copy(dAtA[i:], x.SupplierOperatorAddr) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.SupplierOperatorAddr))) + i-- + dAtA[i] = 0x12 + } + if len(x.ApplicationAddr) > 0 { + i -= len(x.ApplicationAddr) + copy(dAtA[i:], x.ApplicationAddr) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.ApplicationAddr))) + i-- + dAtA[i] = 0xa + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*EventApplicationReimbursementRequest) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: EventApplicationReimbursementRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: EventApplicationReimbursementRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ApplicationAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.ApplicationAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field SupplierOperatorAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.SupplierOperatorAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field SupplierOwnerAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.SupplierOwnerAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field ServiceId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.ServiceId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field SessionId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.SessionId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if x.Amount == nil { + x.Amount = &v1beta1.Coin{} + } + if err := options.Unmarshal(dAtA[iNdEx:postIndex], x.Amount); err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.0 @@ -2974,6 +3729,83 @@ func (x *EventSupplierSlashed) GetSlashingAmount() *v1beta1.Coin { return nil } +// EventApplicationReimbursementRequest is emitted when an application requests +// a reimbursement +type EventApplicationReimbursementRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` + SupplierOperatorAddr string `protobuf:"bytes,2,opt,name=supplier_operator_addr,json=supplierOperatorAddr,proto3" json:"supplier_operator_addr,omitempty"` + SupplierOwnerAddr string `protobuf:"bytes,3,opt,name=supplier_owner_addr,json=supplierOwnerAddr,proto3" json:"supplier_owner_addr,omitempty"` + ServiceId string `protobuf:"bytes,4,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` + SessionId string `protobuf:"bytes,5,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + Amount *v1beta1.Coin `protobuf:"bytes,6,opt,name=amount,proto3" json:"amount,omitempty"` +} + +func (x *EventApplicationReimbursementRequest) Reset() { + *x = EventApplicationReimbursementRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_poktroll_tokenomics_event_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EventApplicationReimbursementRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EventApplicationReimbursementRequest) ProtoMessage() {} + +// Deprecated: Use EventApplicationReimbursementRequest.ProtoReflect.Descriptor instead. +func (*EventApplicationReimbursementRequest) Descriptor() ([]byte, []int) { + return file_poktroll_tokenomics_event_proto_rawDescGZIP(), []int{4} +} + +func (x *EventApplicationReimbursementRequest) GetApplicationAddr() string { + if x != nil { + return x.ApplicationAddr + } + return "" +} + +func (x *EventApplicationReimbursementRequest) GetSupplierOperatorAddr() string { + if x != nil { + return x.SupplierOperatorAddr + } + return "" +} + +func (x *EventApplicationReimbursementRequest) GetSupplierOwnerAddr() string { + if x != nil { + return x.SupplierOwnerAddr + } + return "" +} + +func (x *EventApplicationReimbursementRequest) GetServiceId() string { + if x != nil { + return x.ServiceId + } + return "" +} + +func (x *EventApplicationReimbursementRequest) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +func (x *EventApplicationReimbursementRequest) GetAmount() *v1beta1.Coin { + if x != nil { + return x.Amount + } + return nil +} + var File_poktroll_tokenomics_event_proto protoreflect.FileDescriptor var file_poktroll_tokenomics_event_proto_rawDesc = []byte{ @@ -3076,26 +3908,45 @@ var file_poktroll_tokenomics_event_proto_rawDesc = []byte{ 0x73, 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x0e, 0x73, - 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2a, 0x60, 0x0a, - 0x15, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x58, 0x50, 0x49, 0x52, 0x41, - 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, - 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, - 0x4f, 0x46, 0x5f, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, - 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x42, - 0xbc, 0x01, 0xd8, 0xe2, 0x1e, 0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6b, 0x74, - 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x42, - 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x24, 0x63, - 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, - 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, - 0x69, 0x63, 0x73, 0xa2, 0x02, 0x03, 0x50, 0x54, 0x58, 0xaa, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, - 0x72, 0x6f, 0x6c, 0x6c, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xca, - 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xe2, 0x02, 0x1f, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, - 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x14, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, - 0x6c, 0x6c, 0x3a, 0x3a, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6c, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xa8, 0x02, + 0x0a, 0x24, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x69, 0x6d, 0x62, 0x75, 0x72, 0x73, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0f, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x64, 0x64, + 0x72, 0x12, 0x34, 0x0a, 0x16, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x6f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x14, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x4f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x75, 0x70, 0x70, 0x6c, + 0x69, 0x65, 0x72, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x4f, 0x77, + 0x6e, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x62, + 0x61, 0x73, 0x65, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, + 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2a, 0x60, 0x0a, 0x15, 0x43, 0x6c, 0x61, 0x69, + 0x6d, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, + 0x6e, 0x12, 0x21, 0x0a, 0x1d, 0x45, 0x58, 0x50, 0x49, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, + 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, 0x5f, 0x4d, 0x49, + 0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x52, 0x4f, 0x4f, 0x46, + 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x02, 0x42, 0xbc, 0x01, 0xd8, 0xe2, 0x1e, + 0x01, 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x42, 0x0a, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x24, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, + 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6f, 0x6b, 0x74, 0x72, + 0x6f, 0x6c, 0x6c, 0x2f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xa2, 0x02, + 0x03, 0x50, 0x54, 0x58, 0xaa, 0x02, 0x13, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x2e, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0xca, 0x02, 0x13, 0x50, 0x6f, 0x6b, + 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, + 0xe2, 0x02, 0x1f, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x5c, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0xea, 0x02, 0x14, 0x50, 0x6f, 0x6b, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x3a, 0x3a, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -3111,32 +3962,34 @@ func file_poktroll_tokenomics_event_proto_rawDescGZIP() []byte { } var file_poktroll_tokenomics_event_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_poktroll_tokenomics_event_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_poktroll_tokenomics_event_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_poktroll_tokenomics_event_proto_goTypes = []interface{}{ - (ClaimExpirationReason)(0), // 0: poktroll.tokenomics.ClaimExpirationReason - (*EventClaimExpired)(nil), // 1: poktroll.tokenomics.EventClaimExpired - (*EventClaimSettled)(nil), // 2: poktroll.tokenomics.EventClaimSettled - (*EventApplicationOverserviced)(nil), // 3: poktroll.tokenomics.EventApplicationOverserviced - (*EventSupplierSlashed)(nil), // 4: poktroll.tokenomics.EventSupplierSlashed - (*proof.Claim)(nil), // 5: poktroll.proof.Claim - (*v1beta1.Coin)(nil), // 6: cosmos.base.v1beta1.Coin - (proof.ProofRequirementReason)(0), // 7: poktroll.proof.ProofRequirementReason + (ClaimExpirationReason)(0), // 0: poktroll.tokenomics.ClaimExpirationReason + (*EventClaimExpired)(nil), // 1: poktroll.tokenomics.EventClaimExpired + (*EventClaimSettled)(nil), // 2: poktroll.tokenomics.EventClaimSettled + (*EventApplicationOverserviced)(nil), // 3: poktroll.tokenomics.EventApplicationOverserviced + (*EventSupplierSlashed)(nil), // 4: poktroll.tokenomics.EventSupplierSlashed + (*EventApplicationReimbursementRequest)(nil), // 5: poktroll.tokenomics.EventApplicationReimbursementRequest + (*proof.Claim)(nil), // 6: poktroll.proof.Claim + (*v1beta1.Coin)(nil), // 7: cosmos.base.v1beta1.Coin + (proof.ProofRequirementReason)(0), // 8: poktroll.proof.ProofRequirementReason } var file_poktroll_tokenomics_event_proto_depIdxs = []int32{ - 5, // 0: poktroll.tokenomics.EventClaimExpired.claim:type_name -> poktroll.proof.Claim - 0, // 1: poktroll.tokenomics.EventClaimExpired.expiration_reason:type_name -> poktroll.tokenomics.ClaimExpirationReason - 6, // 2: poktroll.tokenomics.EventClaimExpired.claimed_upokt:type_name -> cosmos.base.v1beta1.Coin - 5, // 3: poktroll.tokenomics.EventClaimSettled.claim:type_name -> poktroll.proof.Claim - 7, // 4: poktroll.tokenomics.EventClaimSettled.proof_requirement:type_name -> poktroll.proof.ProofRequirementReason - 6, // 5: poktroll.tokenomics.EventClaimSettled.claimed_upokt:type_name -> cosmos.base.v1beta1.Coin - 6, // 6: poktroll.tokenomics.EventApplicationOverserviced.expected_burn:type_name -> cosmos.base.v1beta1.Coin - 6, // 7: poktroll.tokenomics.EventApplicationOverserviced.effective_burn:type_name -> cosmos.base.v1beta1.Coin - 6, // 8: poktroll.tokenomics.EventSupplierSlashed.slashing_amount:type_name -> cosmos.base.v1beta1.Coin - 9, // [9:9] is the sub-list for method output_type - 9, // [9:9] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 6, // 0: poktroll.tokenomics.EventClaimExpired.claim:type_name -> poktroll.proof.Claim + 0, // 1: poktroll.tokenomics.EventClaimExpired.expiration_reason:type_name -> poktroll.tokenomics.ClaimExpirationReason + 7, // 2: poktroll.tokenomics.EventClaimExpired.claimed_upokt:type_name -> cosmos.base.v1beta1.Coin + 6, // 3: poktroll.tokenomics.EventClaimSettled.claim:type_name -> poktroll.proof.Claim + 8, // 4: poktroll.tokenomics.EventClaimSettled.proof_requirement:type_name -> poktroll.proof.ProofRequirementReason + 7, // 5: poktroll.tokenomics.EventClaimSettled.claimed_upokt:type_name -> cosmos.base.v1beta1.Coin + 7, // 6: poktroll.tokenomics.EventApplicationOverserviced.expected_burn:type_name -> cosmos.base.v1beta1.Coin + 7, // 7: poktroll.tokenomics.EventApplicationOverserviced.effective_burn:type_name -> cosmos.base.v1beta1.Coin + 7, // 8: poktroll.tokenomics.EventSupplierSlashed.slashing_amount:type_name -> cosmos.base.v1beta1.Coin + 7, // 9: poktroll.tokenomics.EventApplicationReimbursementRequest.amount:type_name -> cosmos.base.v1beta1.Coin + 10, // [10:10] is the sub-list for method output_type + 10, // [10:10] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name } func init() { file_poktroll_tokenomics_event_proto_init() } @@ -3193,6 +4046,18 @@ func file_poktroll_tokenomics_event_proto_init() { return nil } } + file_poktroll_tokenomics_event_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EventApplicationReimbursementRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -3200,7 +4065,7 @@ func file_poktroll_tokenomics_event_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_poktroll_tokenomics_event_proto_rawDesc, NumEnums: 1, - NumMessages: 4, + NumMessages: 5, NumExtensions: 0, NumServices: 0, }, diff --git a/e2e/tests/0_settlement.feature b/e2e/tests/0_settlement.feature index fb3e228d6..a6595eb37 100644 --- a/e2e/tests/0_settlement.feature +++ b/e2e/tests/0_settlement.feature @@ -6,7 +6,7 @@ # that can be used to clear the state of the chain between tests. Feature: Tokenomics Namespace - Scenario: Settle the session when a valid claim is within max limits and a valid proof is submitted and required via threshold + Scenario: TLM Mint=Burn when a valid claim is within max limits and a valid proof is submitted and required via threshold # Baseline Given the user has the pocketd binary installed # Network preparation and validation @@ -35,12 +35,13 @@ Feature: Tokenomics Namespace And the user should wait for the ClaimSettled event with "THRESHOLD" proof requirement to be broadcast # Validate the results # Please note that supplier mint is > app burn because of inflation - # TODO_TECHDEBT: Update this test such the the inflation is set and enforce that Mint=Burn + # TODO_TECHDEBT: Update this test such the inflation is set and enforce that Mint=Burn # Then add a separate test that only validates that inflation is enforced correctly Then the account balance of "supplier1" should be "898" uPOKT "more" than before - And the "application" stake of "app1" should be "840" uPOKT "less" than before + # The application stake should be less 840 * (1 + glbal_inflation) = 840 * 1.1 = 924 + And the "application" stake of "app1" should be "924" uPOKT "less" than before - Scenario: Settle the session when a valid claim is create but not required + Scenario: TLM Mint=Burn when a valid claim is create but not required # Baseline Given the user has the pocketd binary installed # Network preparation and validation @@ -70,9 +71,10 @@ Feature: Tokenomics Namespace And the user should wait for the ClaimSettled event with "NOT_REQUIRED" proof requirement to be broadcast # Validate the results # Please note that supplier mint is > app burn because of inflation - # TODO_TECHDEBT: Update this test such the the inflation is set and enforce that Mint=Burn + # TODO_TECHDEBT: Update this test such the inflation is set and enforce that Mint=Burn Then the account balance of "supplier1" should be "449" uPOKT "more" than before - And the "application" stake of "app1" should be "420" uPOKT "less" than before + # The application stake should be less 420 * (1 + glbal_inflation) = 420 * 1.1 = 462 + And the "application" stake of "app1" should be "462" uPOKT "less" than before # TODO_TEST: Implement the following scenarios # Scenario: Supplier revenue shares are properly distributed diff --git a/proto/poktroll/tokenomics/event.proto b/proto/poktroll/tokenomics/event.proto index fb807d121..23c4f8e10 100644 --- a/proto/poktroll/tokenomics/event.proto +++ b/proto/poktroll/tokenomics/event.proto @@ -79,4 +79,15 @@ message EventSupplierSlashed { // Amount slashed from the supplier's stake due to the expired claims. // This is a function of the number of expired claims and proof missing penalty. cosmos.base.v1beta1.Coin slashing_amount = 3; +} + +// EventApplicationReimbursementRequest is emitted when an application requests +// a reimbursement. +message EventApplicationReimbursementRequest { + string application_addr = 1; + string supplier_operator_addr = 2; + string supplier_owner_addr = 3; + string service_id = 4; + string session_id = 5; + cosmos.base.v1beta1.Coin amount = 6; } \ No newline at end of file diff --git a/tests/integration/application/min_stake_test.go b/tests/integration/application/min_stake_test.go index dc14736dc..52bc57912 100644 --- a/tests/integration/application/min_stake_test.go +++ b/tests/integration/application/min_stake_test.go @@ -5,7 +5,6 @@ import ( "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" @@ -25,6 +24,7 @@ import ( sessiontypes "github.com/pokt-network/poktroll/x/session/types" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" suppliertypes "github.com/pokt-network/poktroll/x/supplier/types" + tokenomicskeeper "github.com/pokt-network/poktroll/x/tokenomics/keeper" ) type applicationMinStakeTestSuite struct { @@ -51,7 +51,7 @@ func TestApplicationMinStakeTestSuite(t *testing.T) { } func (s *applicationMinStakeTestSuite) SetupTest() { - s.keepers, s.ctx = keeper.NewTokenomicsModuleKeepers(s.T(), cosmoslog.NewNopLogger()) + s.keepers, s.ctx = keeper.NewTokenomicsModuleKeepers(s.T(), cosmoslog.NewNopLogger(), keeper.WithProofRequirement(false)) proofParams := prooftypes.DefaultParams() proofParams.ProofRequestProbability = 0 @@ -235,7 +235,8 @@ func (s *applicationMinStakeTestSuite) getExpectedApp(claim *prooftypes.Claim) * expectedBurnCoin, err := claim.GetClaimeduPOKT(sharedParams, relayMiningDifficulty) require.NoError(s.T(), err) - expectedEndStake := s.appStake.Sub(expectedBurnCoin) + globalInflationAmt, _ := tokenomicskeeper.CalculateGlobalPerClaimMintInflationFromSettlementAmount(expectedBurnCoin) + expectedEndStake := s.appStake.Sub(expectedBurnCoin).Sub(globalInflationAmt) return &apptypes.Application{ Address: s.appBech32, Stake: &expectedEndStake, @@ -304,8 +305,11 @@ func (s *applicationMinStakeTestSuite) assertUnbondingEndEventObserved(expectedA func (s *applicationMinStakeTestSuite) assertAppStakeIsReturnedToBalance() { s.T().Helper() - expectedAppBurn := math.NewInt(int64(s.numRelays * s.numComputeUnitsPerRelay * sharedtypes.DefaultComputeUnitsToTokensMultiplier)) - expectedAppBalance := s.appStake.SubAmount(expectedAppBurn) + expectedAppBurn := int64(s.numRelays * s.numComputeUnitsPerRelay * sharedtypes.DefaultComputeUnitsToTokensMultiplier) + expectedAppBurnCoin := cosmostypes.NewInt64Coin(volatile.DenomuPOKT, expectedAppBurn) + globalInflationCoin, _ := tokenomicskeeper.CalculateGlobalPerClaimMintInflationFromSettlementAmount(expectedAppBurnCoin) + expectedAppBalance := s.appStake.Sub(expectedAppBurnCoin).Sub(globalInflationCoin) + appBalance := s.getAppBalance() require.Equal(s.T(), expectedAppBalance.Amount.Int64(), appBalance.Amount.Int64()) } diff --git a/tests/integration/tokenomics/relay_mining_integration_test.go b/tests/integration/tokenomics/relay_mining_integration_test.go index 2beeb2196..b97dc4b15 100644 --- a/tests/integration/tokenomics/relay_mining_integration_test.go +++ b/tests/integration/tokenomics/relay_mining_integration_test.go @@ -1,7 +1,6 @@ package integration_test import ( - "math" "math/big" "testing" @@ -84,6 +83,7 @@ func TestComputeNewDifficultyHash_RewardsReflectWorkCompleted(t *testing.T) { testutils.WithService(service), testutils.WithApplication(application), testutils.WithSupplier(supplier), + testutils.WithProofRequirement(false), ) sdkCtx := sdk.UnwrapSDKContext(ctx) sdkCtx = sdkCtx.WithBlockHeight(1) @@ -94,13 +94,6 @@ func TestComputeNewDifficultyHash_RewardsReflectWorkCompleted(t *testing.T) { err := keepers.SharedKeeper.SetParams(sdkCtx, sharedParams) require.NoError(t, err) - // Set the global proof params so we never need a proof (for simplicity of this test) - err = keepers.ProofKeeper.SetParams(sdkCtx, prooftypes.Params{ - ProofRequestProbability: 0, // we never need a proof randomly - ProofRequirementThreshold: &sdk.Coin{Denom: volatile.DenomuPOKT, Amount: sdkmath.NewInt(math.MaxInt64)}, // a VERY high threshold - }) - require.NoError(t, err) - // Update the relay mining difficulty so there's always a difficulty to retrieve // for the test service. _, err = keepers.ServiceKeeper.UpdateRelayMiningDifficulty(sdkCtx, map[string]uint64{service.Id: 1}) diff --git a/testutil/keeper/tokenomics.go b/testutil/keeper/tokenomics.go index 75d6551f4..73d6f8a05 100644 --- a/testutil/keeper/tokenomics.go +++ b/testutil/keeper/tokenomics.go @@ -2,10 +2,11 @@ package keeper import ( "context" + "math" "testing" "cosmossdk.io/log" - "cosmossdk.io/math" + cosmosmath "cosmossdk.io/math" "cosmossdk.io/store" "cosmossdk.io/store/metrics" storetypes "cosmossdk.io/store/types" @@ -29,6 +30,7 @@ import ( "github.com/stretchr/testify/require" "github.com/pokt-network/poktroll/app" + "github.com/pokt-network/poktroll/app/volatile" "github.com/pokt-network/poktroll/testutil/sample" "github.com/pokt-network/poktroll/testutil/tokenomics/mocks" appkeeper "github.com/pokt-network/poktroll/x/application/keeper" @@ -117,7 +119,7 @@ func TokenomicsKeeperWithActorAddrs(t testing.TB) ( // Prepare the test application. application := apptypes.Application{ Address: sample.AccAddress(), - Stake: &sdk.Coin{Denom: "upokt", Amount: math.NewInt(100000)}, + Stake: &sdk.Coin{Denom: "upokt", Amount: cosmosmath.NewInt(100000)}, ServiceConfigs: []*sharedtypes.ApplicationServiceConfig{{ServiceId: service.Id}}, } @@ -126,7 +128,7 @@ func TokenomicsKeeperWithActorAddrs(t testing.TB) ( supplier := sharedtypes.Supplier{ OwnerAddress: supplierOwnerAddr, OperatorAddress: supplierOwnerAddr, - Stake: &sdk.Coin{Denom: "upokt", Amount: math.NewInt(100000)}, + Stake: &sdk.Coin{Denom: "upokt", Amount: cosmosmath.NewInt(100000)}, Services: []*sharedtypes.SupplierServiceConfig{ { ServiceId: service.Id, @@ -199,6 +201,9 @@ func TokenomicsKeeperWithActorAddrs(t testing.TB) ( mockBankKeeper.EXPECT(). SendCoinsFromModuleToModule(gomock.Any(), tokenomicstypes.ModuleName, suppliertypes.ModuleName, gomock.Any()). AnyTimes() + mockBankKeeper.EXPECT(). + SendCoinsFromModuleToModule(gomock.Any(), apptypes.ModuleName, tokenomicstypes.ModuleName, gomock.Any()). + AnyTimes() // Mock the account keeper mockAccountKeeper := mocks.NewMockAccountKeeper(ctrl) @@ -346,9 +351,9 @@ func NewTokenomicsModuleKeepers( require.NoError(t, bankKeeper.SetParams(sdkCtx, banktypes.DefaultParams())) // Provide some initial funds to the suppliers & applications module accounts. - err = bankKeeper.MintCoins(sdkCtx, suppliertypes.ModuleName, sdk.NewCoins(sdk.NewCoin("upokt", math.NewInt(1000000000000)))) + err = bankKeeper.MintCoins(sdkCtx, suppliertypes.ModuleName, sdk.NewCoins(sdk.NewCoin("upokt", cosmosmath.NewInt(1000000000000)))) require.NoError(t, err) - err = bankKeeper.MintCoins(sdkCtx, apptypes.ModuleName, sdk.NewCoins(sdk.NewCoin("upokt", math.NewInt(1000000000000)))) + err = bankKeeper.MintCoins(sdkCtx, apptypes.ModuleName, sdk.NewCoins(sdk.NewCoin("upokt", cosmosmath.NewInt(1000000000000)))) require.NoError(t, err) // Construct a real shared keeper. @@ -513,3 +518,33 @@ func WithProposerAddr(addr string) TokenomicsModuleKeepersOpt { return sdkCtx } } + +// WithProofRequirement is an option to enable or disable the proof requirement +// in the tokenomics module keepers by setting the proof request probability to +// 1 or 0, respectively whie setting the proof requirement threshold to 0 or +// MaxInt64, respectively. +func WithProofRequirement(proofRequired bool) TokenomicsModuleKeepersOpt { + return func(ctx context.Context, keepers *TokenomicsModuleKeepers) context.Context { + + proofParams := keepers.ProofKeeper.GetParams(ctx) + if proofRequired { + // Require a proof 100% of the time probabilistically speaking. + proofParams.ProofRequestProbability = 1 + // Require a proof of any claim amount (i.e. anything greater than 0). + proofRequirementThreshold := cosmostypes.NewInt64Coin(volatile.DenomuPOKT, 0) + proofParams.ProofRequirementThreshold = &proofRequirementThreshold + } else { + // Never require a proof probabilistically speaking. + proofParams.ProofRequestProbability = 0 + // Require a proof for MaxInt64 claim amount (i.e. should never trigger). + proofRequirementThreshold := cosmostypes.NewInt64Coin(volatile.DenomuPOKT, math.MaxInt64) + proofParams.ProofRequirementThreshold = &proofRequirementThreshold + } + + if err := keepers.ProofKeeper.SetParams(ctx, proofParams); err != nil { + panic(err) + } + + return ctx + } +} diff --git a/x/tokenomics/keeper/settle_pending_claims.go b/x/tokenomics/keeper/settle_pending_claims.go index fd314d9b2..37a48b3f2 100644 --- a/x/tokenomics/keeper/settle_pending_claims.go +++ b/x/tokenomics/keeper/settle_pending_claims.go @@ -1,6 +1,7 @@ package keeper import ( + "context" "fmt" "cosmossdk.io/math" @@ -8,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/query" "github.com/pokt-network/poktroll/app/volatile" + apptypes "github.com/pokt-network/poktroll/x/application/types" prooftypes "github.com/pokt-network/poktroll/x/proof/types" servicekeeper "github.com/pokt-network/poktroll/x/service/keeper" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" @@ -35,6 +37,15 @@ func (k Keeper) SettlePendingClaims(ctx sdk.Context) ( return settledResult, expiredResult, err } + // Capture the applications initial stake which will be used to calculate the + // max share any claim could burn from the application stake. + // This ensures that each supplier can calculate the maximum amount it can take + // from an application's stake. + applicationInitialStakeMap, err := k.getApplicationInitialStakeMap(ctx, expiringClaims) + if err != nil { + return settledResult, expiredResult, err + } + blockHeight := ctx.BlockHeight() logger.Info(fmt.Sprintf("found %d expiring claims at block height %d", len(expiringClaims), blockHeight)) @@ -176,8 +187,11 @@ func (k Keeper) SettlePendingClaims(ctx sdk.Context) ( // 1. The claim does not require a proof. // 2. The claim requires a proof and a valid proof was found. + appAddress := claim.GetSessionHeader().GetApplicationAddress() + applicationInitialStake := applicationInitialStakeMap[appAddress] + // Manage the mint & burn accounting for the claim. - if err = k.ProcessTokenLogicModules(ctx, &claim); err != nil { + if err = k.ProcessTokenLogicModules(ctx, &claim, applicationInitialStake); err != nil { logger.Error(fmt.Sprintf("error processing token logic modules for claim %q: %v", claim.SessionHeader.SessionId, err)) return settledResult, expiredResult, err } @@ -402,3 +416,34 @@ func (k Keeper) slashSupplierStake( return nil } + +// getApplicationInitialStakeMap returns a map from an application address to the +// initial stake of the application. This is used to calculate the maximum share +// any claim could burn from the application stake. +func (k Keeper) getApplicationInitialStakeMap( + ctx context.Context, + expiringClaims []prooftypes.Claim, +) (applicationInitialStakeMap map[string]sdk.Coin, err error) { + applicationInitialStakeMap = make(map[string]sdk.Coin) + for _, claim := range expiringClaims { + appAddress := claim.SessionHeader.ApplicationAddress + // The same application is participating in other claims being settled, + // so we already capture its initial stake. + if _, isAppFound := applicationInitialStakeMap[appAddress]; isAppFound { + continue + } + + app, isAppFound := k.applicationKeeper.GetApplication(ctx, appAddress) + if !isAppFound { + err := apptypes.ErrAppNotFound.Wrapf( + "trying to settle a claim for an application that does not exist (which should never happen) with address: %q", + appAddress, + ) + return nil, err + } + + applicationInitialStakeMap[appAddress] = *app.GetStake() + } + + return applicationInitialStakeMap, nil +} diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index 6272d33d3..3dba9136a 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -27,8 +27,10 @@ import ( var ( // Governance parameters for the TLMGlobalMint module - // TODO_BETA(@red-0ne): Make this a governance parameter and give it a non-zero value + tests. - MintPerClaimedTokenGlobalInflation = 0.1 + // TODO_BETA(@red-0ne, #732): Make this a governance parameter and give it a non-zero value + tests. + // GlobalInflationPerClaim is the percentage of the claim amount that is minted + // by TLMGlobalMint to reward the actors in the network. + GlobalInflationPerClaim = 0.1 ) const ( @@ -68,11 +70,20 @@ const ( // global governance parameters in order to reward the participants providing // services while keeping inflation in check. TLMGlobalMint + + // TLMGlobalMintReimbursementRequest is the token logic module that complements + // TLMGlobalMint to enable permissionless demand. + // In order to prevent self-dealing attacks, applications will be overcharged by + // the amount equal to global inflation, those funds will be sent to the DAO/PNF, + // and an event will be emitted to track and send reimbursements; managed offchain by PNF. + // TODO_POST_MAINNET: Introduce proper tokenomics based on the research done by @rawthil and @shane. + TLMGlobalMintReimbursementRequest ) var tokenLogicModuleStrings = [...]string{ "TLMRelayBurnEqualsMint", "TLMGlobalMint", + "TLMGlobalMintReimbursementRequest", } func (tlm TokenLogicModule) String() string { @@ -105,8 +116,9 @@ type TokenLogicModuleProcessor func( // tokenLogicModuleProcessorMap is a map of TLMs to their respective independent processors. var tokenLogicModuleProcessorMap = map[TokenLogicModule]TokenLogicModuleProcessor{ - TLMRelayBurnEqualsMint: Keeper.TokenLogicModuleRelayBurnEqualsMint, - TLMGlobalMint: Keeper.TokenLogicModuleGlobalMint, + TLMRelayBurnEqualsMint: Keeper.TokenLogicModuleRelayBurnEqualsMint, + TLMGlobalMint: Keeper.TokenLogicModuleGlobalMint, + TLMGlobalMintReimbursementRequest: Keeper.TokenLogicModuleGlobalMintReimbursementRequest, } func init() { @@ -115,8 +127,11 @@ func init() { panic("mint allocation percentages do not add to 1.0") } - // TODO_BETA(@red-0ne): Ensure that if `TLMGlobalMint` is present in the map, - // then TLMGlobalMintReimbursementRequest will need to be there too. + _, hasGlobalMintTLM := tokenLogicModuleProcessorMap[TLMGlobalMint] + _, hasGlobalMintReimbursementRequestTLM := tokenLogicModuleProcessorMap[TLMGlobalMintReimbursementRequest] + if hasGlobalMintTLM != hasGlobalMintReimbursementRequestTLM { + panic("TLMGlobalMint and TLMGlobalMintReimbursementRequest must be (de-)activated together") + } } // ProcessTokenLogicModules is the entrypoint for all TLM processing. @@ -131,6 +146,7 @@ func init() { func (k Keeper) ProcessTokenLogicModules( ctx context.Context, claim *prooftypes.Claim, + applicationInitialStake cosmostypes.Coin, ) (err error) { logger := k.Logger().With("method", "ProcessTokenLogicModules") @@ -276,7 +292,7 @@ func (k Keeper) ProcessTokenLogicModules( // Ensure the claim amount is within the limits set by Relay Mining. // If not, update the settlement amount and emit relevant events. - actualSettlementCoin, err := k.ensureClaimAmountLimits(ctx, logger, &application, &supplier, claimSettlementCoin) + actualSettlementCoin, err := k.ensureClaimAmountLimits(ctx, logger, &application, &supplier, claimSettlementCoin, applicationInitialStake) if err != nil { return err } @@ -404,14 +420,13 @@ func (k Keeper) TokenLogicModuleGlobalMint( ) error { logger := k.Logger().With("method", "TokenLogicModuleGlobalMint") - if MintPerClaimedTokenGlobalInflation == 0 { - // TODO_BETA(@red-0ne): Make sure to skip GMRR TLM in this case as well. + if GlobalInflationPerClaim == 0 { logger.Warn("global inflation is set to zero. Skipping Global Mint TLM.") return nil } // Determine how much new uPOKT to mint based on global inflation - newMintCoin, newMintAmtFloat := calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin) + newMintCoin, newMintAmtFloat := CalculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin) if newMintCoin.Amount.Int64() == 0 { return tokenomicstypes.ErrTokenomicsMintAmountZero } @@ -481,6 +496,107 @@ func (k Keeper) TokenLogicModuleGlobalMint( return nil } +// TokenLogicModuleGlobalMintReimbursementRequest processes the business logic +// for the GlobalMintReimbursementRequest TLM. +func (k Keeper) TokenLogicModuleGlobalMintReimbursementRequest( + ctx context.Context, + service *sharedtypes.Service, + sessionHeader *sessiontypes.SessionHeader, + application *apptypes.Application, + supplier *sharedtypes.Supplier, + actualSettlementCoin cosmostypes.Coin, + relayMiningDifficulty *servicetypes.RelayMiningDifficulty, +) error { + logger := k.Logger().With("method", "TokenLogicModuleGlobalMintReimbursementRequest") + + // Do not process the reimbursement request if there is no global inflation. + if GlobalInflationPerClaim == 0 { + logger.Warn("global inflation is set to zero. Skipping Global Mint Reimbursement Request TLM.") + return nil + } + + // Determine how much new uPOKT to mint based on global inflation + newMintCoin, _ := CalculateGlobalPerClaimMintInflationFromSettlementAmount(actualSettlementCoin) + if newMintCoin.Amount.Int64() == 0 { + return tokenomicstypes.ErrTokenomicsMintAmountZero + } + + newAppStake, err := application.Stake.SafeSub(newMintCoin) + // This should THEORETICALLY NEVER fall below zero. + // `ensureClaimAmountLimits` should have already checked and adjusted the settlement + // amount so that the application stake covers the global inflation. + // TODO_POST_MAINNET: Consider removing this since it should never happen just to simplify the code + if err != nil { + return err + } + application.Stake = &newAppStake + logger.Info(fmt.Sprintf("updated application %q stake to %s", application.Address, newAppStake)) + + globalInflationMintedCoinsForClaim := sdk.NewCoins(newMintCoin) + + // Send the global per claim mint inflation uPOKT from the tokenomics module + // account to PNF/DAO. + daoAccountAddr, err := cosmostypes.AccAddressFromBech32(k.GetAuthority()) + if err != nil { + return tokenomicstypes.ErrTokenomicsApplicationReimbursementRequestFailed.Wrapf( + "getting PNF/DAO address: %v", + err, + ) + } + + // Send the global per claim mint inflation uPOKT from the application module + // account to the tokenomics module account as an intermediary step. + if err := k.bankKeeper.SendCoinsFromModuleToModule( + ctx, apptypes.ModuleName, tokenomicstypes.ModuleName, globalInflationMintedCoinsForClaim, + ); err != nil { + return tokenomicstypes.ErrTokenomicsApplicationReimbursementRequestFailed.Wrapf( + "sending %s from the application module account to the tokenomics module account: %v", + newMintCoin, err, + ) + } + logger.Info(fmt.Sprintf( + "sent (%s) from the application module account to the tokenomics module account", + newMintCoin, + )) + + // Send the global per claim mint inflation uPOKT from the tokenomics module + // for second order economic effects. + // See: https://discord.com/channels/824324475256438814/997192534168182905/1299372745632649408 + if err := k.bankKeeper.SendCoinsFromModuleToAccount( + ctx, tokenomicstypes.ModuleName, daoAccountAddr, globalInflationMintedCoinsForClaim, + ); err != nil { + return tokenomicstypes.ErrTokenomicsApplicationReimbursementRequestFailed.Wrapf( + "sending %s from the tokenomics module account to the PNF/DAO account: %v", + newMintCoin, err, + ) + } + + // Prepare and emit the event for the application that'll required reimbursement. + // Recall that it is being overcharged to compoensate for global inflation while + // preventing self-dealing attacks. + reimbursementRequestEvent := &tokenomicstypes.EventApplicationReimbursementRequest{ + ApplicationAddr: application.Address, + SupplierOperatorAddr: supplier.OperatorAddress, + SupplierOwnerAddr: supplier.OwnerAddress, + ServiceId: service.Id, + SessionId: sessionHeader.SessionId, + Amount: &newMintCoin, + } + + eventManger := cosmostypes.UnwrapSDKContext(ctx).EventManager() + if err := eventManger.EmitTypedEvent(reimbursementRequestEvent); err != nil { + err = tokenomicstypes.ErrTokenomicsEmittingEventFailed.Wrapf( + "(%+v): %s", + reimbursementRequestEvent, err, + ) + + logger.Error(err.Error()) + return err + } + + return nil +} + func (k Keeper) ensureMintedCoinsAreDistributed( logger log.Logger, appCoin, supplierCoin, daoCoin, serviceCoin, proposerCoin, newMintCoin cosmostypes.Coin, @@ -560,41 +676,76 @@ func (k Keeper) ensureClaimAmountLimits( application *apptypes.Application, supplier *sharedtypes.Supplier, claimSettlementCoin cosmostypes.Coin, + initialApplicationStake cosmostypes.Coin, ) ( actualSettlementCoins cosmostypes.Coin, err error, ) { logger = logger.With("helper", "ensureClaimAmountLimits") - // TODO_BETA(@red-0ne): The application stake gets reduced with every claim - // settlement. Relay miners use the appStake at the beginning of a session to determine - // the maximum amount they can claim. We need to somehow access and propagate this - // value (via context?) so it is the same for all TLM processors for each claim. - // Note that this will also need to incorporate MintPerClaimGlobalInflation because - // applications are being overcharged by that amount in the meantime. Whatever the - // solution and implementation ends up being, make sure to KISS. - appStake := application.GetStake() - - // Determine the max claimable amount for the supplier based on the application's stake in this session. - maxClaimableCoin := sdk.NewCoin(volatile.DenomuPOKT, appStake.Amount.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession))) - - if maxClaimableCoin.Amount.GTE(claimSettlementCoin.Amount) { + // TODO_BETA(@red-0ne): Make relay miners use the appStake at the beginning + // of a session to determine the maximum amount they can claim. + // Note that this also incorporates MintPerClaimGlobalInflation since applications + // are being overcharged by that amount and the funds are sent to the DAO/PNF + // before being reimbursed to the application in the future. + appStake := initialApplicationStake + + // The application should have enough stake to cover for the global mint reimbursement. + // This amount is deducted from the maximum claimable amount. + globalInflationCoin, _ := CalculateGlobalPerClaimMintInflationFromSettlementAmount(claimSettlementCoin) + globalInflationAmt := globalInflationCoin.Amount + minRequiredAppStakeAmt := claimSettlementCoin.Amount.Add(globalInflationAmt) + totalClaimedCoin := sdk.NewCoin(volatile.DenomuPOKT, minRequiredAppStakeAmt) + + // TODO_BETA(@red-0ne): Introduce a session sliding window to account for potential consumption + // during the current session (i.e. Not the session being settled) such as: + // maxClaimableAmt = (AppStake / (currSessNum - settlingSessNum + 1) / NumSuppliersPerSession) + // In conjunction with single service applications, this would make maxClaimableAmt + // effectively addressing the issue of over-servicing. + // Example: + // - Current session num: 3 + // - Settling session num: 2 + // - Application already requested work for session 3 + // Problem: + // - If the application consumes its entire stake in settlement of session 2 + // - Then over-servicing in session 3 (i.e. No stake left to consume) + // Solution: + // - By dividing the claimable stake by 2 (3 - 2 + 1), settling session 2 assumes that + // the application will consume its maxClaimableAmt the current session (3). + // - Off-chain actors could use this formula during the servicing of session num 3 + // and assume maxClaimableAmt will be settled in session 2. + // - Guarantee no over-servicing at the cost of higher application stake requirements. + maxClaimableAmt := appStake.Amount.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession)) + maxClaimSettlementAmt := supplierAppStakeToMaxSettlementAmount(maxClaimableAmt) + + // Check if the claimable amount is capped by the max claimable amount. + // As per the Relay Mining paper, the Supplier claim MUST NOT exceed the application's + // allocated stake. If it does, the claim is capped by the application's allocated stake + // and the supplier is effectively "overserviced". + if minRequiredAppStakeAmt.GT(maxClaimableAmt) { + logger.Warn(fmt.Sprintf("Claim by supplier %s EXCEEDS LIMITS for application %s. Max claimable amount < Claim amount: %v < %v", + supplier.GetOperatorAddress(), application.GetAddress(), maxClaimableAmt, claimSettlementCoin.Amount)) + + minRequiredAppStakeAmt = maxClaimableAmt + maxClaimSettlementAmt = supplierAppStakeToMaxSettlementAmount(minRequiredAppStakeAmt) + } + + // Nominal case: The claimable amount is within the limits set by Relay Mining. + if claimSettlementCoin.Amount.LTE(maxClaimSettlementAmt) { logger.Info(fmt.Sprintf("Claim by supplier %s IS WITHIN LIMITS of servicing application %s. Max claimable amount >= Claim amount: %v >= %v", - supplier.GetOperatorAddress(), application.GetAddress(), maxClaimableCoin, claimSettlementCoin.Amount)) + supplier.GetOperatorAddress(), application.GetAddress(), maxClaimSettlementAmt, claimSettlementCoin.Amount)) return claimSettlementCoin, nil } - logger.Warn(fmt.Sprintf("Claim by supplier %s EXCEEDS LIMITS for application %s. Max claimable amount < Claim amount: %v < %v", - supplier.GetOperatorAddress(), application.GetAddress(), maxClaimableCoin, claimSettlementCoin.Amount)) - - // Reduce the settlement amount if the application was over-serviced - actualSettlementCoins = maxClaimableCoin + // Claimable amount is capped by the max claimable amount or the application allocated stake. + // Determine the max claimable amount for the supplier based on the application's stake in this session. + maxClaimableCoin := sdk.NewCoin(volatile.DenomuPOKT, maxClaimSettlementAmt) // Prepare and emit the event for the application being overserviced applicationOverservicedEvent := &tokenomicstypes.EventApplicationOverserviced{ - ApplicationAddr: application.Address, + ApplicationAddr: application.GetAddress(), SupplierOperatorAddr: supplier.GetOperatorAddress(), - ExpectedBurn: &claimSettlementCoin, + ExpectedBurn: &totalClaimedCoin, EffectiveBurn: &maxClaimableCoin, } eventManager := cosmostypes.UnwrapSDKContext(ctx).EventManager() @@ -603,7 +754,7 @@ func (k Keeper) ensureClaimAmountLimits( tokenomicstypes.ErrTokenomicsEmittingEventFailed.Wrapf("error emitting event %v", applicationOverservicedEvent) } - return actualSettlementCoins, nil + return maxClaimableCoin, nil } // distributeSupplierRewardsToShareHolders distributes the supplier rewards to its @@ -662,14 +813,15 @@ func (k Keeper) distributeSupplierRewardsToShareHolders( return nil } -// calculateGlobalPerClaimMintInflationFromSettlementAmount calculates the amount +// CalculateGlobalPerClaimMintInflationFromSettlementAmount calculates the amount // of uPOKT to mint based on the global per claim inflation rate as a function of // the settlement amount for a particular claim(s) or session(s). -func calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin sdk.Coin) (sdk.Coin, big.Float) { +// DEV_NOTE: This function is publically exposed to be used in the tests. +func CalculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin sdk.Coin) (sdk.Coin, big.Float) { // Determine how much new uPOKT to mint based on global per claim inflation. // TODO_MAINNET(@red-0ne): Consider using fixed point arithmetic for deterministic results. settlementAmtFloat := new(big.Float).SetUint64(settlementCoin.Amount.Uint64()) - newMintAmtFloat := new(big.Float).Mul(settlementAmtFloat, big.NewFloat(MintPerClaimedTokenGlobalInflation)) + newMintAmtFloat := new(big.Float).Mul(settlementAmtFloat, big.NewFloat(GlobalInflationPerClaim)) // DEV_NOTE: If new mint is less than 1 and more than 0, ceil it to 1 so that // we never expect to process a claim with 0 minted tokens. if newMintAmtFloat.Cmp(big.NewFloat(1)) < 0 && newMintAmtFloat.Cmp(big.NewFloat(0)) > 0 { @@ -680,6 +832,22 @@ func calculateGlobalPerClaimMintInflationFromSettlementAmount(settlementCoin sdk return mintAmtCoin, *newMintAmtFloat } +// supplierAppStakeToMaxSettlementAmount calculates the max amount of uPOKT the supplier +// can claim based on the stake allocated to the supplier and the global inflation +// allocation percentage. +// This is the inverse of CalculateGlobalPerClaimMintInflationFromSettlementAmount: +// stake = maxSettlementAmt + globalInflationAmt +// stake = maxSettlementAmt + (maxSettlementAmt * MintPerClaimedTokenGlobalInflation) +// stake = maxSettlementAmt * (1 + MintPerClaimedTokenGlobalInflation) +// maxSettlementAmt = stake / (1 + MintPerClaimedTokenGlobalInflation) +func supplierAppStakeToMaxSettlementAmount(stakeAmount math.Int) math.Int { + stakeAmountFloat := big.NewFloat(0).SetInt(stakeAmount.BigInt()) + maxSettlementAmountFloat := big.NewFloat(0).Quo(stakeAmountFloat, big.NewFloat(1+GlobalInflationPerClaim)) + + settlementAmount, _ := maxSettlementAmountFloat.Int(nil) + return math.NewIntFromBigInt(settlementAmount) +} + // calculateAllocationAmount does big float arithmetic to determine the absolute // amount from amountFloat based on the allocation percentage provided. // TODO_MAINNET(@red-0ne): Measure and limit the precision loss here. diff --git a/x/tokenomics/keeper/token_logic_modules_test.go b/x/tokenomics/keeper/token_logic_modules_test.go index 34267c9d9..db5aa8320 100644 --- a/x/tokenomics/keeper/token_logic_modules_test.go +++ b/x/tokenomics/keeper/token_logic_modules_test.go @@ -4,9 +4,10 @@ import ( "bytes" "context" "fmt" + "math" "testing" - "cosmossdk.io/math" + cosmosmath "cosmossdk.io/math" cosmostypes "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -42,8 +43,8 @@ func init() { func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid(t *testing.T) { // Test Parameters - appInitialStake := apptypes.DefaultMinStake.Amount.Mul(math.NewInt(2)) - supplierInitialStake := math.NewInt(1000000) + appInitialStake := apptypes.DefaultMinStake.Amount.Mul(cosmosmath.NewInt(2)) + supplierInitialStake := cosmosmath.NewInt(1000000) supplierRevShareRatios := []float32{12.5, 37.5, 50} globalComputeUnitsToTokensMultiplier := uint64(1) serviceComputeUnitsPerRelay := uint64(1) @@ -56,7 +57,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid(t *testing.T) { // Ensure the claim is within relay mining bounds numTokensClaimed := int64(numRelays * serviceComputeUnitsPerRelay * globalComputeUnitsToTokensMultiplier) - maxClaimableAmountPerSupplier := appInitialStake.Quo(math.NewInt(sessionkeeper.NumSupplierPerSession)) + maxClaimableAmountPerSupplier := appInitialStake.Quo(cosmosmath.NewInt(sessionkeeper.NumSupplierPerSession)) require.GreaterOrEqual(t, maxClaimableAmountPerSupplier.Int64(), numTokensClaimed) // Retrieve the app and supplier module addresses @@ -70,10 +71,10 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid(t *testing.T) { require.NoError(t, err) // TODO_TECHDEBT: Setting inflation to zero so we are testing the BurnEqualsMint logic exclusively. // Once it is a governance param, update it using the keeper above. - prevInflationValue := tokenomicskeeper.MintPerClaimedTokenGlobalInflation - tokenomicskeeper.MintPerClaimedTokenGlobalInflation = 0 + prevInflationValue := tokenomicskeeper.GlobalInflationPerClaim + tokenomicskeeper.GlobalInflationPerClaim = 0 t.Cleanup(func() { - tokenomicskeeper.MintPerClaimedTokenGlobalInflation = prevInflationValue + tokenomicskeeper.GlobalInflationPerClaim = prevInflationValue }) // Add a new application with non-zero app stake end balance to assert against. @@ -118,7 +119,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid(t *testing.T) { claim := prepareTestClaim(numRelays, service, &app, &supplier) // Process the token logic modules - err = keepers.ProcessTokenLogicModules(ctx, &claim) + err = keepers.ProcessTokenLogicModules(ctx, &claim, appStake) require.NoError(t, err) // Assert that `applicationAddress` account balance is *unchanged* @@ -126,7 +127,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid(t *testing.T) { require.EqualValues(t, appStartBalance, appEndBalance) // Determine the expected app end stake amount and the expected app burn - appBurn := math.NewInt(numTokensClaimed) + appBurn := cosmosmath.NewInt(numTokensClaimed) expectedAppEndStakeAmount := appInitialStake.Sub(appBurn) // Assert that `applicationAddress` staked balance has decreased by the appropriate amount @@ -166,13 +167,13 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid(t *testing.T) { // DEV_NOTE: Most of the setup here is a copy-paste of TLMBurnEqualsMintValid // except that the application stake is calculated to explicitly be too low to // handle all the relays completed. -func TestProcessTokenLogicModules_TLMBurnEqualsMint_Invalid_SupplierExceedsMaxClaimableAmount(t *testing.T) { +func TestProcessTokenLogicModules_TLMBurnEqualsMint_Valid_SupplierExceedsMaxClaimableAmount(t *testing.T) { // Test Parameters globalComputeUnitsToTokensMultiplier := uint64(1) serviceComputeUnitsPerRelay := uint64(100) service := prepareTestService(serviceComputeUnitsPerRelay) numRelays := uint64(1000) // By a single supplier for application in this session - supplierInitialStake := math.NewInt(1000000) + supplierInitialStake := cosmosmath.NewInt(1000000) supplierRevShareRatios := []float32{12.5, 37.5, 50} // Prepare the keepers @@ -183,7 +184,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Invalid_SupplierExceedsMaxCl // Determine the max a supplier can claim maxClaimableAmountPerSupplier := int64(numRelays * serviceComputeUnitsPerRelay * globalComputeUnitsToTokensMultiplier) // Figure out what the app's initial stake should be to cover the max claimable amount - appInitialStake := math.NewInt(maxClaimableAmountPerSupplier*sessionkeeper.NumSupplierPerSession + 1) + appInitialStake := cosmosmath.NewInt(maxClaimableAmountPerSupplier*sessionkeeper.NumSupplierPerSession + 1) // Increase the number of relay such that the supplier did "free work" and would // be able to claim more than the max claimable amount. numRelays *= 5 @@ -200,10 +201,10 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Invalid_SupplierExceedsMaxCl require.NoError(t, err) // TODO_TECHDEBT: Setting inflation to zero so we are testing the BurnEqualsMint logic exclusively. // Once it is a governance param, update it using the keeper above. - prevInflationValue := tokenomicskeeper.MintPerClaimedTokenGlobalInflation - tokenomicskeeper.MintPerClaimedTokenGlobalInflation = 0 + prevInflationValue := tokenomicskeeper.GlobalInflationPerClaim + tokenomicskeeper.GlobalInflationPerClaim = 0 t.Cleanup(func() { - tokenomicskeeper.MintPerClaimedTokenGlobalInflation = prevInflationValue + tokenomicskeeper.GlobalInflationPerClaim = prevInflationValue }) // Add a new application with non-zero app stake end balance to assert against. @@ -248,7 +249,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Invalid_SupplierExceedsMaxCl claim := prepareTestClaim(numRelays, service, &app, &supplier) // Process the token logic modules - err = keepers.ProcessTokenLogicModules(ctx, &claim) + err = keepers.ProcessTokenLogicModules(ctx, &claim, appStake) require.NoError(t, err) // Assert that `applicationAddress` account balance is *unchanged* @@ -256,7 +257,7 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Invalid_SupplierExceedsMaxCl require.EqualValues(t, appStartBalance, appEndBalance) // Determine the expected app end stake amount and the expected app burn - appBurn := math.NewInt(maxClaimableAmountPerSupplier) + appBurn := cosmosmath.NewInt(maxClaimableAmountPerSupplier) appBurnCoin := sdk.NewCoin(volatile.DenomuPOKT, appBurn) expectedAppEndStakeAmount := appInitialStake.Sub(appBurn) @@ -313,8 +314,8 @@ func TestProcessTokenLogicModules_TLMBurnEqualsMint_Invalid_SupplierExceedsMaxCl func TestProcessTokenLogicModules_TLMGlobalMint_Valid_MintDistributionCorrect(t *testing.T) { // Test Parameters - appInitialStake := apptypes.DefaultMinStake.Amount.Mul(math.NewInt(2)) - supplierInitialStake := math.NewInt(1000000) + appInitialStake := apptypes.DefaultMinStake.Amount.Mul(cosmosmath.NewInt(2)) + supplierInitialStake := cosmosmath.NewInt(1000000) supplierRevShareRatios := []float32{12.5, 37.5, 50} globalComputeUnitsToTokensMultiplier := uint64(1) serviceComputeUnitsPerRelay := uint64(1) @@ -383,7 +384,7 @@ func TestProcessTokenLogicModules_TLMGlobalMint_Valid_MintDistributionCorrect(t } // Process the token logic modules - err = keepers.ProcessTokenLogicModules(ctx, &claim) + err = keepers.ProcessTokenLogicModules(ctx, &claim, appStake) require.NoError(t, err) // Determine balances after inflation @@ -398,15 +399,16 @@ func TestProcessTokenLogicModules_TLMGlobalMint_Valid_MintDistributionCorrect(t } // Compute mint per actor - numTokensMinted := numTokensClaimed * tokenomicskeeper.MintPerClaimedTokenGlobalInflation - daoMint := math.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationDAO)) - propMint := math.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationProposer)) - serviceOwnerMint := math.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationSourceOwner)) - appMint := math.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationApplication)) + numTokensMinted := numTokensClaimed * tokenomicskeeper.GlobalInflationPerClaim + numTokensMintedInt := cosmosmath.NewIntFromUint64(uint64(numTokensMinted)) + daoMint := cosmosmath.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationDAO)) + propMint := cosmosmath.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationProposer)) + serviceOwnerMint := cosmosmath.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationSourceOwner)) + appMint := cosmosmath.NewInt(int64(numTokensMinted * tokenomicskeeper.MintAllocationApplication)) supplierMint := float32(numTokensMinted * tokenomicskeeper.MintAllocationSupplier) // Ensure the balance was increase be the appropriate amount - require.Equal(t, daoBalanceBefore.Amount.Add(daoMint), daoBalanceAfter.Amount) + require.Equal(t, daoBalanceBefore.Amount.Add(daoMint).Add(numTokensMintedInt), daoBalanceAfter.Amount) require.Equal(t, propBalanceBefore.Amount.Add(propMint), propBalanceAfter.Amount) require.Equal(t, serviceOwnerBalanceBefore.Amount.Add(serviceOwnerMint), serviceOwnerBalanceAfter.Amount) require.Equal(t, appBalanceBefore.Amount.Add(appMint), appBalanceAfter.Amount) @@ -416,12 +418,19 @@ func TestProcessTokenLogicModules_TLMGlobalMint_Valid_MintDistributionCorrect(t balanceAfter := supplierShareholderBalancesAfter[addr].Amount.Int64() mintShare := int64(supplierMint * revShare.RevSharePercentage / 100) rewardShare := int64(float32(numTokensClaimed) * revShare.RevSharePercentage / 100) - balanceIncrease := math.NewInt(mintShare + rewardShare) + balanceIncrease := cosmosmath.NewInt(mintShare + rewardShare) expectedBalanceAfter := balanceBefore.Amount.Add(balanceIncrease).Int64() // TODO_MAINNET: Remove the InDelta check and use the exact amount once the floating point arithmetic is fixed acceptableRoundingDelta := tokenomicskeeper.MintDistributionAllowableTolerancePercent * float64(balanceAfter) require.InDelta(t, expectedBalanceAfter, balanceAfter, acceptableRoundingDelta) } + + foundApp, appFound := keepers.GetApplication(ctx, appAddress) + require.True(t, appFound) + + appStakeAfter := foundApp.GetStake().Amount + numTokensClaimedInt := cosmosmath.NewIntFromUint64(uint64(numTokensClaimed)) + require.Equal(t, appInitialStake.Sub(numTokensMintedInt).Sub(numTokensClaimedInt), appStakeAfter) } func TestProcessTokenLogicModules_AppNotFound(t *testing.T) { @@ -443,7 +452,7 @@ func TestProcessTokenLogicModules_AppNotFound(t *testing.T) { } // Process the token logic modules - err := keeper.ProcessTokenLogicModules(ctx, &claim) + err := keeper.ProcessTokenLogicModules(ctx, &claim, uPOKTCoin(math.MaxInt)) require.Error(t, err) require.ErrorIs(t, err, tokenomicstypes.ErrTokenomicsApplicationNotFound) } @@ -466,7 +475,7 @@ func TestProcessTokenLogicModules_ServiceNotFound(t *testing.T) { } // Execute test function - err := keeper.ProcessTokenLogicModules(ctx, &claim) + err := keeper.ProcessTokenLogicModules(ctx, &claim, uPOKTCoin(math.MaxInt)) require.Error(t, err) require.ErrorIs(t, err, tokenomicstypes.ErrTokenomicsServiceNotFound) @@ -536,7 +545,7 @@ func TestProcessTokenLogicModules_InvalidRoot(t *testing.T) { claim.RootHash = smt.MerkleRoot(test.root[:]) // Execute test function - err := keeper.ProcessTokenLogicModules(ctx, &claim) + err := keeper.ProcessTokenLogicModules(ctx, &claim, uPOKTCoin(math.MaxInt)) // Assert the error if test.errExpected { @@ -626,7 +635,7 @@ func TestProcessTokenLogicModules_InvalidClaim(t *testing.T) { err = fmt.Errorf("panic occurred: %v", r) } }() - return keeper.ProcessTokenLogicModules(ctx, test.claim) + return keeper.ProcessTokenLogicModules(ctx, test.claim, uPOKTCoin(math.MaxInt)) }() // Assert the error @@ -640,6 +649,18 @@ func TestProcessTokenLogicModules_InvalidClaim(t *testing.T) { } } +func TestProcessTokenLogicModules_AppStakeInsufficientToCoverGlobalInflationAmount(t *testing.T) { + t.Skip("TODO_MAINNET(@red-0ne): Test application stake that is insufficient to cover the global inflation amount, for reimbursment and the max claim should scale down proportionally") +} + +func TestProcessTokenLogicModules_AppStakeTooLowRoundingToZero(t *testing.T) { + t.Skip("TODO_MAINNET(@red-0ne): Test application stake that is too low which results in stake/num_suppliers rounding down to zero") +} + +func TestProcessTokenLogicModules_AppStakeDropsBelowMinStakeAfterSession(t *testing.T) { + t.Skip("TODO_MAINNET(@red-0ne): Test that application stake being auto-unbonding after the stake drops below the required minimum when settling session accounting") +} + // prepareTestClaim uses the given number of relays and compute unit per relay in the // service provided to set up the test claim correctly. func prepareTestClaim( diff --git a/x/tokenomics/types/errors.go b/x/tokenomics/types/errors.go index 2d80c19ea..ce1e4595b 100644 --- a/x/tokenomics/types/errors.go +++ b/x/tokenomics/types/errors.go @@ -36,4 +36,5 @@ var ( ErrTokenomicsMintAmountZero = sdkerrors.Register(ModuleName, 1127, "mint amount cannot be zero") ErrTokenomicsTLMError = sdkerrors.Register(ModuleName, 1128, "failed to process TLM") ErrTokenomicsCalculation = sdkerrors.Register(ModuleName, 1129, "tokenomics calculation error") + ErrTokenomicsApplicationModuleSendFailed = sdkerrors.Register(ModuleName, 1130, "failed to send uPOKT from application module account") ) diff --git a/x/tokenomics/types/event.pb.go b/x/tokenomics/types/event.pb.go index 6f4278908..8570fd911 100644 --- a/x/tokenomics/types/event.pb.go +++ b/x/tokenomics/types/event.pb.go @@ -369,65 +369,153 @@ func (m *EventSupplierSlashed) GetSlashingAmount() *types1.Coin { return nil } +// EventApplicationReimbursementRequest is emitted when an application requests +// a reimbursement +type EventApplicationReimbursementRequest struct { + ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` + SupplierOperatorAddr string `protobuf:"bytes,2,opt,name=supplier_operator_addr,json=supplierOperatorAddr,proto3" json:"supplier_operator_addr,omitempty"` + SupplierOwnerAddr string `protobuf:"bytes,3,opt,name=supplier_owner_addr,json=supplierOwnerAddr,proto3" json:"supplier_owner_addr,omitempty"` + ServiceId string `protobuf:"bytes,4,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` + SessionId string `protobuf:"bytes,5,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + Amount *types1.Coin `protobuf:"bytes,6,opt,name=amount,proto3" json:"amount,omitempty"` +} + +func (m *EventApplicationReimbursementRequest) Reset() { *m = EventApplicationReimbursementRequest{} } +func (m *EventApplicationReimbursementRequest) String() string { return proto.CompactTextString(m) } +func (*EventApplicationReimbursementRequest) ProtoMessage() {} +func (*EventApplicationReimbursementRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_a78874bbf91a58c7, []int{4} +} +func (m *EventApplicationReimbursementRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventApplicationReimbursementRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil +} +func (m *EventApplicationReimbursementRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventApplicationReimbursementRequest.Merge(m, src) +} +func (m *EventApplicationReimbursementRequest) XXX_Size() int { + return m.Size() +} +func (m *EventApplicationReimbursementRequest) XXX_DiscardUnknown() { + xxx_messageInfo_EventApplicationReimbursementRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_EventApplicationReimbursementRequest proto.InternalMessageInfo + +func (m *EventApplicationReimbursementRequest) GetApplicationAddr() string { + if m != nil { + return m.ApplicationAddr + } + return "" +} + +func (m *EventApplicationReimbursementRequest) GetSupplierOperatorAddr() string { + if m != nil { + return m.SupplierOperatorAddr + } + return "" +} + +func (m *EventApplicationReimbursementRequest) GetSupplierOwnerAddr() string { + if m != nil { + return m.SupplierOwnerAddr + } + return "" +} + +func (m *EventApplicationReimbursementRequest) GetServiceId() string { + if m != nil { + return m.ServiceId + } + return "" +} + +func (m *EventApplicationReimbursementRequest) GetSessionId() string { + if m != nil { + return m.SessionId + } + return "" +} + +func (m *EventApplicationReimbursementRequest) GetAmount() *types1.Coin { + if m != nil { + return m.Amount + } + return nil +} + func init() { proto.RegisterEnum("poktroll.tokenomics.ClaimExpirationReason", ClaimExpirationReason_name, ClaimExpirationReason_value) proto.RegisterType((*EventClaimExpired)(nil), "poktroll.tokenomics.EventClaimExpired") proto.RegisterType((*EventClaimSettled)(nil), "poktroll.tokenomics.EventClaimSettled") proto.RegisterType((*EventApplicationOverserviced)(nil), "poktroll.tokenomics.EventApplicationOverserviced") proto.RegisterType((*EventSupplierSlashed)(nil), "poktroll.tokenomics.EventSupplierSlashed") + proto.RegisterType((*EventApplicationReimbursementRequest)(nil), "poktroll.tokenomics.EventApplicationReimbursementRequest") } func init() { proto.RegisterFile("poktroll/tokenomics/event.proto", fileDescriptor_a78874bbf91a58c7) } var fileDescriptor_a78874bbf91a58c7 = []byte{ - // 739 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x55, 0x4d, 0x53, 0xdb, 0x3a, - 0x14, 0x8d, 0x43, 0x60, 0x06, 0x3d, 0x12, 0x12, 0x3f, 0x60, 0x02, 0xef, 0x61, 0xf3, 0x58, 0xbc, - 0xa1, 0x4c, 0xb1, 0x07, 0xe8, 0x74, 0xd9, 0x69, 0x12, 0x42, 0xc7, 0x33, 0x6d, 0x12, 0x94, 0xd2, - 0x61, 0xba, 0xa8, 0xeb, 0xd8, 0x22, 0xb8, 0xc4, 0x92, 0x2b, 0xc9, 0x29, 0x2c, 0xfb, 0x0f, 0xfa, - 0x8b, 0xba, 0xee, 0x92, 0x25, 0xab, 0x4c, 0x27, 0xec, 0xb2, 0xed, 0xa2, 0xdb, 0x8e, 0xe4, 0x7c, - 0xf1, 0xd1, 0xb0, 0x60, 0xdb, 0x4d, 0x22, 0xdd, 0x7b, 0xce, 0x91, 0x74, 0xcf, 0xb5, 0x04, 0xf4, - 0x90, 0x9c, 0x72, 0x4a, 0x5a, 0x2d, 0x93, 0x93, 0x53, 0x84, 0x49, 0xe0, 0xbb, 0xcc, 0x44, 0x6d, - 0x84, 0xb9, 0x11, 0x52, 0xc2, 0x89, 0xfa, 0xf7, 0x00, 0x60, 0x8c, 0x00, 0x2b, 0x9a, 0x4b, 0x58, - 0x40, 0x98, 0xd9, 0x70, 0x18, 0x32, 0xdb, 0xdb, 0x0d, 0xc4, 0x9d, 0x6d, 0xd3, 0x25, 0x3e, 0x8e, - 0x49, 0x2b, 0x0b, 0x4d, 0xd2, 0x24, 0x72, 0x68, 0x8a, 0x51, 0x3f, 0xba, 0x32, 0x5c, 0x2b, 0xa4, - 0x84, 0x1c, 0x9b, 0xfc, 0x3c, 0x44, 0x2c, 0xce, 0xad, 0xff, 0x9c, 0x02, 0xb9, 0xb2, 0x58, 0xb6, - 0xd4, 0x72, 0xfc, 0xa0, 0x7c, 0x16, 0xfa, 0x14, 0x79, 0xea, 0x53, 0x30, 0xed, 0x8a, 0x79, 0x5e, - 0x59, 0x53, 0x36, 0xfe, 0xda, 0x59, 0x34, 0x86, 0x9b, 0x91, 0x0a, 0x86, 0x04, 0x17, 0x67, 0x7b, - 0x1d, 0x3d, 0xc6, 0xc1, 0xf8, 0x4f, 0xc5, 0x20, 0x87, 0x84, 0x84, 0xc3, 0x7d, 0x82, 0x6d, 0x8a, - 0x1c, 0x46, 0x70, 0x3e, 0xb9, 0xa6, 0x6c, 0x64, 0x76, 0x36, 0x8d, 0x3b, 0x0e, 0x64, 0x8c, 0x56, - 0x95, 0x14, 0x28, 0x19, 0xc5, 0xc5, 0x5e, 0x47, 0xbf, 0x2d, 0x04, 0xb3, 0xe8, 0x06, 0x50, 0xdd, - 0x02, 0x00, 0x47, 0x81, 0x4d, 0x51, 0xcb, 0x39, 0x67, 0xf9, 0xa9, 0x35, 0x65, 0x23, 0x55, 0xcc, - 0xf4, 0x3a, 0xfa, 0x58, 0x14, 0xce, 0xe2, 0x28, 0x80, 0x72, 0xa8, 0x1e, 0x81, 0x65, 0x91, 0x90, - 0x7b, 0x45, 0x9e, 0xed, 0x92, 0x20, 0x8c, 0x38, 0xb2, 0x23, 0xec, 0x73, 0x96, 0x4f, 0x49, 0xf6, - 0x6a, 0xaf, 0xa3, 0xff, 0x1e, 0x04, 0x97, 0x70, 0x14, 0x94, 0xe2, 0x4c, 0x29, 0x4e, 0x1c, 0x8a, - 0xb8, 0xfa, 0x0e, 0xfc, 0x23, 0x48, 0x88, 0x71, 0x3f, 0x70, 0xf8, 0x2d, 0xed, 0x69, 0xa9, 0xad, - 0xf7, 0x3a, 0xfa, 0x24, 0x18, 0xcc, 0xe3, 0x28, 0x28, 0x0f, 0x72, 0xd7, 0xf4, 0x0f, 0x40, 0x7a, - 0xb0, 0xa1, 0x48, 0xd4, 0x31, 0x3f, 0x23, 0x8d, 0x59, 0x36, 0xe2, 0x86, 0x30, 0x44, 0x43, 0x18, - 0xfd, 0x86, 0x30, 0x4a, 0xc4, 0xc7, 0xc5, 0x5c, 0xaf, 0xa3, 0x5f, 0xe7, 0xc0, 0xb9, 0xfe, 0xf4, - 0x50, 0xcc, 0xd6, 0x7f, 0x5c, 0x73, 0xbe, 0x8e, 0x38, 0x6f, 0x3d, 0xc0, 0xf9, 0x0f, 0x20, 0x27, - 0x01, 0x36, 0x45, 0x1f, 0x23, 0x9f, 0xa2, 0x00, 0x61, 0xde, 0x77, 0xfe, 0xff, 0x9b, 0x1a, 0x35, - 0xf1, 0x0b, 0x47, 0xb8, 0x71, 0xd7, 0x6f, 0x89, 0xc0, 0x6c, 0x78, 0x03, 0xfe, 0xc7, 0xf5, 0x07, - 0xb8, 0xfe, 0x39, 0x09, 0xfe, 0x95, 0xae, 0x17, 0xc2, 0xb0, 0xe5, 0xbb, 0xf2, 0x63, 0xaa, 0xb6, - 0x11, 0x65, 0x88, 0xb6, 0x7d, 0x17, 0x79, 0xea, 0x23, 0x90, 0x75, 0x46, 0x29, 0xdb, 0xf1, 0x3c, - 0x2a, 0x7b, 0x61, 0x16, 0xce, 0x8f, 0xc5, 0x0b, 0x9e, 0x47, 0xd5, 0x27, 0x60, 0x89, 0x45, 0x22, - 0x86, 0xa8, 0x4d, 0x42, 0x44, 0x1d, 0x4e, 0x68, 0x4c, 0x48, 0x4a, 0xc2, 0xc2, 0x20, 0x5b, 0xed, - 0x27, 0x25, 0xeb, 0x19, 0x48, 0xa3, 0xb3, 0x10, 0xb9, 0xa2, 0x10, 0x8d, 0x88, 0x62, 0x69, 0xe0, - 0xa4, 0x43, 0xc1, 0xb9, 0x01, 0xbe, 0x18, 0x51, 0xac, 0x3e, 0x07, 0x19, 0x74, 0x7c, 0x8c, 0x5c, - 0xee, 0xb7, 0x51, 0x2c, 0x90, 0xba, 0x4f, 0x20, 0x3d, 0x24, 0x08, 0x85, 0xf5, 0xaf, 0x0a, 0x58, - 0x90, 0x35, 0xa8, 0xf7, 0xf7, 0x57, 0x6f, 0x39, 0xec, 0x04, 0x79, 0x13, 0x0e, 0xa4, 0x4c, 0x38, - 0xd0, 0x63, 0xa0, 0x4a, 0x7b, 0xe3, 0xbb, 0x33, 0x6e, 0x21, 0x26, 0x4b, 0x90, 0x82, 0x59, 0xe1, - 0x6d, 0x9c, 0x90, 0x0d, 0xc4, 0xd4, 0x22, 0x98, 0x67, 0x62, 0x39, 0x1f, 0x37, 0x6d, 0x27, 0x20, - 0x11, 0xe6, 0xf7, 0x17, 0x20, 0x33, 0x60, 0x14, 0x24, 0x61, 0xf3, 0x3d, 0x58, 0xbc, 0xf3, 0xe2, - 0x54, 0xff, 0x03, 0xab, 0xe5, 0xa3, 0x9a, 0x05, 0x0b, 0xaf, 0xad, 0x6a, 0xc5, 0x86, 0xe5, 0x42, - 0xbd, 0x5a, 0xb1, 0x0f, 0x2b, 0xf5, 0x5a, 0xb9, 0x64, 0xed, 0x5b, 0xe5, 0xbd, 0x6c, 0x42, 0xcd, - 0x81, 0x74, 0x0d, 0x56, 0xab, 0xfb, 0xf6, 0x2b, 0xab, 0x5e, 0xb7, 0x2a, 0x2f, 0xb2, 0xca, 0x28, - 0x64, 0x55, 0xde, 0x14, 0x5e, 0x5a, 0x7b, 0xd9, 0x64, 0xf1, 0xe0, 0x5b, 0x57, 0x53, 0x2e, 0xba, - 0x9a, 0x72, 0xd9, 0xd5, 0x94, 0xef, 0x5d, 0x4d, 0xf9, 0x72, 0xa5, 0x25, 0x2e, 0xae, 0xb4, 0xc4, - 0xe5, 0x95, 0x96, 0x78, 0xbb, 0xdb, 0xf4, 0xf9, 0x49, 0xd4, 0x30, 0x5c, 0x12, 0x98, 0xa2, 0xab, - 0xb6, 0x30, 0xe2, 0x9f, 0x08, 0x3d, 0x35, 0x87, 0x0f, 0xcd, 0xd9, 0xf8, 0xb3, 0x26, 0xdf, 0x9b, - 0xc6, 0x8c, 0x7c, 0x70, 0x76, 0x7f, 0x05, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x71, 0x30, 0x08, 0xfa, - 0x06, 0x00, 0x00, + // 823 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x56, 0xcf, 0x6f, 0xdb, 0x36, + 0x14, 0x8e, 0x9c, 0x34, 0x80, 0xb9, 0xc6, 0xb5, 0xd5, 0xa4, 0x70, 0xb3, 0x45, 0xca, 0x8c, 0x61, + 0xc8, 0x8a, 0x55, 0x42, 0xda, 0x61, 0xc7, 0x61, 0xb6, 0xeb, 0x0e, 0x02, 0x36, 0xdb, 0xa5, 0x97, + 0xa1, 0xd8, 0x61, 0x9a, 0x2c, 0xbd, 0xb8, 0x5c, 0x2c, 0x52, 0x25, 0x29, 0x37, 0x3d, 0xee, 0x3f, + 0xd8, 0x9f, 0xb1, 0xbf, 0x62, 0xe7, 0x1d, 0x7b, 0xec, 0xc9, 0x18, 0x9c, 0x9b, 0xaf, 0x3b, 0xec, + 0x3a, 0x90, 0x92, 0x7f, 0xc4, 0xe9, 0x9c, 0x43, 0xb0, 0x5b, 0x2f, 0x36, 0xf9, 0xbe, 0xef, 0x7b, + 0x24, 0xdf, 0xf7, 0x68, 0x1a, 0xd9, 0x09, 0x3b, 0x93, 0x9c, 0x0d, 0x87, 0xae, 0x64, 0x67, 0x40, + 0x59, 0x4c, 0x42, 0xe1, 0xc2, 0x08, 0xa8, 0x74, 0x12, 0xce, 0x24, 0x33, 0xef, 0xce, 0x08, 0xce, + 0x82, 0xb0, 0x6f, 0x85, 0x4c, 0xc4, 0x4c, 0xb8, 0xfd, 0x40, 0x80, 0x3b, 0x3a, 0xee, 0x83, 0x0c, + 0x8e, 0xdd, 0x90, 0x11, 0x9a, 0x89, 0xf6, 0x77, 0x07, 0x6c, 0xc0, 0xf4, 0xd0, 0x55, 0xa3, 0x3c, + 0xba, 0x3f, 0x5f, 0x2b, 0xe1, 0x8c, 0x9d, 0xba, 0xf2, 0x75, 0x02, 0x22, 0xc3, 0x6a, 0xff, 0x6c, + 0xa2, 0x4a, 0x4b, 0x2d, 0xdb, 0x1c, 0x06, 0x24, 0x6e, 0x9d, 0x27, 0x84, 0x43, 0x64, 0x7e, 0x89, + 0x6e, 0x85, 0x6a, 0x5e, 0x35, 0x0e, 0x8d, 0xa3, 0x0f, 0x1e, 0xed, 0x39, 0xf3, 0xcd, 0xe8, 0x0c, + 0x8e, 0x26, 0x37, 0x8a, 0xd3, 0xb1, 0x9d, 0xf1, 0x70, 0xf6, 0x65, 0x52, 0x54, 0x01, 0x95, 0x22, + 0x90, 0x84, 0x51, 0x9f, 0x43, 0x20, 0x18, 0xad, 0x16, 0x0e, 0x8d, 0xa3, 0xd2, 0xa3, 0x07, 0xce, + 0x3b, 0x0e, 0xe4, 0x2c, 0x56, 0xd5, 0x12, 0xac, 0x15, 0x8d, 0xbd, 0xe9, 0xd8, 0xbe, 0x9a, 0x08, + 0x97, 0x61, 0x85, 0x68, 0x3e, 0x44, 0x88, 0xa6, 0xb1, 0xcf, 0x61, 0x18, 0xbc, 0x16, 0xd5, 0xcd, + 0x43, 0xe3, 0x68, 0xab, 0x51, 0x9a, 0x8e, 0xed, 0xa5, 0x28, 0x2e, 0xd2, 0x34, 0xc6, 0x7a, 0x68, + 0x3e, 0x47, 0xf7, 0x15, 0xa0, 0xf7, 0x0a, 0x91, 0x1f, 0xb2, 0x38, 0x49, 0x25, 0xf8, 0x29, 0x25, + 0x52, 0x54, 0xb7, 0xb4, 0xfa, 0x60, 0x3a, 0xb6, 0xff, 0x9b, 0x84, 0xef, 0xd1, 0x34, 0x6e, 0x66, + 0x48, 0x33, 0x03, 0x4e, 0x54, 0xdc, 0xfc, 0x09, 0x7d, 0xa8, 0x44, 0x20, 0x24, 0x89, 0x03, 0x79, + 0x25, 0xf7, 0x2d, 0x9d, 0xdb, 0x9e, 0x8e, 0xed, 0x75, 0x34, 0x5c, 0xa5, 0x69, 0xdc, 0x9a, 0x61, + 0x97, 0xf2, 0x3f, 0x43, 0x3b, 0xb3, 0x0d, 0xa5, 0xaa, 0x8e, 0xd5, 0x6d, 0x6d, 0xcc, 0x7d, 0x27, + 0x6b, 0x08, 0x47, 0x35, 0x84, 0x93, 0x37, 0x84, 0xd3, 0x64, 0x84, 0x36, 0x2a, 0xd3, 0xb1, 0x7d, + 0x59, 0x83, 0x6f, 0xe7, 0xd3, 0x13, 0x35, 0xab, 0xfd, 0x7d, 0xc9, 0xf9, 0x1e, 0x48, 0x39, 0xbc, + 0x81, 0xf3, 0xbf, 0xa0, 0x8a, 0x26, 0xf8, 0x1c, 0x5e, 0xa6, 0x84, 0x43, 0x0c, 0x54, 0xe6, 0xce, + 0x7f, 0xba, 0x9a, 0xa3, 0xab, 0x3e, 0xf1, 0x82, 0xb7, 0xec, 0xfa, 0x95, 0x24, 0xb8, 0x9c, 0xac, + 0xd0, 0xdf, 0xbb, 0x7e, 0x03, 0xd7, 0x7f, 0x2d, 0xa0, 0x8f, 0xb4, 0xeb, 0xf5, 0x24, 0x19, 0x92, + 0x50, 0x5f, 0xa6, 0xce, 0x08, 0xb8, 0x00, 0x3e, 0x22, 0x21, 0x44, 0xe6, 0x67, 0xa8, 0x1c, 0x2c, + 0x20, 0x3f, 0x88, 0x22, 0xae, 0x7b, 0xa1, 0x88, 0xef, 0x2c, 0xc5, 0xeb, 0x51, 0xc4, 0xcd, 0x2f, + 0xd0, 0x3d, 0x91, 0xaa, 0x18, 0x70, 0x9f, 0x25, 0xc0, 0x03, 0xc9, 0x78, 0x26, 0x28, 0x68, 0xc1, + 0xee, 0x0c, 0xed, 0xe4, 0xa0, 0x56, 0x7d, 0x85, 0x76, 0xe0, 0x3c, 0x81, 0x50, 0x15, 0xa2, 0x9f, + 0x72, 0xaa, 0x0d, 0x5c, 0x77, 0x28, 0x7c, 0x7b, 0xc6, 0x6f, 0xa4, 0x9c, 0x9a, 0x5f, 0xa3, 0x12, + 0x9c, 0x9e, 0x42, 0x28, 0xc9, 0x08, 0xb2, 0x04, 0x5b, 0xd7, 0x25, 0xd8, 0x99, 0x0b, 0x54, 0x86, + 0xda, 0x1f, 0x06, 0xda, 0xd5, 0x35, 0xe8, 0xe5, 0xfb, 0xeb, 0x0d, 0x03, 0xf1, 0x02, 0xa2, 0x35, + 0x07, 0x32, 0xd6, 0x1c, 0xe8, 0x73, 0x64, 0x6a, 0x7b, 0xb3, 0xdf, 0xce, 0xac, 0x85, 0x84, 0x2e, + 0xc1, 0x16, 0x2e, 0x2b, 0x6f, 0x33, 0x40, 0x37, 0x90, 0x30, 0x1b, 0xe8, 0x8e, 0x50, 0xcb, 0x11, + 0x3a, 0xf0, 0x83, 0x98, 0xa5, 0x54, 0x5e, 0x5f, 0x80, 0xd2, 0x4c, 0x51, 0xd7, 0x82, 0xda, 0xef, + 0x05, 0xf4, 0xc9, 0xaa, 0x89, 0x18, 0x48, 0xdc, 0x4f, 0xb9, 0xc8, 0x6f, 0xd4, 0xcb, 0x14, 0x84, + 0xfc, 0xff, 0xcd, 0x74, 0xd0, 0xdd, 0x85, 0xea, 0x15, 0x85, 0x5c, 0xb2, 0xa9, 0x25, 0x95, 0xb9, + 0x44, 0x21, 0x9a, 0x7f, 0x80, 0x50, 0xde, 0x69, 0x3e, 0x89, 0xb4, 0x71, 0x45, 0x5c, 0xcc, 0x23, + 0x5e, 0x94, 0xc1, 0x42, 0xa8, 0xbd, 0x92, 0x48, 0xdf, 0x1f, 0x0d, 0xeb, 0x88, 0x17, 0x99, 0xc7, + 0x68, 0x3b, 0x2f, 0xd9, 0x75, 0x17, 0x01, 0xe7, 0xc4, 0x07, 0x3f, 0xa3, 0xbd, 0x77, 0xbe, 0x31, + 0xe6, 0xc7, 0xe8, 0xa0, 0xf5, 0xbc, 0xeb, 0xe1, 0xfa, 0xf7, 0x5e, 0xa7, 0xed, 0xe3, 0x56, 0xbd, + 0xd7, 0x69, 0xfb, 0x27, 0xed, 0x5e, 0xb7, 0xd5, 0xf4, 0x9e, 0x7a, 0xad, 0x27, 0xe5, 0x0d, 0xb3, + 0x82, 0x76, 0xba, 0xb8, 0xd3, 0x79, 0xea, 0x7f, 0xe7, 0xf5, 0x7a, 0x5e, 0xfb, 0x9b, 0xb2, 0xb1, + 0x08, 0x79, 0xed, 0x1f, 0xea, 0xdf, 0x7a, 0x4f, 0xca, 0x85, 0xc6, 0xb3, 0x3f, 0x27, 0x96, 0xf1, + 0x66, 0x62, 0x19, 0x6f, 0x27, 0x96, 0xf1, 0xd7, 0xc4, 0x32, 0x7e, 0xbb, 0xb0, 0x36, 0xde, 0x5c, + 0x58, 0x1b, 0x6f, 0x2f, 0xac, 0x8d, 0x1f, 0x1f, 0x0f, 0x88, 0x7c, 0x91, 0xf6, 0x9d, 0x90, 0xc5, + 0xae, 0xba, 0x80, 0x0f, 0x29, 0xc8, 0x57, 0x8c, 0x9f, 0xb9, 0xf3, 0x37, 0xf9, 0x7c, 0xf9, 0x1f, + 0x80, 0x7e, 0x9a, 0xfb, 0xdb, 0xfa, 0x6d, 0x7e, 0xfc, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8b, + 0xd5, 0xac, 0x44, 0x25, 0x08, 0x00, 0x00, } func (m *EventClaimExpired) Marshal() (dAtA []byte, err error) { @@ -672,6 +760,76 @@ func (m *EventSupplierSlashed) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *EventApplicationReimbursementRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *EventApplicationReimbursementRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventApplicationReimbursementRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Amount != nil { + { + size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvent(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + if len(m.SessionId) > 0 { + i -= len(m.SessionId) + copy(dAtA[i:], m.SessionId) + i = encodeVarintEvent(dAtA, i, uint64(len(m.SessionId))) + i-- + dAtA[i] = 0x2a + } + if len(m.ServiceId) > 0 { + i -= len(m.ServiceId) + copy(dAtA[i:], m.ServiceId) + i = encodeVarintEvent(dAtA, i, uint64(len(m.ServiceId))) + i-- + dAtA[i] = 0x22 + } + if len(m.SupplierOwnerAddr) > 0 { + i -= len(m.SupplierOwnerAddr) + copy(dAtA[i:], m.SupplierOwnerAddr) + i = encodeVarintEvent(dAtA, i, uint64(len(m.SupplierOwnerAddr))) + i-- + dAtA[i] = 0x1a + } + if len(m.SupplierOperatorAddr) > 0 { + i -= len(m.SupplierOperatorAddr) + copy(dAtA[i:], m.SupplierOperatorAddr) + i = encodeVarintEvent(dAtA, i, uint64(len(m.SupplierOperatorAddr))) + i-- + dAtA[i] = 0x12 + } + if len(m.ApplicationAddr) > 0 { + i -= len(m.ApplicationAddr) + copy(dAtA[i:], m.ApplicationAddr) + i = encodeVarintEvent(dAtA, i, uint64(len(m.ApplicationAddr))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintEvent(dAtA []byte, offset int, v uint64) int { offset -= sovEvent(v) base := offset @@ -786,6 +944,39 @@ func (m *EventSupplierSlashed) Size() (n int) { return n } +func (m *EventApplicationReimbursementRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ApplicationAddr) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } + l = len(m.SupplierOperatorAddr) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } + l = len(m.SupplierOwnerAddr) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } + l = len(m.ServiceId) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } + l = len(m.SessionId) + if l > 0 { + n += 1 + l + sovEvent(uint64(l)) + } + if m.Amount != nil { + l = m.Amount.Size() + n += 1 + l + sovEvent(uint64(l)) + } + return n +} + func sovEvent(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1511,6 +1702,252 @@ func (m *EventSupplierSlashed) Unmarshal(dAtA []byte) error { } return nil } +func (m *EventApplicationReimbursementRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: EventApplicationReimbursementRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventApplicationReimbursementRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ApplicationAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ApplicationAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SupplierOperatorAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SupplierOperatorAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SupplierOwnerAddr", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SupplierOwnerAddr = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ServiceId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ServiceId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SessionId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SessionId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvent + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvent + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvent + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Amount == nil { + m.Amount = &types1.Coin{} + } + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvent(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvent + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipEvent(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 From bae452a331b16ccd4b36b2b9bbefecc854276a5e Mon Sep 17 00:00:00 2001 From: "Dima K." Date: Wed, 30 Oct 2024 21:18:55 -0700 Subject: [PATCH 4/4] [Observability] Foundation for load testing telemetry (#832) ## Summary Refactor the foundation for E2E tokenomics observability w/ lots of new data points. Key changes include: - `x/tokenomics` telemetry - Begin/End blockers execution time management - Custom `poktroll` telemetry config in `app.toml` ## Issue - #762 --------- Co-authored-by: Daniel Olshansky --- Tiltfile | 29 +- api/poktroll/application/types.pulsar.go | 14 +- api/poktroll/tokenomics/event.pulsar.go | 2 +- app/app.go | 5 + cmd/poktrolld/cmd/config.go | 67 +- config.yml | 26 +- go.mod | 2 +- .../cosmos_sdk_insights.json | 1318 +++++++++++++++++ .../permissionless_demand_observability.json | 1314 ++++++++++++++++ .../grafana-dashboards/tokenomics_relays.json | 523 +++++++ .../observability-prometheus-stack.yaml | 23 +- localnet/poktrolld/config/app.toml | 7 +- ...appgate_server_config_localnet_vscode.yaml | 2 +- .../relayminer_config_localnet_vscode.yaml | 12 +- pkg/appgateserver/cmd/cmd.go | 5 +- pkg/relayer/cmd/cmd.go | 5 +- pkg/relayer/proxy/metrics.go | 4 +- pkg/relayer/proxy/synchronous.go | 7 +- telemetry/block.go | 8 + telemetry/common.go | 54 + telemetry/event_counters.go | 156 +- telemetry/telemetry.go | 31 + telemetry/tokens.go | 61 + x/application/module/abci.go | 5 + x/application/types/types.pb.go | 14 +- x/proof/keeper/msg_server_create_claim.go | 31 +- x/proof/keeper/msg_server_submit_proof.go | 45 +- x/proof/keeper/proof_validation.go | 5 + x/session/keeper/query_get_session.go | 2 +- x/session/keeper/session_hydrator.go | 13 +- x/supplier/module/abci.go | 5 + x/tokenomics/keeper/settle_pending_claims.go | 47 +- x/tokenomics/keeper/token_logic_modules.go | 26 +- x/tokenomics/module/abci.go | 42 +- x/tokenomics/types/event.pb.go | 2 +- 35 files changed, 3744 insertions(+), 168 deletions(-) create mode 100644 localnet/grafana-dashboards/cosmos_sdk_insights.json create mode 100644 localnet/grafana-dashboards/permissionless_demand_observability.json create mode 100644 localnet/grafana-dashboards/tokenomics_relays.json create mode 100644 telemetry/common.go create mode 100644 telemetry/telemetry.go create mode 100644 telemetry/tokens.go diff --git a/Tiltfile b/Tiltfile index cd9b4a177..bc0d78b92 100644 --- a/Tiltfile +++ b/Tiltfile @@ -6,7 +6,7 @@ load("ext://deployment", "deployment_create") load("ext://execute_in_pod", "execute_in_pod") # A list of directories where changes trigger a hot-reload of the validator -hot_reload_dirs = ["app", "cmd", "tools", "x", "pkg"] +hot_reload_dirs = ["app", "cmd", "tools", "x", "pkg", "telemetry"] def merge_dicts(base, updates): @@ -38,14 +38,26 @@ localnet_config_defaults = { "enabled": True, "grafana": {"defaultDashboardsEnabled": False}, }, - "relayminers": {"count": 1, "delve": {"enabled": False}}, + "relayminers": { + "count": 1, + "delve": {"enabled": False}, + "logs": { + "level": "debug", + }, + }, "gateways": { "count": 1, "delve": {"enabled": False}, + "logs": { + "level": "debug", + }, }, "appgateservers": { "count": 1, "delve": {"enabled": False}, + "logs": { + "level": "debug", + }, }, "ollama": { "enabled": False, @@ -100,8 +112,10 @@ if localnet_config["observability"]["enabled"]: helm_repo("prometheus-community", "https://prometheus-community.github.io/helm-charts") helm_repo("grafana-helm-repo", "https://grafana.github.io/helm-charts") - # Increase timeout for building the image - update_settings(k8s_upsert_timeout_secs=60) + # Timeout is increased to 120 seconds (default is 30) because a slow internet connection + # could timeout pulling the image. + # container images. + update_settings(k8s_upsert_timeout_secs=120) helm_resource( "observability", @@ -226,6 +240,7 @@ helm_resource( "--set=logs.format=" + str(localnet_config["validator"]["logs"]["format"]), "--set=serviceMonitor.enabled=" + str(localnet_config["observability"]["enabled"]), "--set=development.delve.enabled=" + str(localnet_config["validator"]["delve"]["enabled"]), + "--set=image.repository=poktrolld", ], image_deps=["poktrolld"], image_keys=[("image.repository", "image.tag")], @@ -244,6 +259,8 @@ for x in range(localnet_config["relayminers"]["count"]): "--values=./localnet/kubernetes/values-relayminer-" + str(actor_number) + ".yaml", "--set=metrics.serviceMonitor.enabled=" + str(localnet_config["observability"]["enabled"]), "--set=development.delve.enabled=" + str(localnet_config["relayminers"]["delve"]["enabled"]), + "--set=logLevel=" + str(localnet_config["relayminers"]["logs"]["level"]), + "--set=image.repository=poktrolld", ], image_deps=["poktrolld"], image_keys=[("image.repository", "image.tag")], @@ -284,6 +301,8 @@ for x in range(localnet_config["appgateservers"]["count"]): "--set=config.signing_key=app" + str(actor_number), "--set=metrics.serviceMonitor.enabled=" + str(localnet_config["observability"]["enabled"]), "--set=development.delve.enabled=" + str(localnet_config["appgateservers"]["delve"]["enabled"]), + "--set=logLevel=" + str(localnet_config["appgateservers"]["logs"]["level"]), + "--set=image.repository=poktrolld", ], image_deps=["poktrolld"], image_keys=[("image.repository", "image.tag")], @@ -325,6 +344,8 @@ for x in range(localnet_config["gateways"]["count"]): "--set=config.signing_key=gateway" + str(actor_number), "--set=metrics.serviceMonitor.enabled=" + str(localnet_config["observability"]["enabled"]), "--set=development.delve.enabled=" + str(localnet_config["gateways"]["delve"]["enabled"]), + "--set=logLevel=" + str(localnet_config["gateways"]["logs"]["level"]), + "--set=image.repository=poktrolld", ], image_deps=["poktrolld"], image_keys=[("image.repository", "image.tag")], diff --git a/api/poktroll/application/types.pulsar.go b/api/poktroll/application/types.pulsar.go index 4a7751438..d1f8f492f 100644 --- a/api/poktroll/application/types.pulsar.go +++ b/api/poktroll/application/types.pulsar.go @@ -2190,14 +2190,12 @@ type Application struct { Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` // The Bech32 address of the application. Stake *v1beta1.Coin `protobuf:"bytes,2,opt,name=stake,proto3" json:"stake,omitempty"` // The total amount of uPOKT the application has staked - // As per this discussion: - // https://github.com/pokt-network/poktroll/pull/750#discussion_r1735025033 - // The number of service_configs is limited to 1 per service. - // This is to ensure that an application could not over service by making multiple - // claims settelments compete to burn the same stake. - // A slice of service_configs is still maintained to allow for future multi-service - // capabilities to be added, such as off-chain application stake tracking by suppliers: - // https://www.notion.so/buildwithgrove/Off-chain-Application-Stake-Tracking-6a8bebb107db4f7f9dc62cbe7ba555f7 + // CRITICAL_DEV_NOTE: The number of service_configs must be EXACTLY ONE. + // This prevents applications from over-servicing. + // The field is kept repeated (a list) for both legacy and future logic reaosns. + // References: + // - https://github.com/pokt-network/poktroll/pull/750#discussion_r1735025033 + // - https://www.notion.so/buildwithgrove/Off-chain-Application-Stake-Tracking-6a8bebb107db4f7f9dc62cbe7ba555f7 ServiceConfigs []*shared.ApplicationServiceConfig `protobuf:"bytes,3,rep,name=service_configs,json=serviceConfigs,proto3" json:"service_configs,omitempty"` // The list of services this appliccation is configured to request service for // TODO_BETA: Rename `delegatee_gateway_addresses` to `gateway_addresses_delegated_to`. // Ensure to rename all relevant configs, comments, variables, function names, etc as well. diff --git a/api/poktroll/tokenomics/event.pulsar.go b/api/poktroll/tokenomics/event.pulsar.go index cf18db79d..4a8a3c0e5 100644 --- a/api/poktroll/tokenomics/event.pulsar.go +++ b/api/poktroll/tokenomics/event.pulsar.go @@ -3730,7 +3730,7 @@ func (x *EventSupplierSlashed) GetSlashingAmount() *v1beta1.Coin { } // EventApplicationReimbursementRequest is emitted when an application requests -// a reimbursement +// a reimbursement. type EventApplicationReimbursementRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache diff --git a/app/app.go b/app/app.go index 8384a82f4..b98b86b42 100644 --- a/app/app.go +++ b/app/app.go @@ -302,6 +302,11 @@ func New( return nil, err } + // Set up poktroll telemetry using `app.toml` configuration options (in addition to cosmos-sdk telemetry config). + if err := telemetry.New(appOpts); err != nil { + return nil, err + } + return app, nil } diff --git a/cmd/poktrolld/cmd/config.go b/cmd/poktrolld/cmd/config.go index 003c6a690..61a441fa7 100644 --- a/cmd/poktrolld/cmd/config.go +++ b/cmd/poktrolld/cmd/config.go @@ -9,10 +9,27 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/pokt-network/poktroll/app" + "github.com/pokt-network/poktroll/telemetry" ) var once sync.Once +// PoktrollAppConfig represents a poktroll-specific part of `app.toml` file. +// Checkout `customAppConfigTemplate()` for additional information about each setting. +type PoktrollAppConfig struct { + Telemetry telemetry.PoktrollTelemetryConfig `mapstructure:"telemetry"` +} + +// poktrollAppConfigDefaults sets default values to render in `app.toml`. +// Checkout `customAppConfigTemplate()` for additional information about each setting. +func poktrollAppConfigDefaults() PoktrollAppConfig { + return PoktrollAppConfig{ + Telemetry: telemetry.PoktrollTelemetryConfig{ + CardinalityLevel: "medium", + }, + } +} + func InitSDKConfig() { once.Do(func() { checkOrInitSDKConfig() @@ -90,6 +107,7 @@ func initAppConfig() (string, interface{}) { // The following code snippet is just for reference. type CustomAppConfig struct { serverconfig.Config `mapstructure:",squash"` + Poktroll PoktrollAppConfig `mapstructure:"poktroll"` } // Optionally allow the chain developer to overwrite the SDK's default @@ -113,7 +131,9 @@ func initAppConfig() (string, interface{}) { srvCfg.MinGasPrices = "0.000000001upokt" // Also adjust ignite's `config.yml`. srvCfg.Mempool.MaxTxs = 10000 srvCfg.Telemetry.Enabled = true - srvCfg.Telemetry.PrometheusRetentionTime = 60 // in seconds. This turns on Prometheus support. + // Positive non-zero value turns on Prometheus support. + // Prometheus metrics are removed from the exporter when retention time is reached. + srvCfg.Telemetry.PrometheusRetentionTime = 60 * 60 * 24 // in seconds. srvCfg.Telemetry.MetricsSink = "mem" srvCfg.Pruning = "nothing" // archiving node by default srvCfg.API.Enable = true @@ -121,19 +141,38 @@ func initAppConfig() (string, interface{}) { srvCfg.GRPCWeb.Enable = true customAppConfig := CustomAppConfig{ - Config: *srvCfg, + Config: *srvCfg, + Poktroll: poktrollAppConfigDefaults(), } - customAppTemplate := serverconfig.DefaultConfigTemplate - // Edit the default template file - // - // customAppTemplate := serverconfig.DefaultConfigTemplate + ` - // [wasm] - // # This is the maximum sdk gas (wasm and storage) that we allow for any x/wasm "smart" queries - // query_gas_limit = 300000 - // # This is the number of wasm vm instances we keep cached in memory for speed-up - // # Warning: this is currently unstable and may lead to crashes, best to keep for 0 unless testing locally - // lru_size = 0` - - return customAppTemplate, customAppConfig + return customPoktrollAppConfigTemplate(), customAppConfig +} + +// customPoktrollAppConfigTemplate extends the default configuration `app.toml` file with our own configs. +// They are going to be used by validators and full-nodes. +// These configs are rendered using default values from `poktrollAppConfigDefaults()`. +func customPoktrollAppConfigTemplate() string { + return serverconfig.DefaultConfigTemplate + ` + ############################################################################### + ### Poktroll ### + ############################################################################### + + # Poktroll-specific app configuration for Full Nodes and Validators. + [poktroll] + + # Telemetry configuration in addition to the [telemetry] settings. + [poktroll.telemetry] + + # Cardinality level for telemetry metrics collection + # This controls the level of detail (number of unique labels) in metrics. + # Options: + # - "low": Collects basic metrics with low cardinality. + # Suitable for production environments with tight performance constraints. + # - "medium": Collects a moderate number of labels, balancing detail and performance. + # Suitable for moderate workloads or staging environments. + # - "high": WARNING: WILL CAUSE STRESS TO YOUR MONITORING ENVIRONMENT! Collects detailed metrics with high + # cardinality, including labels with many unique values (e.g., application_id, session_id). + # Recommended for debugging or testing environments. + cardinality-level = "{{ .Poktroll.Telemetry.CardinalityLevel }}" + ` } diff --git a/config.yml b/config.yml index 73ea3a945..e2cabd9a8 100644 --- a/config.yml +++ b/config.yml @@ -91,7 +91,11 @@ validators: # minimum-gas-prices: 0.000000001upokt telemetry: enabled: true - prometheus-retention-time: "600" # seconds + poktroll: + telemetry: + # "high" produces a lot of timeseries. + # ONLY suitable for small networks such as LocalNet. + cardinality-level: high config: moniker: "validator1" consensus: @@ -139,28 +143,28 @@ genesis: denom: upokt bank: supply: - - amount: "1003000204" + - amount: "1102000204" denom: upokt balances: # Application module - address: pokt1rl3gjgzexmplmds3tq3r3yk84zlwdl6djzgsvm coins: - - amount: "1000068" # Equals to the total of all app stakes below + - amount: "100000068" # MUST BE equal to the total of all app stakes below denom: upokt # Supplier module - address: pokt1j40dzzmn6cn9kxku7a5tjnud6hv37vesr5ccaa coins: - - amount: "1000068" # Equals to the total of all supplier stakes below + - amount: "1000068" # MUST BE equal to the total of all supplier stakes below denom: upokt # Gateway module - address: pokt1f6j7u6875p2cvyrgjr0d2uecyzah0kget9vlpl coins: - - amount: "1000068" # Equals to the total of all gateway stakes below + - amount: "1000068" # MUST BE equal to the total of all gateway stakes below denom: upokt # Service module - address: pokt1nhmtqf4gcmpxu0p6e53hpgtwj0llmsqpxtumcf coins: - - amount: "1000000000" # Equals to one add_service_fee below + - amount: "1000000000" # MUST BE equal to one add_service_fee below denom: upokt application: params: @@ -171,9 +175,8 @@ genesis: denom: upokt applicationList: - address: pokt1mrqt5f7qh8uxs27cjm9t7v9e74a9vvdnq5jva4 - delegatee_gateway_addresses: [ - pokt15vzxjqklzjtlz7lahe8z2dfe9nm5vxwwmscne4 - ] + delegatee_gateway_addresses: + [pokt15vzxjqklzjtlz7lahe8z2dfe9nm5vxwwmscne4] service_configs: - service_id: anvil stake: @@ -182,9 +185,8 @@ genesis: amount: "100000068" # ~100 POKT denom: upokt - address: pokt184zvylazwu4queyzpl0gyz9yf5yxm2kdhh9hpm - delegatee_gateway_addresses: [ - pokt15vzxjqklzjtlz7lahe8z2dfe9nm5vxwwmscne4 - ] + delegatee_gateway_addresses: + [pokt15vzxjqklzjtlz7lahe8z2dfe9nm5vxwwmscne4] service_configs: - service_id: rest stake: diff --git a/go.mod b/go.mod index 91de15f1d..024364e1b 100644 --- a/go.mod +++ b/go.mod @@ -82,6 +82,7 @@ require ( require ( cosmossdk.io/x/tx v0.13.4 github.com/jhump/protoreflect v1.16.0 + github.com/mitchellh/mapstructure v1.5.0 ) require ( @@ -224,7 +225,6 @@ require ( github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/term v0.5.0 // indirect github.com/morikuni/aec v1.0.0 // indirect diff --git a/localnet/grafana-dashboards/cosmos_sdk_insights.json b/localnet/grafana-dashboards/cosmos_sdk_insights.json new file mode 100644 index 000000000..157314cdc --- /dev/null +++ b/localnet/grafana-dashboards/cosmos_sdk_insights.json @@ -0,0 +1,1318 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "links": [], + "panels": [ + { + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 8, + "title": "Block processing times", + "type": "row" + }, + { + "datasource": { + "default": true, + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": ".*: avg$" + }, + "properties": [ + { + "id": "custom.lineWidth", + "value": 3 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(begin_blocker{job=\"$job\"}) by (module, quantile)", + "instant": false, + "legendFormat": "{{module}}: q{{quantile}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(begin_blocker_sum{job=\"$job\"}) by (module) / sum(begin_blocker_count{job=\"$job\"}) by (module)", + "hide": false, + "instant": false, + "legendFormat": "{{module}}: avg", + "range": true, + "refId": "B" + } + ], + "title": "Begin Blocker Time", + "type": "timeseries" + }, + { + "datasource": { + "default": true, + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": ".*: avg$" + }, + "properties": [ + { + "id": "custom.lineWidth", + "value": 3 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(end_blocker{job=\"$job\"}) by (module, quantile)", + "instant": false, + "legendFormat": "{{module}}: q{{quantile}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(end_blocker_sum{job=\"$job\"}) by (module) / sum(end_blocker_count{job=\"$job\"}) by (module)", + "hide": false, + "instant": false, + "legendFormat": "{{module}}: avg", + "range": true, + "refId": "B" + } + ], + "title": "End Blocker Time", + "type": "timeseries" + }, + { + "datasource": { + "default": true, + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 9 + }, + "id": 13, + "options": { + "calculate": true, + "calculation": { + "yBuckets": { + "scale": { + "type": "linear" + } + } + }, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-green", + "mode": "opacity", + "reverse": false, + "scale": "exponential", + "scheme": "Greens", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "11.2.2+security-01", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by(le) (increase(cometbft_consensus_block_interval_seconds_bucket[$__rate_interval]))", + "format": "time_series", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "CometBFT Consensus Block Interval", + "type": "heatmap" + }, + { + "datasource": { + "default": true, + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": ".*: avg$" + }, + "properties": [ + { + "id": "custom.lineWidth", + "value": 3 + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 9 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(poktroll_proof_validation{job=\"$job\"}) by (quantile)", + "instant": false, + "legendFormat": " q{{quantile}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(poktroll_proof_validation_sum{job=\"$job\"}) / sum(poktroll_proof_validation_count{job=\"$job\"})", + "hide": false, + "instant": false, + "legendFormat": "avg", + "range": true, + "refId": "B" + } + ], + "title": "Proof Validation Time", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 17 + }, + "id": 9, + "panels": [], + "title": "Tokenomics", + "type": "row" + }, + { + "datasource": { + "default": true, + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 0, + "y": 18 + }, + "id": 11, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(poktroll_relay_ema{job=\"$job\",service_id=~\"$service_id\"}) by (service_id)", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "EMA by ServiceID", + "type": "timeseries" + }, + { + "datasource": { + "default": true, + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 6, + "y": 18 + }, + "id": 12, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(poktroll_relay_mining_difficulty{job=\"$job\",service_id=~\"$service_id\"}) by (service_id)", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "RelayMining difficulty by ServiceID", + "type": "timeseries" + }, + { + "datasource": { + "default": true, + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 12, + "y": 18 + }, + "id": 7, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(increase(poktroll_relays{job=\"$job\",service_id=~\"$service_id\"}[1m])) by (service_id, claim_proof_stage)", + "instant": false, + "legendFormat": "{{service_id}}-{{claim_proof_stage}}", + "range": true, + "refId": "A" + } + ], + "title": "On-Chain Relays", + "type": "timeseries" + }, + { + "datasource": { + "default": true, + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 18, + "y": 18 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(increase(poktroll_compute_units{job=\"$job\",service_id=~\"$service_id\"}[1m])) by (service_id, claim_proof_stage)", + "instant": false, + "legendFormat": "{{service_id}}-{{claim_proof_stage}}", + "range": true, + "refId": "A" + } + ], + "title": "Compute Units", + "type": "timeseries" + }, + { + "datasource": { + "default": true, + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 0, + "y": 24 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(increase(poktroll_proof_requirements{job=\"$job\",service_id=~\"$service_id\"}[1m])) by (service_id, reason)", + "instant": false, + "legendFormat": "{{service_id}}-{{reason}}", + "range": true, + "refId": "A" + } + ], + "title": "Proof requirements", + "type": "timeseries" + }, + { + "datasource": { + "default": true, + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byFrameRefID", + "options": "D" + }, + "properties": [ + { + "id": "custom.lineWidth", + "value": 3 + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 6, + "y": 24 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(increase(poktroll_minted_tokens{job=\"$job\"}[1m])) by (module)", + "instant": false, + "legendFormat": "minted by {{module}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(increase(poktroll_burned_tokens{job=\"$job\"}[1m])) by (module)", + "hide": false, + "instant": false, + "legendFormat": "burned by {{module}}", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(increase(poktroll_slashed_tokens{job=\"$job\"}[1m])) by (module)", + "hide": false, + "instant": false, + "legendFormat": "slashed by {{module}}", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(increase(poktroll_minted_tokens{job=\"$job\"}[1m])) - sum(increase(poktroll_burned_tokens{job=\"$job\"}[1m]))", + "hide": false, + "instant": false, + "legendFormat": "Minted total (minus burned)", + "range": true, + "refId": "D" + } + ], + "title": "Minted / Burned / Slashed Tokens", + "type": "timeseries" + }, + { + "datasource": { + "default": true, + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 6, + "x": 18, + "y": 24 + }, + "id": 10, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(increase(poktroll_claims{job=\"$job\",service_id=~\"$service_id\"}[1m])) by (service_id, claim_proof_stage)", + "instant": false, + "legendFormat": "{{service_id}}-{{claim_proof_stage}}", + "range": true, + "refId": "A" + } + ], + "title": "Claims", + "type": "timeseries" + } + ], + "refresh": "5s", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "validator-poktroll-validator", + "value": "validator-poktroll-validator" + }, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "definition": "label_values(cometbft_consensus_height,job)", + "hide": 0, + "includeAll": false, + "label": "Full Node", + "multi": false, + "name": "job", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(cometbft_consensus_height,job)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "definition": "label_values(poktroll_proof_requirements,service_id)", + "hide": 0, + "includeAll": true, + "label": "Service ID", + "multi": true, + "name": "service_id", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(poktroll_proof_requirements,service_id)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Protocol / Insights and On-Chain data", + "uid": "adzickiu028lcb", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/localnet/grafana-dashboards/permissionless_demand_observability.json b/localnet/grafana-dashboards/permissionless_demand_observability.json new file mode 100644 index 000000000..9fffee6e9 --- /dev/null +++ b/localnet/grafana-dashboards/permissionless_demand_observability.json @@ -0,0 +1,1314 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "links": [], + "panels": [ + { + "datasource": { + "default": true, + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "max(cometbft_consensus_block_size_bytes{})", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Block size", + "type": "timeseries" + }, + { + "datasource": { + "default": false, + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "editorMode": "code", + "format": "time_series", + "rawQuery": true, + "rawSql": "SELECT\n b.timestamp AS time,\n COUNT(m.id) AS num_proofs\nFROM\n localnet.messages m\nJOIN\n localnet.transactions t ON t.id = m.transaction_id\nJOIN\n localnet.blocks b ON b.id = t.block_id\nWHERE\n m.type_url = '/poktroll.proof.MsgSubmitProof'\n AND b.timestamp BETWEEN $__timeFrom() AND $__timeTo()\nGROUP BY\n b.timestamp\nORDER BY\n b.timestamp;\n", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Number of proofs", + "type": "timeseries" + }, + { + "datasource": { + "default": true, + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "increase(appgateserver_relay_requests_total[1m])", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Actual relays", + "type": "timeseries" + }, + { + "datasource": { + "default": false, + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "SELECT\n $__timeGroup(b.\"timestamp\", '1m') AS time,\n SUM(trim(both '\"' from ea_num_relays.value)::bigint) AS total_num_relays,\n (ea_claim.value::json ->> 'supplier_operator_address') AS supplier_operator_address,\n (ea_claim.value::json -> 'session_header' ->> 'service_id') AS service_id\nFROM\n localnet.events e\nJOIN\n localnet.event_attributes ea_num_relays ON ea_num_relays.event_id = e.id\n AND ea_num_relays.key = 'num_relays'\nJOIN\n localnet.event_attributes ea_claim ON ea_claim.event_id = e.id\n AND ea_claim.key = 'claim'\nJOIN\n localnet.blocks b ON b.id = e.block_id\nWHERE\n e.type = 'poktroll.proof.EventClaimCreated'\n AND b.\"timestamp\" BETWEEN $__timeFrom() AND $__timeTo()\nGROUP BY\n time, supplier_operator_address, service_id\nORDER BY\n time;\n", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "On chain relays from claims", + "type": "timeseries" + }, + { + "datasource": { + "default": true, + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 11, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(poktroll_relay_ema{service_id=~\"$service_id\"}) by (service_id)", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "EMA by service", + "type": "timeseries" + }, + { + "datasource": { + "default": true, + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 12, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(poktroll_relay_mining_difficulty{service_id=~\"$service_id\"}) by (service_id)", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "RM difficulty by service", + "type": "timeseries" + }, + { + "datasource": { + "default": false, + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 8, + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "targets": [ + { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "-- Average number of proofs per application\n\nWITH proofs_per_block AS (\n SELECT\n b.height AS block_height,\n m.json::jsonb -> 'sessionHeader' ->> 'applicationAddress' AS application_address,\n COUNT(m.id) AS num_proofs\n FROM\n localnet.messages m\n JOIN\n localnet.transactions t ON t.id = m.transaction_id\n JOIN\n localnet.blocks b ON b.id = t.block_id\n WHERE\n m.type_url = '/poktroll.proof.MsgSubmitProof'\n AND b.timestamp BETWEEN $__timeFrom() AND $__timeTo()\n GROUP BY\n b.height, application_address\n)\n\nSELECT\n application_address AS application,\n AVG(num_proofs) AS avg_num_proofs\nFROM\n proofs_per_block\nGROUP BY\n application\nORDER BY\n avg_num_proofs DESC;\n", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Average Number of Proofs per Application", + "type": "barchart" + }, + { + "datasource": { + "default": false, + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 24 + }, + "id": 9, + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "targets": [ + { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "-- Average number of proofs per service\n\nWITH proofs_per_block AS (\n SELECT\n b.height AS block_height,\n m.json::jsonb -> 'sessionHeader' ->> 'serviceId' AS service_id,\n COUNT(m.id) AS num_proofs\n FROM\n localnet.messages m\n JOIN\n localnet.transactions t ON t.id = m.transaction_id\n JOIN\n localnet.blocks b ON b.id = t.block_id\n WHERE\n m.type_url = '/poktroll.proof.MsgSubmitProof'\n AND b.timestamp BETWEEN $__timeFrom() AND $__timeTo()\n GROUP BY\n b.height, service_id\n)\n\nSELECT\n service_id AS service,\n AVG(num_proofs) AS avg_num_proofs\nFROM\n proofs_per_block\nGROUP BY\n service\nORDER BY\n avg_num_proofs DESC;\n", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Average Number of Proofs per Service", + "type": "barchart" + }, + { + "datasource": { + "default": false, + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 32 + }, + "id": 5, + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "targets": [ + { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "editorMode": "code", + "format": "time_series", + "rawQuery": true, + "rawSql": "SELECT\n b.timestamp AS time,\n COUNT(m.id) AS num_proofs,\n m.json::jsonb -> 'sessionHeader' ->> 'applicationAddress' AS application_address\nFROM\n localnet.messages m\nJOIN\n localnet.transactions t ON t.id = m.transaction_id\nJOIN\n localnet.blocks b ON b.id = t.block_id\nWHERE\n m.type_url = '/poktroll.proof.MsgSubmitProof'\n AND b.timestamp BETWEEN $__timeFrom() AND $__timeTo()\nGROUP BY\n b.timestamp, application_address\nORDER BY\n b.timestamp;\n", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Proof per application", + "type": "barchart" + }, + { + "datasource": { + "default": false, + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 32 + }, + "id": 6, + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "targets": [ + { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "editorMode": "code", + "format": "time_series", + "rawQuery": true, + "rawSql": "SELECT\n b.timestamp AS time,\n COUNT(m.id) AS num_proofs,\n m.json::jsonb -> 'sessionHeader' ->> 'serviceId' AS service_id\nFROM\n localnet.messages m\nJOIN\n localnet.transactions t ON t.id = m.transaction_id\nJOIN\n localnet.blocks b ON b.id = t.block_id\nWHERE\n m.type_url = '/poktroll.proof.MsgSubmitProof'\n AND b.timestamp BETWEEN $__timeFrom() AND $__timeTo()\nGROUP BY\n b.timestamp, service_id\nORDER BY\n b.timestamp;\n", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Proof per service", + "type": "barchart" + }, + { + "datasource": { + "default": false, + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 32 + }, + "id": 7, + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "targets": [ + { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "editorMode": "code", + "format": "time_series", + "rawQuery": true, + "rawSql": "SELECT\n b.timestamp AS time,\n COUNT(m.id) AS num_proofs,\n m.json::jsonb ->> 'supplierOperatorAddress' AS supplier_operator_address\nFROM\n localnet.messages m\nJOIN\n localnet.transactions t ON t.id = m.transaction_id\nJOIN\n localnet.blocks b ON b.id = t.block_id\nWHERE\n m.type_url = '/poktroll.proof.MsgSubmitProof'\n AND b.timestamp BETWEEN $__timeFrom() AND $__timeTo()\nGROUP BY\n b.timestamp, supplier_operator_address\nORDER BY\n b.timestamp;\n", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Proof per supplier operator", + "type": "barchart" + }, + { + "datasource": { + "default": false, + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 10, + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "targets": [ + { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "-- Serviced relays (from claims)\nWITH serviced_relays AS (\n SELECT\n (ea_claim.value::json ->> 'supplier_operator_address') AS supplier_operator_address,\n SUM(trim(both '\"' from ea_num_relays.value)::bigint) AS total_serviced_relays\n FROM\n localnet.events e\n JOIN\n localnet.event_attributes ea_num_relays ON ea_num_relays.event_id = e.id\n AND ea_num_relays.key = 'num_relays'\n JOIN\n localnet.event_attributes ea_claim ON ea_claim.event_id = e.id\n AND ea_claim.key = 'claim'\n JOIN\n localnet.blocks b ON b.id = e.block_id\n WHERE\n e.type = 'poktroll.proof.EventClaimCreated'\n AND b.\"timestamp\" BETWEEN $__timeFrom() AND $__timeTo()\n GROUP BY\n supplier_operator_address\n),\n\n-- Estimated relays (from proofs)\nestimated_relays AS (\n SELECT\n (ea_proof.value::json ->> 'supplier_operator_address') AS supplier_operator_address,\n SUM(trim(both '\"' from ea_num_relays.value)::bigint) AS total_estimated_relays\n FROM\n localnet.events e\n JOIN\n localnet.event_attributes ea_num_relays ON ea_num_relays.event_id = e.id\n AND ea_num_relays.key = 'num_relays'\n JOIN\n localnet.event_attributes ea_proof ON ea_proof.event_id = e.id\n AND ea_proof.key = 'proof'\n JOIN\n localnet.blocks b ON b.id = e.block_id\n WHERE\n e.type = 'poktroll.proof.EventProofSubmitted'\n AND b.\"timestamp\" BETWEEN $__timeFrom() AND $__timeTo()\n GROUP BY\n supplier_operator_address\n)\n\n-- Combine the totals per supplier\nSELECT\n COALESCE(s.supplier_operator_address, e.supplier_operator_address) AS supplier_operator_address,\n COALESCE(s.total_serviced_relays, 0) AS total_serviced_relays,\n COALESCE(e.total_estimated_relays, 0) AS total_estimated_relays\nFROM\n serviced_relays s\nFULL OUTER JOIN\n estimated_relays e ON s.supplier_operator_address = e.supplier_operator_address\nORDER BY\n supplier_operator_address;\n", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "cumulative number of relays claims vs proofs per supplier", + "type": "barchart" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Permissionless demand observability", + "version": 0, + "weekStart": "" +} \ No newline at end of file diff --git a/localnet/grafana-dashboards/tokenomics_relays.json b/localnet/grafana-dashboards/tokenomics_relays.json new file mode 100644 index 000000000..f6228f499 --- /dev/null +++ b/localnet/grafana-dashboards/tokenomics_relays.json @@ -0,0 +1,523 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 5, + "y": 0 + }, + "id": 4, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "## What does this dashboard show?\n\nAs relays flow through the network\nAppGate -> RelayMiner and RelayMiner creates proofs and claims, we can capture the whole relay cycle.\n\n1. shows the actual amount of relays on AppGate;\n2. shows the actual amount of relays processed by RelayMiner;\n3. the amount of relays from the on-chain information using `EventClaimCreated`;\n4. relays from `EventProofSubmitted`;", + "mode": "markdown" + }, + "pluginVersion": "11.2.2+security-01", + "title": "Wht is this dashboard?", + "type": "text" + }, + { + "datasource": { + "default": true, + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "increase(appgateserver_relay_requests_total[$group_by])", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Actual AppGate Requests", + "type": "timeseries" + }, + { + "datasource": { + "default": true, + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 16 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "increase(relayminer_requests_total[$group_by])", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Actual RelayMIner Requests", + "type": "timeseries" + }, + { + "datasource": { + "default": false, + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 24 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "editorMode": "code", + "format": "time_series", + "rawQuery": true, + "rawSql": "SELECT\n $__timeGroup(b.\"timestamp\", '$group_by') AS time,\n SUM(trim(both '\"' from ea_num_relays.value)::bigint) AS total_num_relays,\n (ea_claim.value::json ->> 'supplier_operator_address') AS supplier_operator_address,\n (ea_claim.value::json -> 'session_header' ->> 'service_id') AS service_id\nFROM\n localnet.events e\nJOIN\n localnet.event_attributes ea_num_relays ON ea_num_relays.event_id = e.id\n AND ea_num_relays.key = 'num_relays'\nJOIN\n localnet.event_attributes ea_claim ON ea_claim.event_id = e.id\n AND ea_claim.key = 'claim'\nJOIN\n localnet.blocks b ON b.id = e.block_id\nWHERE\n e.type = 'poktroll.proof.EventClaimCreated'\n AND b.\"timestamp\" BETWEEN $__timeFrom() AND $__timeTo()\nGROUP BY\n time, supplier_operator_address, service_id\nORDER BY\n time;\n", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Relays (from on-chain claims)", + "type": "timeseries" + }, + { + "datasource": { + "default": false, + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 32 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "grafana-postgresql-datasource", + "uid": "PCC52D03280B7034C" + }, + "editorMode": "code", + "format": "time_series", + "rawQuery": true, + "rawSql": "SELECT\n $__timeGroup(b.\"timestamp\", '$group_by') AS time,\n SUM(trim(both '\"' from ea_num_relays.value)::bigint) AS total_num_relays,\n (ea_proof.value::json ->> 'supplier_operator_address') AS supplier_operator_address,\n (ea_proof.value::json -> 'session_header' ->> 'service_id') AS service_id\nFROM\n localnet.events e\nJOIN\n localnet.event_attributes ea_num_relays ON ea_num_relays.event_id = e.id\n AND ea_num_relays.key = 'num_relays'\nJOIN\n localnet.event_attributes ea_proof ON ea_proof.event_id = e.id\n AND ea_proof.key = 'proof'\nJOIN\n localnet.blocks b ON b.id = e.block_id\nWHERE\n e.type = 'poktroll.proof.EventProofSubmitted'\n AND b.\"timestamp\" BETWEEN $__timeFrom() AND $__timeTo()\nGROUP BY\n time, supplier_operator_address, service_id\nORDER BY\n time;\n", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Relays (from on-chain proofs)", + "type": "timeseries" + } + ], + "refresh": "10s", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": true, + "text": "1m", + "value": "1m" + }, + "hide": 0, + "includeAll": false, + "label": "Group by time / Window", + "multi": false, + "name": "group_by", + "options": [ + { + "selected": true, + "text": "1m", + "value": "1m" + }, + { + "selected": false, + "text": "5m", + "value": "5m" + }, + { + "selected": false, + "text": "10m", + "value": "10m" + }, + { + "selected": false, + "text": "15m", + "value": "15m" + } + ], + "query": "1m,5m,10m,15m", + "queryValue": "", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Protocol / Tokenomics / Relays life-cycle", + "version": 0, + "weekStart": "" +} \ No newline at end of file diff --git a/localnet/kubernetes/observability-prometheus-stack.yaml b/localnet/kubernetes/observability-prometheus-stack.yaml index c6a29b67b..566ac33fd 100644 --- a/localnet/kubernetes/observability-prometheus-stack.yaml +++ b/localnet/kubernetes/observability-prometheus-stack.yaml @@ -17,7 +17,28 @@ grafana: viewers_can_edit: true security: allow_embedding: true + additionalDataSources: + - name: PostgreSQL + type: postgres + access: proxy + url: postgres-service:5432 + database: postgres + user: postgres + secureJsonData: + password: postgres + jsonData: + sslmode: disable + postgresVersion: 1604 # Adjust to match your PostgreSQL version + # timescaledb: false # Set to true if you are using TimescaleDB + schema: localnet # Specify your postgres schema here prometheus: prometheusSpec: - serviceMonitorSelectorNilUsesHelmValues: false + scrapeConfigSelector: + matchLabels: null + serviceMonitorSelector: + matchLabels: null + ruleSelector: + matchLabels: null + podMonitorSelector: + matchLabels: null diff --git a/localnet/poktrolld/config/app.toml b/localnet/poktrolld/config/app.toml index c80f545ae..d5135735e 100644 --- a/localnet/poktrolld/config/app.toml +++ b/localnet/poktrolld/config/app.toml @@ -34,6 +34,11 @@ query-gas-limit = "0" [mempool] max-txs = 10000 +[poktroll] + + [poktroll.telemetry] + cardinality-level = "high" + [rpc] cors_allowed_origins = ["*"] @@ -56,6 +61,6 @@ query-gas-limit = "0" enabled = true global-labels = [] metrics-sink = "mem" - prometheus-retention-time = "600" + prometheus-retention-time = 86400 service-name = "" statsd-addr = "" diff --git a/localnet/poktrolld/config/appgate_server_config_localnet_vscode.yaml b/localnet/poktrolld/config/appgate_server_config_localnet_vscode.yaml index 7c7e475da..2dab42371 100644 --- a/localnet/poktrolld/config/appgate_server_config_localnet_vscode.yaml +++ b/localnet/poktrolld/config/appgate_server_config_localnet_vscode.yaml @@ -1,5 +1,5 @@ query_node_rpc_url: tcp://localhost:26657 -query_node_grpc_url: tcp://localhost:9090 +query_node_grpc_url: tcp://localhost:36658 signing_key: app1 self_signing: true listening_endpoint: http://0.0.0.0:42069 diff --git a/localnet/poktrolld/config/relayminer_config_localnet_vscode.yaml b/localnet/poktrolld/config/relayminer_config_localnet_vscode.yaml index 74ba44dde..451914f9f 100644 --- a/localnet/poktrolld/config/relayminer_config_localnet_vscode.yaml +++ b/localnet/poktrolld/config/relayminer_config_localnet_vscode.yaml @@ -22,9 +22,9 @@ metrics: enabled: true addr: :9070 pocket_node: - query_node_rpc_url: tcp://127.0.0.1:36657 - query_node_grpc_url: tcp://127.0.0.1:36658 - tx_node_rpc_url: tcp://127.0.0.1:36657 + query_node_rpc_url: tcp://localhost:26657 + query_node_grpc_url: tcp://localhost:36658 + tx_node_rpc_url: tcp://localhost:26657 suppliers: - service_id: anvil listen_url: http://0.0.0.0:8545 @@ -38,6 +38,12 @@ suppliers: backend_url: http://localhost:11434/ publicly_exposed_endpoints: - relayminer1 + - service_id: rest + listen_url: http://0.0.0.0:8545 + service_config: + backend_url: http://rest:10000/ + publicly_exposed_endpoints: + - relayminer1 pprof: enabled: false addr: localhost:6070 diff --git a/pkg/appgateserver/cmd/cmd.go b/pkg/appgateserver/cmd/cmd.go index 740104182..124d8ceb5 100644 --- a/pkg/appgateserver/cmd/cmd.go +++ b/pkg/appgateserver/cmd/cmd.go @@ -31,6 +31,8 @@ var ( flagNodeRPCURL string // flagNodeGRPCURL is the variable containing the Cosmos node GRPC URL flag value. flagNodeGRPCURL string + // flagLogLevel is the variable to set a log level (used by cosmos and polylog). + flagLogLevel string ) // AppGateServerCmd returns the Cobra command for running the AppGate server. @@ -74,6 +76,7 @@ provided that: cmd.Flags().StringVar(&flagNodeRPCURL, cosmosflags.FlagNode, omittedDefaultFlagValue, "Register the default Cosmos node flag, which is needed to initialize the Cosmos query context correctly. It can be used to override the `QueryNodeUrl` field in the config file if specified.") cmd.Flags().StringVar(&flagNodeGRPCURL, cosmosflags.FlagGRPC, omittedDefaultFlagValue, "Register the default Cosmos node grpc flag, which is needed to initialize the Cosmos query context with grpc correctly. It can be used to override the `QueryNodeGRPCUrl` field in the config file if specified.") cmd.Flags().Bool(cosmosflags.FlagGRPCInsecure, true, "Used to initialize the Cosmos query context with grpc security options. It can be used to override the `QueryNodeGRPCInsecure` field in the config file if specified.") + cmd.Flags().StringVar(&flagLogLevel, cosmosflags.FlagLogLevel, "debug", "The logging level (debug|info|warn|error)") return cmd } @@ -99,7 +102,7 @@ func runAppGateServer(cmd *cobra.Command, _ []string) error { // TODO_TECHDEBT: populate logger from the config (ideally, from viper). loggerOpts := []polylog.LoggerOption{ - polyzero.WithLevel(polyzero.DebugLevel), + polyzero.WithLevel(polyzero.ParseLevel(flagLogLevel)), polyzero.WithOutput(os.Stderr), } diff --git a/pkg/relayer/cmd/cmd.go b/pkg/relayer/cmd/cmd.go index c8f0df94e..98df7e375 100644 --- a/pkg/relayer/cmd/cmd.go +++ b/pkg/relayer/cmd/cmd.go @@ -39,6 +39,8 @@ var ( flagNodeRPCURL string // flagNodeGRPCURL is the variable containing the Cosmos node GRPC URL flag value. flagNodeGRPCURL string + // flagLogLevel is the variable to set a log level (used by cosmos and polylog). + flagLogLevel string ) // RelayerCmd returns the Cobra command for running the relay miner. @@ -72,6 +74,7 @@ for such operations.`, cmd.Flags().StringVar(&flagNodeGRPCURL, cosmosflags.FlagGRPC, omittedDefaultFlagValue, "Register the default Cosmos node grpc flag, which is needed to initialize the Cosmos query context with grpc correctly. It can be used to override the `QueryNodeGRPCURL` field in the config file if specified.") cmd.Flags().Bool(cosmosflags.FlagGRPCInsecure, true, "Used to initialize the Cosmos query context with grpc security options. It can be used to override the `QueryNodeGRPCInsecure` field in the config file if specified.") cmd.Flags().String(cosmosflags.FlagChainID, "poktroll", "The network chain ID") + cmd.Flags().StringVar(&flagLogLevel, cosmosflags.FlagLogLevel, "debug", "The logging level (debug|info|warn|error)") return cmd } @@ -97,7 +100,7 @@ func runRelayer(cmd *cobra.Command, _ []string) error { // TODO_TECHDEBT: populate logger from the config (ideally, from viper). loggerOpts := []polylog.LoggerOption{ - polyzero.WithLevel(polyzero.DebugLevel), + polyzero.WithLevel(polyzero.ParseLevel(flagLogLevel)), polyzero.WithOutput(os.Stderr), } diff --git a/pkg/relayer/proxy/metrics.go b/pkg/relayer/proxy/metrics.go index d42f09c4b..4fdea226e 100644 --- a/pkg/relayer/proxy/metrics.go +++ b/pkg/relayer/proxy/metrics.go @@ -29,7 +29,7 @@ var ( Subsystem: relayMinerProcess, Name: requestsTotal, Help: "Total number of requests processed, labeled by service ID.", - }, []string{"service_id"}) + }, []string{"service_id", "supplier_operator_address"}) // relaysErrorsTotal is a Counter for total error events in the relay miner. // It increments with each error, labeled by 'service_id', @@ -45,7 +45,7 @@ var ( }, []string{"service_id"}) // relaysSuccessTotal is a Counter metric for successful requests in the relay miner. - // It increments with each successful request, labeled by ''service_id'. + // It increments with each successful request, labeled by 'service_id'. relaysSuccessTotal = prometheus.NewCounterFrom(stdprometheus.CounterOpts{ Subsystem: relayMinerProcess, Name: requestsSuccessTotal, diff --git a/pkg/relayer/proxy/synchronous.go b/pkg/relayer/proxy/synchronous.go index e3767eef6..df3bb8e35 100644 --- a/pkg/relayer/proxy/synchronous.go +++ b/pkg/relayer/proxy/synchronous.go @@ -174,7 +174,10 @@ func (sync *synchronousRPCServer) ServeHTTP(writer http.ResponseWriter, request } // Increment the relays counter. - relaysTotal.With("service_id", supplierServiceId).Add(1) + relaysTotal.With( + "service_id", supplierServiceId, + "supplier_operator_address", relayRequest.Meta.SupplierOperatorAddress, + ).Add(1) defer func() { duration := time.Since(startTime).Seconds() @@ -203,7 +206,7 @@ func (sync *synchronousRPCServer) ServeHTTP(writer http.ResponseWriter, request return } - sync.logger.Info().Fields(map[string]any{ + sync.logger.Debug().Fields(map[string]any{ "application_address": relay.Res.Meta.SessionHeader.ApplicationAddress, "service_id": relay.Res.Meta.SessionHeader.ServiceId, "session_start_height": relay.Res.Meta.SessionHeader.SessionStartBlockHeight, diff --git a/telemetry/block.go b/telemetry/block.go index b012a7d4a..59074f783 100644 --- a/telemetry/block.go +++ b/telemetry/block.go @@ -77,6 +77,10 @@ func (mal metricsABCIListener) ListenFinalizeBlock( req abci.RequestFinalizeBlock, res abci.ResponseFinalizeBlock, ) error { + if !isTelemetyEnabled() { + return nil + } + telemetry.SetGauge( float32(res.Size()), blockResultSizeBytesMetric, @@ -94,5 +98,9 @@ func (mal metricsABCIListener) ListenCommit( res abci.ResponseCommit, changeSet []*storetypes.StoreKVPair, ) error { + if !isTelemetyEnabled() { + return nil + } + return nil } diff --git a/telemetry/common.go b/telemetry/common.go new file mode 100644 index 000000000..28f5dc59b --- /dev/null +++ b/telemetry/common.go @@ -0,0 +1,54 @@ +package telemetry + +import ( + cosmostelemetry "github.com/cosmos/cosmos-sdk/telemetry" + "github.com/hashicorp/go-metrics" +) + +// MetricNameKeys prefixes metrics with `poktroll` for easy identification. +// E.g., `("hodlers", "regret_level")` yields `poktroll_hodlers_regret_level` — great for tracking FOMO as hodlers rethink choices. +// Returns a slice of strings as `go-metric`, the underlying metrics library, expects. +func MetricNameKeys(metrics ...string) []string { + result := make([]string, 0, len(metrics)+1) + result = append(result, metricNamePrefix) + result = append(result, metrics...) + return result +} + +// isTelemetyEnabled returns whether is telemetry turned on in the config file `app.toml` - cosmos-sdk's telemetry section. +func isTelemetyEnabled() bool { + return cosmostelemetry.IsTelemetryEnabled() +} + +// appendMediumCardinalityLabels only creates the label if cardinality if set to "medium" or higher. +// A good example for a "medium" cardinality use-case is `service_id`: +// - This is a network wide parameter +// - It is dependenon the permissionless nature of the network and can grow unbounded +// - We're keeping an option to turn off such labels to avoid metric bloat +// +// Configuration option is exposed in app.toml under the `poktroll.telemetry` section. +func appendMediumCardinalityLabels(labels []metrics.Label, labelPairs ...metrics.Label) []metrics.Label { + if globalTelemetryConfig.CardinalityLevel == "medium" || globalTelemetryConfig.CardinalityLevel == "high" { + return append(labels, labelPairs...) + } + return labels +} + +// appendHighCardinalityLabels only creates the label if cardinality is set to "high". +// A good example of high cardinality labels is `application_address` or `supplier_address`: +// - This setting, on a large network, will slow down both the full node and the metric scraping system. +// - These labels need to be exposed for local development, debugging and performance troubleshooting. +// +// Additional references on cardinality: https://www.robustperception.io/cardinality-is-key/ +// Configuration option is exposed in app.toml under the `poktroll.telemetry` section. +func appendHighCardinalityLabels(labels []metrics.Label, labelPairs ...metrics.Label) []metrics.Label { + if globalTelemetryConfig.CardinalityLevel == "high" { + return append(labels, labelPairs...) + } + return labels +} + +// toMetricLabel takes simple key and value of the label to return metrics.Label. +func toMetricLabel(key, value string) metrics.Label { + return cosmostelemetry.NewLabel(key, value) +} diff --git a/telemetry/event_counters.go b/telemetry/event_counters.go index 054e67ddb..2a36580be 100644 --- a/telemetry/event_counters.go +++ b/telemetry/event_counters.go @@ -10,16 +10,15 @@ import ( "github.com/cosmos/cosmos-sdk/telemetry" "github.com/hashicorp/go-metrics" - - prooftypes "github.com/pokt-network/poktroll/x/proof/types" ) const ( - // TODO_DECIDE: Decide if we want to continue using these generic metrics keys - // or opt for specific keys for each event_type. - // See: https://github.com/pokt-network/poktroll/pull/631#discussion_r1653760820 - eventTypeMetricKey = "event_type" - eventTypeMetricKeyGauge = "event_type_gauge" + // Prefix all metric names with "poktroll" for easier search + metricNamePrefix = "poktroll" + + // Label Names + applicationAddressLabelName = "app_addr" + supplierOperatorAddressLabelName = "sup_op_addr" ) // EventSuccessCounter increments a counter with the given data type and success status. @@ -28,15 +27,25 @@ func EventSuccessCounter( getValue func() float32, isSuccessful func() bool, ) { - successResult := strconv.FormatBool(isSuccessful()) + if !isTelemetyEnabled() { + return + } + value := getValue() + var metricName []string + + if isSuccessful() { + metricName = MetricNameKeys("successful", "events") + } else { + metricName = MetricNameKeys("failed", "events") + } + telemetry.IncrCounterWithLabels( - []string{eventTypeMetricKey}, + metricName, value, []metrics.Label{ {Name: "type", Value: eventType}, - {Name: "is_successful", Value: successResult}, }, ) } @@ -46,23 +55,34 @@ func EventSuccessCounter( // probabilistic selection, above compute unit threshold). // If err is not nil, the counter is not incremented but Prometheus will ingest this event. func ProofRequirementCounter( - reason prooftypes.ProofRequirementReason, + reason string, + serviceId string, + applicationAddress string, + supplierOperatorAddress string, err error, ) { + if !isTelemetyEnabled() { + return + } + incrementAmount := 1 - isRequired := strconv.FormatBool(reason != prooftypes.ProofRequirementReason_NOT_REQUIRED) labels := []metrics.Label{ - {Name: "proof_required_reason", Value: reason.String()}, - {Name: "is_required", Value: isRequired}, + {Name: "reason", Value: reason}, } + labels = appendMediumCardinalityLabels(labels, toMetricLabel("service_id", serviceId)) + labels = appendHighCardinalityLabels( + labels, + toMetricLabel(applicationAddressLabelName, applicationAddress), + toMetricLabel(supplierOperatorAddressLabelName, supplierOperatorAddress), + ) // Ensure the counter is not incremented if there was an error. if err != nil { - incrementAmount = 0 + return } telemetry.IncrCounterWithLabels( - []string{eventTypeMetricKey}, + MetricNameKeys("proof", "requirements"), float32(incrementAmount), labels, ) @@ -72,15 +92,27 @@ func ProofRequirementCounter( // which are represented by on-chain claims at the given ClaimProofStage. // If err is not nil, the counter is not incremented but Prometheus will ingest this event. func ClaimComputeUnitsCounter( - claimProofStage prooftypes.ClaimProofStage, + claimProofStage string, numComputeUnits uint64, + serviceId string, + applicationAddress string, + supplierOperatorAddress string, err error, ) { + if !isTelemetyEnabled() { + return + } + incrementAmount := numComputeUnits labels := []metrics.Label{ - {Name: "unit", Value: "compute_units"}, - {Name: "claim_proof_stage", Value: claimProofStage.String()}, + {Name: "claim_proof_stage", Value: claimProofStage}, } + labels = appendMediumCardinalityLabels(labels, toMetricLabel("service_id", serviceId)) + labels = appendHighCardinalityLabels( + labels, + toMetricLabel(applicationAddressLabelName, applicationAddress), + toMetricLabel(supplierOperatorAddressLabelName, supplierOperatorAddress), + ) // Ensure the counter is not incremented if there was an error. if err != nil { @@ -88,7 +120,7 @@ func ClaimComputeUnitsCounter( } telemetry.IncrCounterWithLabels( - []string{eventTypeMetricKey}, + MetricNameKeys("compute_units"), float32(incrementAmount), labels, ) @@ -99,15 +131,27 @@ func ClaimComputeUnitsCounter( // If err is not nil, the counter is not incremented and an "error" label is added // with the error's message. I.e., Prometheus will ingest this event. func ClaimRelaysCounter( - claimProofStage prooftypes.ClaimProofStage, + claimProofStage string, numRelays uint64, + serviceId string, + applicationAddress string, + supplierOperatorAddress string, err error, ) { + if !isTelemetyEnabled() { + return + } + incrementAmount := numRelays labels := []metrics.Label{ - {Name: "unit", Value: "relays"}, - {Name: "claim_proof_stage", Value: claimProofStage.String()}, + {Name: "claim_proof_stage", Value: claimProofStage}, } + labels = appendMediumCardinalityLabels(labels, toMetricLabel("service_id", serviceId)) + labels = appendHighCardinalityLabels( + labels, + toMetricLabel(applicationAddressLabelName, applicationAddress), + toMetricLabel(supplierOperatorAddressLabelName, supplierOperatorAddress), + ) // Ensure the counter is not incremented if there was an error. if err != nil { @@ -115,7 +159,7 @@ func ClaimRelaysCounter( } telemetry.IncrCounterWithLabels( - []string{eventTypeMetricKey}, + MetricNameKeys("relays"), float32(incrementAmount), labels, ) @@ -125,23 +169,36 @@ func ClaimRelaysCounter( // ClaimProofStage. // If err is not nil, the counter is not incremented but Prometheus will ingest this event. func ClaimCounter( - claimProofStage prooftypes.ClaimProofStage, + claimProofStage string, numClaims uint64, + serviceId string, + applicationAddress string, + supplierOperatorAddress string, err error, ) { + if !isTelemetyEnabled() { + return + } + incrementAmount := numClaims labels := []metrics.Label{ - {Name: "unit", Value: "claims"}, - {Name: "claim_proof_stage", Value: claimProofStage.String()}, + {Name: "claim_proof_stage", Value: claimProofStage}, } + labels = appendMediumCardinalityLabels(labels, toMetricLabel("service_id", serviceId)) + labels = appendHighCardinalityLabels( + labels, + toMetricLabel(applicationAddressLabelName, applicationAddress), + toMetricLabel(supplierOperatorAddressLabelName, supplierOperatorAddress), + ) + // Ensure the counter is not incremented if there was an error. if err != nil { incrementAmount = 0 } telemetry.IncrCounterWithLabels( - []string{eventTypeMetricKey}, + MetricNameKeys("claims"), float32(incrementAmount), labels, ) @@ -151,13 +208,15 @@ func ClaimCounter( // of the relay mining difficulty. The serviceId is used as a label to be able to // track the difficulty for each service. func RelayMiningDifficultyGauge(difficulty float32, serviceId string) { - labels := []metrics.Label{ - {Name: "type", Value: "relay_mining_difficulty"}, - {Name: "service_id", Value: serviceId}, + if !isTelemetyEnabled() { + return } + labels := []metrics.Label{} + labels = appendMediumCardinalityLabels(labels, toMetricLabel("service_id", serviceId)) + telemetry.SetGaugeWithLabels( - []string{eventTypeMetricKeyGauge}, + MetricNameKeys("relay_mining", "difficulty"), difficulty, labels, ) @@ -166,14 +225,39 @@ func RelayMiningDifficultyGauge(difficulty float32, serviceId string) { // RelayEMAGauge sets a gauge which tracks the relay EMA for a service. // The serviceId is used as a label to be able to track the EMA for each service. func RelayEMAGauge(relayEMA uint64, serviceId string) { - labels := []metrics.Label{ - {Name: "type", Value: "relay_ema"}, - {Name: "service_id", Value: serviceId}, + if !isTelemetyEnabled() { + return } + labels := []metrics.Label{} + labels = appendMediumCardinalityLabels(labels, toMetricLabel("service_id", serviceId)) + telemetry.SetGaugeWithLabels( - []string{eventTypeMetricKeyGauge}, + MetricNameKeys("relay", "ema"), float32(relayEMA), labels, ) } + +// SessionSuppliersGauge sets a gauge which tracks the number of candidates available +// for session suppliers at the given maxPerSession value. +// The serviceId is used as a label to be able to track this information for each service. +func SessionSuppliersGauge(numCandidates int, maxPerSession int, serviceId string) { + if !isTelemetyEnabled() { + return + } + + maxPerSessionStr := strconv.Itoa(maxPerSession) + labels := []metrics.Label{} + labels = appendMediumCardinalityLabels( + labels, + toMetricLabel("service_id", serviceId), + toMetricLabel("max_per_session", maxPerSessionStr), + ) + + telemetry.SetGaugeWithLabels( + MetricNameKeys("session", "suppliers"), + float32(numCandidates), + labels, + ) +} diff --git a/telemetry/telemetry.go b/telemetry/telemetry.go new file mode 100644 index 000000000..348b73898 --- /dev/null +++ b/telemetry/telemetry.go @@ -0,0 +1,31 @@ +package telemetry + +import ( + "fmt" + + servertypes "github.com/cosmos/cosmos-sdk/server/types" + "github.com/mitchellh/mapstructure" +) + +// globalTelemetryConfig stores poktroll specific telemetry configurations. +// Set once on initialization and remains constant during runtime. +var globalTelemetryConfig PoktrollTelemetryConfig + +// PoktrollTelemetryConfig represents the telemetry protion of the custom poktroll config section in `app.toml`. +type PoktrollTelemetryConfig struct { + CardinalityLevel string `mapstructure:"cardinality-level"` +} + +// New sets the globalTelemetryConfig for telemetry package. +func New(appOpts servertypes.AppOptions) error { + // Extract the map from appOpts. + // `poktroll.telemetry` comes from `app.toml` which is parsed into a map. + telemetryMap := appOpts.Get("poktroll.telemetry").(map[string]interface{}) + + // Use mapstructure to decode the map into the struct + if err := mapstructure.Decode(telemetryMap, &globalTelemetryConfig); err != nil { + return fmt.Errorf("error decoding poktroll.telemetry config: %v", err) + } + + return nil +} diff --git a/telemetry/tokens.go b/telemetry/tokens.go new file mode 100644 index 000000000..a62b3355f --- /dev/null +++ b/telemetry/tokens.go @@ -0,0 +1,61 @@ +package telemetry + +import ( + cosmostelemetry "github.com/cosmos/cosmos-sdk/telemetry" + "github.com/hashicorp/go-metrics" +) + +// TODO_MAINNET(@bryanchriswhite): Revisit how telemetry is managed under `x/tokenomics` to ensure that it +// complies with the new hardened settlement approach. + +// TODO_MAINNET(@red-0ne, #897): Minted, burnt and slashd tokens values might not be completely accurate. +// While we're keeping this metric for now consider removing in favor of utilizing the `cosmos-exporter` which uses on-chain data. +// Context: https://github.com/cosmos/cosmos-sdk/issues/21614, https://github.com/pokt-network/poktroll/pull/832 + +// MintedTokensFromModule is a function to track token minting from a specific module. +// The metric used is an increment counter, and the label includes the module name for context. +func MintedTokensFromModule(module string, amount float32) { + if !isTelemetyEnabled() { + return + } + + cosmostelemetry.IncrCounterWithLabels( + MetricNameKeys("minted", "tokens"), + amount, + []metrics.Label{ + cosmostelemetry.NewLabel("module", module), + }, + ) +} + +// BurnedTokensFromModule is a function to track token burning from a specific module. +// The metric used is an increment counter, and the label includes the module name for context. +func BurnedTokensFromModule(module string, amount float32) { + if !isTelemetyEnabled() { + return + } + + cosmostelemetry.IncrCounterWithLabels( + MetricNameKeys("burned", "tokens"), + amount, + []metrics.Label{ + cosmostelemetry.NewLabel("module", module), + }, + ) +} + +// SlashedTokensFromModule is a function to track token slashing from a specific module. +// The metric used is an increment counter, and the label includes the module name for context. +func SlashedTokensFromModule(module string, amount float32) { + if !isTelemetyEnabled() { + return + } + + cosmostelemetry.IncrCounterWithLabels( + MetricNameKeys("slashed", "tokens"), + amount, + []metrics.Label{ + cosmostelemetry.NewLabel("module", module), + }, + ) +} diff --git a/x/application/module/abci.go b/x/application/module/abci.go index 4890fa062..3a1b7b337 100644 --- a/x/application/module/abci.go +++ b/x/application/module/abci.go @@ -1,13 +1,18 @@ package application import ( + cosmostelemetry "github.com/cosmos/cosmos-sdk/telemetry" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/pokt-network/poktroll/x/application/keeper" + "github.com/pokt-network/poktroll/x/application/types" ) // EndBlocker is called every block and handles application related updates. func EndBlocker(ctx sdk.Context, k keeper.Keeper) error { + // Telemetry: measure the end-block execution time following standard cosmos-sdk practices. + defer cosmostelemetry.ModuleMeasureSince(types.ModuleName, cosmostelemetry.Now(), cosmostelemetry.MetricKeyEndBlocker) + if err := k.EndBlockerAutoUndelegateFromUnstakedGateways(ctx); err != nil { return err } diff --git a/x/application/types/types.pb.go b/x/application/types/types.pb.go index 9e5b8ff6c..32bc0cc13 100644 --- a/x/application/types/types.pb.go +++ b/x/application/types/types.pb.go @@ -31,14 +31,12 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type Application struct { Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` Stake *types.Coin `protobuf:"bytes,2,opt,name=stake,proto3" json:"stake,omitempty"` - // As per this discussion: - // https://github.com/pokt-network/poktroll/pull/750#discussion_r1735025033 - // The number of service_configs is limited to 1 per service. - // This is to ensure that an application could not over service by making multiple - // claims settelments compete to burn the same stake. - // A slice of service_configs is still maintained to allow for future multi-service - // capabilities to be added, such as off-chain application stake tracking by suppliers: - // https://www.notion.so/buildwithgrove/Off-chain-Application-Stake-Tracking-6a8bebb107db4f7f9dc62cbe7ba555f7 + // CRITICAL_DEV_NOTE: The number of service_configs must be EXACTLY ONE. + // This prevents applications from over-servicing. + // The field is kept repeated (a list) for both legacy and future logic reaosns. + // References: + // - https://github.com/pokt-network/poktroll/pull/750#discussion_r1735025033 + // - https://www.notion.so/buildwithgrove/Off-chain-Application-Stake-Tracking-6a8bebb107db4f7f9dc62cbe7ba555f7 ServiceConfigs []*types1.ApplicationServiceConfig `protobuf:"bytes,3,rep,name=service_configs,json=serviceConfigs,proto3" json:"service_configs,omitempty"` // TODO_BETA: Rename `delegatee_gateway_addresses` to `gateway_addresses_delegated_to`. // Ensure to rename all relevant configs, comments, variables, function names, etc as well. diff --git a/x/proof/keeper/msg_server_create_claim.go b/x/proof/keeper/msg_server_create_claim.go index 01a5f509a..f95e262b1 100644 --- a/x/proof/keeper/msg_server_create_claim.go +++ b/x/proof/keeper/msg_server_create_claim.go @@ -11,6 +11,7 @@ import ( "github.com/pokt-network/poktroll/telemetry" "github.com/pokt-network/poktroll/x/proof/types" + sessiontypes "github.com/pokt-network/poktroll/x/session/types" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" ) @@ -26,16 +27,6 @@ func (k msgServer) CreateClaim( numClaimComputeUnits uint64 ) - // Defer telemetry calls so that they reference the final values the relevant variables. - defer func() { - // Only increment these metrics counters if handling a new claim. - if !isExistingClaim { - telemetry.ClaimCounter(types.ClaimProofStage_CLAIMED, 1, err) - telemetry.ClaimRelaysCounter(types.ClaimProofStage_CLAIMED, numRelays, err) - telemetry.ClaimComputeUnitsCounter(types.ClaimProofStage_CLAIMED, numClaimComputeUnits, err) - } - }() - logger := k.Logger().With("method", "CreateClaim") sdkCtx := cosmostypes.UnwrapSDKContext(ctx) logger.Info("creating claim") @@ -52,6 +43,9 @@ func (k msgServer) CreateClaim( return nil, status.Error(codes.InvalidArgument, err.Error()) } + // Defer telemetry calls to a helper function to keep business logic clean. + defer k.finalizeCreateClaimTelemetry(session, msg, isExistingClaim, numRelays, numClaimComputeUnits, err) + // Construct and insert claim claim = types.Claim{ SupplierOperatorAddress: msg.GetSupplierOperatorAddress(), @@ -154,3 +148,20 @@ func (k msgServer) CreateClaim( Claim: &claim, }, nil } + +// finalizeCreateClaimTelemetry defers telemetry calls to be executed after business logic, +// incrementing counters based on whether a new claim was handled successfully. +// Meant to run deferred. +func (k msgServer) finalizeCreateClaimTelemetry(session *sessiontypes.Session, msg *types.MsgCreateClaim, isExistingClaim bool, numRelays, numClaimComputeUnits uint64, err error) { + // Only increment these metrics counters if handling a new claim. + if !isExistingClaim { + serviceId := session.Header.ServiceId + applicationAddress := session.Header.ApplicationAddress + supplierOperatorAddress := msg.GetSupplierOperatorAddress() + claimProofStage := types.ClaimProofStage_CLAIMED.String() + + telemetry.ClaimCounter(claimProofStage, 1, serviceId, applicationAddress, supplierOperatorAddress, err) + telemetry.ClaimRelaysCounter(claimProofStage, numRelays, serviceId, applicationAddress, supplierOperatorAddress, err) + telemetry.ClaimComputeUnitsCounter(claimProofStage, numClaimComputeUnits, serviceId, applicationAddress, supplierOperatorAddress, err) + } +} diff --git a/x/proof/keeper/msg_server_submit_proof.go b/x/proof/keeper/msg_server_submit_proof.go index 6496a3f30..c19fbd2e6 100644 --- a/x/proof/keeper/msg_server_submit_proof.go +++ b/x/proof/keeper/msg_server_submit_proof.go @@ -16,6 +16,7 @@ import ( "github.com/pokt-network/poktroll/telemetry" "github.com/pokt-network/poktroll/x/proof/types" servicekeeper "github.com/pokt-network/poktroll/x/service/keeper" + sessiontypes "github.com/pokt-network/poktroll/x/session/types" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" ) @@ -47,16 +48,6 @@ func (k msgServer) SubmitProof( numClaimComputeUnits uint64 ) - // Defer telemetry calls so that they reference the final values the relevant variables. - defer func() { - // Only increment these metrics counters if handling a new claim. - if !isExistingProof { - telemetry.ClaimCounter(types.ClaimProofStage_PROVEN, 1, err) - telemetry.ClaimRelaysCounter(types.ClaimProofStage_PROVEN, numRelays, err) - telemetry.ClaimComputeUnitsCounter(types.ClaimProofStage_PROVEN, numClaimComputeUnits, err) - } - }() - logger := k.Logger().With("method", "SubmitProof") sdkCtx := cosmostypes.UnwrapSDKContext(ctx) logger.Info("About to start submitting proof") @@ -73,6 +64,9 @@ func (k msgServer) SubmitProof( return nil, status.Error(codes.InvalidArgument, err.Error()) } + // Defer telemetry calls so that they reference the final values the relevant variables. + defer k.finalizeSubmitProofTelemetry(session, msg, isExistingProof, numRelays, numClaimComputeUnits, err) + if err = k.deductProofSubmissionFee(ctx, msg.GetSupplierOperatorAddress()); err != nil { logger.Error(fmt.Sprintf("failed to deduct proof submission fee: %v", err)) return nil, status.Error(codes.FailedPrecondition, err.Error()) @@ -219,9 +213,7 @@ func (k Keeper) ProofRequirementForClaim(ctx context.Context, claim *types.Claim var requirementReason = types.ProofRequirementReason_NOT_REQUIRED // Defer telemetry calls so that they reference the final values the relevant variables. - defer func() { - telemetry.ProofRequirementCounter(requirementReason, err) - }() + defer k.finalizeProofRequirementTelemetry(requirementReason, claim, err) proofParams := k.GetParams(ctx) sharedParams := k.sharedKeeper.GetParams(ctx) @@ -322,3 +314,30 @@ func (k Keeper) getProofRequirementSeedBlockHash( // the block that is before the earliest block at which a proof can be committed. return k.sessionKeeper.GetBlockHash(ctx, earliestSupplierProofCommitHeight-1), nil } + +// finalizeSubmitProofTelemetry finalizes telemetry updates for SubmitProof, incrementing counters as needed. +// Meant to run deferred. +func (k msgServer) finalizeSubmitProofTelemetry(session *sessiontypes.Session, msg *types.MsgSubmitProof, isExistingProof bool, numRelays, numClaimComputeUnits uint64, err error) { + if !isExistingProof { + serviceId := session.Header.ServiceId + applicationAddress := session.Header.ApplicationAddress + supplierOperatorAddress := msg.GetSupplierOperatorAddress() + claimProofStage := types.ClaimProofStage_PROVEN.String() + + telemetry.ClaimCounter(claimProofStage, 1, serviceId, applicationAddress, supplierOperatorAddress, err) + telemetry.ClaimRelaysCounter(claimProofStage, numRelays, serviceId, applicationAddress, supplierOperatorAddress, err) + telemetry.ClaimComputeUnitsCounter(claimProofStage, numClaimComputeUnits, serviceId, applicationAddress, supplierOperatorAddress, err) + } +} + +// finalizeProofRequirementTelemetry finalizes telemetry updates for proof requirements. +// Meant to run deferred. +func (k Keeper) finalizeProofRequirementTelemetry(requirementReason types.ProofRequirementReason, claim *types.Claim, err error) { + telemetry.ProofRequirementCounter( + requirementReason.String(), + claim.SessionHeader.ServiceId, + claim.SessionHeader.ApplicationAddress, + claim.SupplierOperatorAddress, + err, + ) +} diff --git a/x/proof/keeper/proof_validation.go b/x/proof/keeper/proof_validation.go index 614c5cf03..778d66d8c 100644 --- a/x/proof/keeper/proof_validation.go +++ b/x/proof/keeper/proof_validation.go @@ -32,9 +32,11 @@ import ( "bytes" "context" + cosmostelemetry "github.com/cosmos/cosmos-sdk/telemetry" "github.com/pokt-network/smt" "github.com/pokt-network/poktroll/pkg/crypto/protocol" + "github.com/pokt-network/poktroll/telemetry" "github.com/pokt-network/poktroll/x/proof/types" servicekeeper "github.com/pokt-network/poktroll/x/service/keeper" servicetypes "github.com/pokt-network/poktroll/x/service/types" @@ -59,6 +61,9 @@ func (k Keeper) EnsureValidProof( ctx context.Context, proof *types.Proof, ) error { + // Telemetry: measure execution time. + defer cosmostelemetry.MeasureSince(cosmostelemetry.Now(), telemetry.MetricNameKeys("proof", "validation")...) + logger := k.Logger().With("method", "ValidateProof") // Retrieve the supplier operator's public key. diff --git a/x/session/keeper/query_get_session.go b/x/session/keeper/query_get_session.go index 166c77d37..bc25fff0e 100644 --- a/x/session/keeper/query_get_session.go +++ b/x/session/keeper/query_get_session.go @@ -36,7 +36,7 @@ func (k Keeper) GetSession(ctx context.Context, req *types.QueryGetSessionReques blockHeight = req.BlockHeight } - k.Logger().Info(fmt.Sprintf("Getting session for height: %d", blockHeight)) + k.Logger().Debug(fmt.Sprintf("Getting session for height: %d", blockHeight)) sessionHydrator := NewSessionHydrator(req.ApplicationAddress, req.ServiceId, blockHeight) session, err := k.HydrateSession(ctx, sessionHydrator) diff --git a/x/session/keeper/session_hydrator.go b/x/session/keeper/session_hydrator.go index 5f259aa78..8dae1a7a5 100644 --- a/x/session/keeper/session_hydrator.go +++ b/x/session/keeper/session_hydrator.go @@ -12,6 +12,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" _ "golang.org/x/crypto/sha3" + "github.com/pokt-network/poktroll/telemetry" "github.com/pokt-network/poktroll/x/session/types" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" ) @@ -66,22 +67,22 @@ func (k Keeper) HydrateSession(ctx context.Context, sh *sessionHydrator) (*types if err := k.hydrateSessionMetadata(ctx, sh); err != nil { return nil, err } - logger.Info("Finished hydrating session metadata") + logger.Debug("Finished hydrating session metadata") if err := k.hydrateSessionID(ctx, sh); err != nil { return nil, err } - logger.Info(fmt.Sprintf("Finished hydrating session ID: %s", sh.sessionHeader.SessionId)) + logger.Debug(fmt.Sprintf("Finished hydrating session ID: %s", sh.sessionHeader.SessionId)) if err := k.hydrateSessionApplication(ctx, sh); err != nil { return nil, err } - logger.Info(fmt.Sprintf("Finished hydrating session application: %+v", sh.session.Application)) + logger.Debug(fmt.Sprintf("Finished hydrating session application: %+v", sh.session.Application)) if err := k.hydrateSessionSuppliers(ctx, sh); err != nil { return nil, err } - logger.Info("Finished hydrating session suppliers") + logger.Debug("Finished hydrating session suppliers") sh.session.Header = sh.sessionHeader sh.session.SessionId = sh.sessionHeader.SessionId @@ -196,6 +197,8 @@ func (k Keeper) hydrateSessionSuppliers(ctx context.Context, sh *sessionHydrator } } + defer telemetry.SessionSuppliersGauge(len(candidateSuppliers), NumSupplierPerSession, sh.sessionHeader.ServiceId) + if len(candidateSuppliers) == 0 { logger.Error("[ERROR] no suppliers found for session") return types.ErrSessionSuppliersNotFound.Wrapf( @@ -206,7 +209,7 @@ func (k Keeper) hydrateSessionSuppliers(ctx context.Context, sh *sessionHydrator } if len(candidateSuppliers) < NumSupplierPerSession { - logger.Info(fmt.Sprintf( + logger.Debug(fmt.Sprintf( "Number of available suppliers (%d) is less than the maximum number of possible suppliers per session (%d)", len(candidateSuppliers), NumSupplierPerSession, diff --git a/x/supplier/module/abci.go b/x/supplier/module/abci.go index 095e33501..f448fd5f0 100644 --- a/x/supplier/module/abci.go +++ b/x/supplier/module/abci.go @@ -3,11 +3,16 @@ package supplier import ( sdk "github.com/cosmos/cosmos-sdk/types" + cosmostelemetry "github.com/cosmos/cosmos-sdk/telemetry" "github.com/pokt-network/poktroll/x/supplier/keeper" + "github.com/pokt-network/poktroll/x/supplier/types" ) // EndBlocker is called every block and handles supplier related updates. func EndBlocker(ctx sdk.Context, k keeper.Keeper) error { + // Telemetry: measure the end-block execution time following standard cosmos-sdk practices. + defer cosmostelemetry.ModuleMeasureSince(types.ModuleName, cosmostelemetry.Now(), cosmostelemetry.MetricKeyEndBlocker) + // TODO_IMPROVE: Add logs and/or telemetry on the number of unbonded suppliers. if err := k.EndBlockerUnbondSuppliers(ctx); err != nil { return err diff --git a/x/tokenomics/keeper/settle_pending_claims.go b/x/tokenomics/keeper/settle_pending_claims.go index 37a48b3f2..7555563a4 100644 --- a/x/tokenomics/keeper/settle_pending_claims.go +++ b/x/tokenomics/keeper/settle_pending_claims.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/query" "github.com/pokt-network/poktroll/app/volatile" + "github.com/pokt-network/poktroll/telemetry" apptypes "github.com/pokt-network/poktroll/x/application/types" prooftypes "github.com/pokt-network/poktroll/x/proof/types" servicekeeper "github.com/pokt-network/poktroll/x/service/keeper" @@ -179,6 +180,18 @@ func (k Keeper) SettlePendingClaims(ctx sdk.Context) ( expiredResult.NumClaims++ expiredResult.NumRelays += numClaimRelays expiredResult.NumComputeUnits += numClaimComputeUnits + + // Telemetry - defer telemetry calls so that they reference the final values the relevant variables. + defer k.finalizeTelemetry( + prooftypes.ClaimProofStage_EXPIRED, + claim.SessionHeader.ServiceId, + claim.SessionHeader.ApplicationAddress, + claim.SupplierOperatorAddress, + numClaimRelays, + numClaimComputeUnits, + err, + ) + continue } } @@ -238,7 +251,18 @@ func (k Keeper) SettlePendingClaims(ctx sdk.Context) ( settledResult.NumComputeUnits += numClaimComputeUnits settledResult.RelaysPerServiceMap[claim.SessionHeader.ServiceId] += numClaimRelays - logger.Info(fmt.Sprintf("Successfully settled claim for session ID %q at block height %d", claim.SessionHeader.SessionId, blockHeight)) + logger.Debug(fmt.Sprintf("Successfully settled claim for session ID %q at block height %d", claim.SessionHeader.SessionId, blockHeight)) + + // Telemetry - defer telemetry calls so that they reference the final values the relevant variables. + defer k.finalizeTelemetry( + prooftypes.ClaimProofStage_SETTLED, + claim.SessionHeader.ServiceId, + claim.SessionHeader.ApplicationAddress, + claim.SupplierOperatorAddress, + numClaimRelays, + numClaimComputeUnits, + err, + ) } // Slash all the suppliers that have been marked for slashing slashingCount times. @@ -358,6 +382,11 @@ func (k Keeper) slashSupplierStake( return err } + // Update telemetry information + if totalSlashingCoin.Amount.IsInt64() { + defer telemetry.SlashedTokensFromModule(suppliertypes.ModuleName, float32(totalSlashingCoin.Amount.Int64())) + } + supplierToSlash.Stake = &remainingStakeCoin logger.Info(fmt.Sprintf( @@ -447,3 +476,19 @@ func (k Keeper) getApplicationInitialStakeMap( return applicationInitialStakeMap, nil } + +// finalizeTelemetry logs telemetry metrics for a claim based on its stage (e.g., EXPIRED, SETTLED). +// Meant to run deferred. +func (k Keeper) finalizeTelemetry( + claimProofStage prooftypes.ClaimProofStage, + serviceId string, + applicationAddress string, + supplierOperatorAddress string, + numRelays uint64, + numClaimComputeUnits uint64, + err error, +) { + telemetry.ClaimCounter(claimProofStage.String(), 1, serviceId, applicationAddress, supplierOperatorAddress, err) + telemetry.ClaimRelaysCounter(claimProofStage.String(), numRelays, serviceId, applicationAddress, supplierOperatorAddress, err) + telemetry.ClaimComputeUnitsCounter(claimProofStage.String(), numClaimComputeUnits, serviceId, applicationAddress, supplierOperatorAddress, err) +} diff --git a/x/tokenomics/keeper/token_logic_modules.go b/x/tokenomics/keeper/token_logic_modules.go index 3dba9136a..f6bad19d5 100644 --- a/x/tokenomics/keeper/token_logic_modules.go +++ b/x/tokenomics/keeper/token_logic_modules.go @@ -376,7 +376,13 @@ func (k Keeper) TokenLogicModuleRelayBurnEqualsMint( err, ) } - logger.Info(fmt.Sprintf("minted (%v) coins in the supplier module", settlementCoin)) + + // Update telemetry information + if settlementCoin.Amount.IsInt64() { + defer telemetry.MintedTokensFromModule(suppliertypes.ModuleName, float32(settlementCoin.Amount.Int64())) + } + + logger.Debug(fmt.Sprintf("minted (%v) coins in the supplier module", settlementCoin)) // Distribute the rewards to the supplier's shareholders based on the rev share percentage. if err := k.distributeSupplierRewardsToShareHolders(ctx, supplier, service.Id, settlementCoin.Amount.Uint64()); err != nil { @@ -386,7 +392,7 @@ func (k Keeper) TokenLogicModuleRelayBurnEqualsMint( err, ) } - logger.Info(fmt.Sprintf("sent (%v) from the supplier module to the supplier account with address %q", settlementCoin, supplier.OperatorAddress)) + logger.Debug(fmt.Sprintf("sent (%v) from the supplier module to the supplier account with address %q", settlementCoin, supplier.OperatorAddress)) // Burn uPOKT from the application module account which was held in escrow // on behalf of the application account. @@ -395,7 +401,13 @@ func (k Keeper) TokenLogicModuleRelayBurnEqualsMint( ); err != nil { return tokenomicstypes.ErrTokenomicsApplicationModuleBurn.Wrapf("burning %s from the application module account: %v", settlementCoin, err) } - logger.Info(fmt.Sprintf("burned (%v) from the application module account", settlementCoin)) + + // Update telemetry information + if settlementCoin.Amount.IsInt64() { + defer telemetry.BurnedTokensFromModule(apptypes.ModuleName, float32(settlementCoin.Amount.Int64())) + } + + logger.Debug(fmt.Sprintf("burned (%v) from the application module account", settlementCoin)) // Update the application's on-chain stake newAppStake, err := application.Stake.SafeSub(settlementCoin) @@ -403,7 +415,7 @@ func (k Keeper) TokenLogicModuleRelayBurnEqualsMint( return tokenomicstypes.ErrTokenomicsApplicationNewStakeInvalid.Wrapf("application %q stake cannot be reduced to a negative amount %v", application.Address, newAppStake) } application.Stake = &newAppStake - logger.Info(fmt.Sprintf("updated application %q stake to %v", application.Address, newAppStake)) + logger.Debug(fmt.Sprintf("updated application %q stake to %v", application.Address, newAppStake)) return nil } @@ -436,6 +448,12 @@ func (k Keeper) TokenLogicModuleGlobalMint( return tokenomicstypes.ErrTokenomicsModuleMintFailed.Wrapf( "minting (%s) to the tokenomics module account: %v", newMintCoin, err) } + + // Update telemetry information + if newMintCoin.Amount.IsInt64() { + defer telemetry.MintedTokensFromModule(tokenomicstypes.ModuleName, float32(newMintCoin.Amount.Int64())) + } + logger.Info(fmt.Sprintf("minted (%s) to the tokenomics module account", newMintCoin)) // Send a portion of the rewards to the application diff --git a/x/tokenomics/module/abci.go b/x/tokenomics/module/abci.go index 8140263c9..fc0776c68 100644 --- a/x/tokenomics/module/abci.go +++ b/x/tokenomics/module/abci.go @@ -3,16 +3,20 @@ package tokenomics import ( "fmt" + cosmostelemetry "github.com/cosmos/cosmos-sdk/telemetry" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/pokt-network/poktroll/pkg/crypto/protocol" "github.com/pokt-network/poktroll/telemetry" - prooftypes "github.com/pokt-network/poktroll/x/proof/types" "github.com/pokt-network/poktroll/x/tokenomics/keeper" + "github.com/pokt-network/poktroll/x/tokenomics/types" ) // EndBlocker called at every block and settles all pending claims. func EndBlocker(ctx sdk.Context, k keeper.Keeper) (err error) { + // Telemetry: measure the end-block execution time following standard cosmos-sdk practices. + defer cosmostelemetry.ModuleMeasureSince(types.ModuleName, cosmostelemetry.Now(), cosmostelemetry.MetricKeyEndBlocker) + logger := k.Logger().With("method", "EndBlocker") // NB: There are two main reasons why we settle expiring claims in the end @@ -33,42 +37,6 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) (err error) { expiredResult.NumClaims, )) - // Telemetry - defer telemetry calls so that they reference the final values the relevant variables. - defer func() { - telemetry.ClaimCounter( - prooftypes.ClaimProofStage_SETTLED, - settledResult.NumClaims, - err, - ) - telemetry.ClaimRelaysCounter( - prooftypes.ClaimProofStage_SETTLED, - settledResult.NumRelays, - err, - ) - telemetry.ClaimComputeUnitsCounter( - prooftypes.ClaimProofStage_SETTLED, - settledResult.NumComputeUnits, - err, - ) - - telemetry.ClaimCounter( - prooftypes.ClaimProofStage_EXPIRED, - expiredResult.NumClaims, - err, - ) - telemetry.ClaimRelaysCounter( - prooftypes.ClaimProofStage_EXPIRED, - expiredResult.NumRelays, - err, - ) - telemetry.ClaimComputeUnitsCounter( - prooftypes.ClaimProofStage_EXPIRED, - expiredResult.NumComputeUnits, - err, - ) - // TODO_POST_MAINNET: Add a counter for expired compute units. - }() - // Update the relay mining difficulty for every service that settled pending // claims based on how many estimated relays were serviced for it. difficultyPerServiceMap, err := k.UpdateRelayMiningDifficulty(ctx, settledResult.RelaysPerServiceMap) diff --git a/x/tokenomics/types/event.pb.go b/x/tokenomics/types/event.pb.go index 8570fd911..5e69f719f 100644 --- a/x/tokenomics/types/event.pb.go +++ b/x/tokenomics/types/event.pb.go @@ -370,7 +370,7 @@ func (m *EventSupplierSlashed) GetSlashingAmount() *types1.Coin { } // EventApplicationReimbursementRequest is emitted when an application requests -// a reimbursement +// a reimbursement. type EventApplicationReimbursementRequest struct { ApplicationAddr string `protobuf:"bytes,1,opt,name=application_addr,json=applicationAddr,proto3" json:"application_addr,omitempty"` SupplierOperatorAddr string `protobuf:"bytes,2,opt,name=supplier_operator_addr,json=supplierOperatorAddr,proto3" json:"supplier_operator_addr,omitempty"`