Skip to content

Commit

Permalink
[Tokenomics] Implement difficulty proportional rewards (#880)
Browse files Browse the repository at this point in the history
**This is a repost of PR #840 which did not get merged into main**

## Summary

This PR incorporated the mining difficulty into the claim reward
calculation.
* Encapsulates the claimed tokens into a `claim.GetClaimeduPOKT(params,
difficulty)`
* Implements a test to assert that the difficulty based rewards are
proportional to the off-chain relays served.
* Removes unused `min_relay_difficulty_bits` gov. param.

It is based on the preparation work of PR #836.

## Issue

- #781 
- #758 

## Type of change

Select one or more from the following:

- [x] New feature, functionality or library
- [ ] Consensus breaking; add the `consensus-breaking` label if so. See
#791 for details
- [ ] Bug fix
- [ ] Code health or cleanup
- [ ] Documentation
- [ ] Other (specify)

## Testing

- [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
  • Loading branch information
red-0ne authored Oct 14, 2024
1 parent b92c203 commit ac48a56
Show file tree
Hide file tree
Showing 35 changed files with 1,068 additions and 784 deletions.
393 changes: 194 additions & 199 deletions api/poktroll/proof/event.pulsar.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions api/poktroll/service/relay_mining_difficulty.pulsar.go

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

296 changes: 147 additions & 149 deletions api/poktroll/tokenomics/event.pulsar.go

Large diffs are not rendered by default.

14 changes: 12 additions & 2 deletions docusaurus/docs/develop/developer_guide/adding_params.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,19 @@ with the default value for the new parameter.
"@type": "/poktroll.proof.MsgUpdateParams",
"authority": "pokt10d07y265gmmuvt4z0w9aw880jnsr700j8yv32t",
"params": {
"min_relay_difficulty_bits": "0",
"proof_request_probability": "0.25",
"proof_requirement_threshold": "20",
"proof_requirement_threshold": {
"denom": "upokt",
"amount": "20000000"
},
"proof_missing_penalty": {
"amount": "320000000",
"denom": "upokt"
},
"proof_submission_fee": {
"amount": "1000000",
"denom": "upokt"
},
"new_parameter_name": "100" // Add this line
}
}
Expand Down
4 changes: 0 additions & 4 deletions makefiles/params.mk
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ params_get_proof: ## Get the proof module params
params_update_proof_all: ## Update the proof module params
poktrolld tx authz exec ./tools/scripts/params/proof_all.json $(PARAM_FLAGS)

.PHONY: params_update_proof_min_relay_difficulty_bits
params_update_proof_min_relay_difficulty_bits: ## Update the proof module min_relay_difficulty_bits param
poktrolld tx authz exec ./tools/scripts/params/proof_min_relay_difficulty_bits.json $(PARAM_FLAGS)

.PHONY: params_update_proof_proof_request_probability
params_update_proof_proof_request_probability: ## Update the proof module proof_request_probability param
poktrolld tx authz exec ./tools/scripts/params/proof_proof_request_probability.json $(PARAM_FLAGS)
Expand Down
2 changes: 1 addition & 1 deletion pkg/client/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ type ProofQueryClient interface {
type ServiceQueryClient interface {
// GetService queries the chain for the details of the service provided
GetService(ctx context.Context, serviceId string) (sharedtypes.Service, error)
GetServiceRelayDifficultyTargetHash(ctx context.Context, serviceId string) (servicetypes.RelayMiningDifficulty, error)
GetServiceRelayDifficulty(ctx context.Context, serviceId string) (servicetypes.RelayMiningDifficulty, error)
}

// BankQueryClient defines an interface that enables the querying of the
Expand Down
18 changes: 16 additions & 2 deletions pkg/client/query/servicequerier.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import (

"cosmossdk.io/depinject"
"github.com/cosmos/gogoproto/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

"github.com/pokt-network/poktroll/pkg/client"
"github.com/pokt-network/poktroll/pkg/crypto/protocol"
servicetypes "github.com/pokt-network/poktroll/x/service/types"
sharedtypes "github.com/pokt-network/poktroll/x/shared/types"
)
Expand Down Expand Up @@ -61,9 +64,9 @@ func (servq *serviceQuerier) GetService(
return res.Service, nil
}

// GetServiceRelayDifficultyTargetHash queries the onchain data for
// GetServiceRelayDifficulty queries the onchain data for
// the relay mining difficulty associated with the given service.
func (servq *serviceQuerier) GetServiceRelayDifficultyTargetHash(
func (servq *serviceQuerier) GetServiceRelayDifficulty(
ctx context.Context,
serviceId string,
) (servicetypes.RelayMiningDifficulty, error) {
Expand All @@ -72,8 +75,19 @@ func (servq *serviceQuerier) GetServiceRelayDifficultyTargetHash(
}

res, err := servq.serviceQuerier.RelayMiningDifficulty(ctx, req)
if status.Code(err) == codes.NotFound {
newServiceDifficulty := servicetypes.RelayMiningDifficulty{
ServiceId: serviceId,
BlockHeight: 0,
NumRelaysEma: 0,
TargetHash: protocol.BaseRelayDifficultyHashBz,
}

return newServiceDifficulty, nil
}
if err != nil {
return servicetypes.RelayMiningDifficulty{}, err
}

return res.RelayMiningDifficulty, nil
}
1 change: 0 additions & 1 deletion pkg/relayer/miner/gen/gen_fixtures.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ const (
defaultSvcID = "svc1"
)

// TODO_FOLLOWUP(@olshansk, #690): Do a global anycase grep for "DifficultyBits" and update/remove things appropriately.
var (
// flagDifficultyThresholdHashStr is the difficulty threshold hash, as a hex string, that a
// randomized, serialized relay must be greater than to be included in the
Expand Down
6 changes: 2 additions & 4 deletions pkg/relayer/miner/miner.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,9 @@ func (mnr *miner) getServiceRelayDifficultyTargetHash(ctx context.Context, req *
return nil, fmt.Errorf("invalid session header: %w", err)
}

serviceRelayDifficulty, err := mnr.serviceQueryClient.GetServiceRelayDifficultyTargetHash(ctx, sessionHeader.ServiceId)
serviceRelayDifficulty, err := mnr.serviceQueryClient.GetServiceRelayDifficulty(ctx, sessionHeader.ServiceId)
if err != nil {
// TODO_IMPROVE: log the error and a message saying the default relay difficulty target hash
// is being used.
return protocol.BaseRelayDifficultyHashBz, nil
return nil, err
}

return serviceRelayDifficulty.GetTargetHash(), nil
Expand Down
4 changes: 1 addition & 3 deletions pkg/relayer/miner/miner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,10 @@ func TestMiner_MinedRelays(t *testing.T) {
expectedMinedRelays = unmarshalHexMinedRelays(t, marshaledMinableRelaysHex)
)

proofQueryClientMock := testqueryclients.NewTestProofQueryClient(t)

testqueryclients.SetServiceRelayDifficultyTargetHash(t, testSvcId, testRelayMiningTargetHash)
serviceQueryClientMock := testqueryclients.NewTestServiceQueryClient(t)

deps := depinject.Supply(proofQueryClientMock, serviceQueryClientMock)
deps := depinject.Supply(serviceQueryClientMock)
mnr, err := miner.NewMiner(deps)
require.NoError(t, err)

Expand Down
10 changes: 6 additions & 4 deletions pkg/relayer/session/claim.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,10 +315,12 @@ func (rs *relayerSessionsManager) payableProofsSessionTrees(
).Warn().Msg("supplier operator cannot afford to submit proof for claim, skipping")
}

logger.Warn().Msgf(
"Supplier operator %q can only afford %d out of %d claims",
supplierOpeartorAddress, len(claimableSessionTrees), len(sessionTrees),
)
if len(claimableSessionTrees) < len(sessionTrees) {
logger.Warn().Msgf(
"Supplier operator %q can only afford %d out of %d claims",
supplierOpeartorAddress, len(claimableSessionTrees), len(sessionTrees),
)
}

return claimableSessionTrees, nil
}
12 changes: 6 additions & 6 deletions pkg/relayer/session/proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"github.com/pokt-network/poktroll/x/proof/types"
prooftypes "github.com/pokt-network/poktroll/x/proof/types"
"github.com/pokt-network/poktroll/x/shared"
tokenomics "github.com/pokt-network/poktroll/x/tokenomics"
)

// submitProofs maps over the given claimedSessions observable.
Expand Down Expand Up @@ -277,24 +276,25 @@ func (rs *relayerSessionsManager) isProofRequired(
// Create the claim object and use its methods to determine if a proof is required.
claim := claimFromSessionTree(sessionTree)

// Get the number of compute units accumulated through the given session.
numClaimComputeUnits, err := claim.GetNumClaimedComputeUnits()
proofParams, err := rs.proofQueryClient.GetParams(ctx)
if err != nil {
return false, err
}

proofParams, err := rs.proofQueryClient.GetParams(ctx)
sharedParams, err := rs.sharedQueryClient.GetParams(ctx)
if err != nil {
return false, err
}

sharedParams, err := rs.sharedQueryClient.GetParams(ctx)
// Retrieving the relay mining difficulty for the service at hand
serviceId := claim.GetSessionHeader().GetServiceId()
relayMiningDifficulty, err := rs.serviceQueryClient.GetServiceRelayDifficulty(ctx, serviceId)
if err != nil {
return false, err
}

// The amount of uPOKT being claimed.
claimedAmount, err := tokenomics.NumComputeUnitsToCoin(*sharedParams, numClaimComputeUnits)
claimedAmount, err := claim.GetClaimeduPOKT(*sharedParams, relayMiningDifficulty)
if err != nil {
return false, err
}
Expand Down
4 changes: 4 additions & 0 deletions pkg/relayer/session/session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ func requireProofCountEqualsExpectedValueFromProofParams(t *testing.T, proofPara
Id: "svc",
ComputeUnitsPerRelay: 2,
}

testqueryclients.SetServiceRelayDifficultyTargetHash(t, service.Id, protocol.BaseRelayDifficultyHashBz)
// Add the service to the existing services.
testqueryclients.AddToExistingServices(t, service)

Expand Down Expand Up @@ -157,12 +159,14 @@ func TestRelayerSessionsManager_InsufficientBalanceForProofSubmission(t *testing
ComputeUnitsPerRelay: 1,
}
testqueryclients.AddToExistingServices(t, lowCUPRService)
testqueryclients.SetServiceRelayDifficultyTargetHash(t, lowCUPRService.Id, protocol.BaseRelayDifficultyHashBz)

highCUPRService := sharedtypes.Service{
Id: "highCUPRService",
ComputeUnitsPerRelay: 2,
}
testqueryclients.AddToExistingServices(t, highCUPRService)
testqueryclients.SetServiceRelayDifficultyTargetHash(t, highCUPRService.Id, protocol.BaseRelayDifficultyHashBz)

lowCUPRServiceActiveSession := &sessiontypes.Session{
Header: &sessiontypes.SessionHeader{
Expand Down
8 changes: 4 additions & 4 deletions proto/poktroll/proof/event.proto
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ message EventClaimCreated {
uint64 num_relays = 2 [(gogoproto.jsontag) = "num_relays"];
uint64 num_claimed_compute_units = 4 [(gogoproto.jsontag) = "num_claimed_compute_units"];
uint64 num_estimated_compute_units = 5 [(gogoproto.jsontag) = "num_estimated_compute_units"];
cosmos.base.v1beta1.Coin claimed_amount_upokt = 6 [(gogoproto.jsontag) = "claimed_amount_upokt"];
cosmos.base.v1beta1.Coin claimed_upokt = 6 [(gogoproto.jsontag) = "claimed_upokt"];
}

// TODO_TEST: Add coverage for claim updates.
Expand All @@ -22,7 +22,7 @@ message EventClaimUpdated {
uint64 num_relays = 2 [(gogoproto.jsontag) = "num_relays"];
uint64 num_claimed_compute_units = 4 [(gogoproto.jsontag) = "num_claimed_compute_units"];
uint64 num_estimated_compute_units = 5 [(gogoproto.jsontag) = "num_estimated_compute_units"];
cosmos.base.v1beta1.Coin claimed_amount_upokt = 6 [(gogoproto.jsontag) = "claimed_amount_upokt"];
cosmos.base.v1beta1.Coin claimed_upokt = 6 [(gogoproto.jsontag) = "claimed_upokt"];
}

message EventProofSubmitted {
Expand All @@ -31,7 +31,7 @@ message EventProofSubmitted {
uint64 num_relays = 3 [(gogoproto.jsontag) = "num_relays"];
uint64 num_claimed_compute_units = 4 [(gogoproto.jsontag) = "num_claimed_compute_units"];
uint64 num_estimated_compute_units = 5 [(gogoproto.jsontag) = "num_estimated_compute_units"];
cosmos.base.v1beta1.Coin claimed_amount_upokt = 6 [(gogoproto.jsontag) = "claimed_amount_upokt"];
cosmos.base.v1beta1.Coin claimed_upokt = 6 [(gogoproto.jsontag) = "claimed_upokt"];
}

// TODO_TEST: Add coverage for proof updates.
Expand All @@ -41,5 +41,5 @@ message EventProofUpdated {
uint64 num_relays = 3 [(gogoproto.jsontag) = "num_relays"];
uint64 num_claimed_compute_units = 4 [(gogoproto.jsontag) = "num_claimed_compute_units"];
uint64 num_estimated_compute_units = 5 [(gogoproto.jsontag) = "num_estimated_compute_units"];
cosmos.base.v1beta1.Coin claimed_amount_upokt = 6 [(gogoproto.jsontag) = "claimed_amount_upokt"];
cosmos.base.v1beta1.Coin claimed_upokt = 6 [(gogoproto.jsontag) = "claimed_upokt"];
}
1 change: 1 addition & 0 deletions proto/poktroll/service/relay_mining_difficulty.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import "gogoproto/gogo.proto";

// RelayMiningDifficulty is a message used to store the on-chain Relay Mining
// difficulty associated with a specific service ID.
// TODO_TECHDEBT: Embed this message in the Service message.
message RelayMiningDifficulty {
// The service ID the relay mining difficulty is associated with.
string service_id = 1;
Expand Down
8 changes: 4 additions & 4 deletions proto/poktroll/tokenomics/event.proto
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ message EventClaimExpired {
// Number of estimated compute units claimed as a function of the number of claimed
// compute units and the relay difficulty multiplier for the particular service.
uint64 num_estimated_compute_units = 5 [(gogoproto.jsontag) = "num_estimated_compute_units"];
// The amount of uPOKT claimed to be rewarded for the work done as a function of
// The uPOKT coin claimed to be rewarded for the work done as a function of
// the number of estimated compute units and the compute uints to token multiplier.
cosmos.base.v1beta1.Coin claimed_amount_upokt = 6 [(gogoproto.jsontag) = "claimed_amount_upokt"];
cosmos.base.v1beta1.Coin claimed_upokt = 6 [(gogoproto.jsontag) = "claimed_upokt"];
}

// EventClaimSettled is an event emitted whenever a claim is settled.
Expand All @@ -48,9 +48,9 @@ message EventClaimSettled {
// Number of estimated compute units claimed as a function of the number of claimed
// compute units and the relay difficulty multiplier for the particular service.
uint64 num_estimated_compute_units = 5 [(gogoproto.jsontag) = "num_estimated_compute_units"];
// The amount of uPOKT claimed to be rewarded for the work done as a function of
// The uPOKT coin claimed to be rewarded for the work done as a function of
// the number of estimated compute units and the compute uints to token multiplier.
cosmos.base.v1beta1.Coin claimed_amount_upokt = 6 [(gogoproto.jsontag) = "claimed_amount_upokt"];
cosmos.base.v1beta1.Coin claimed_upokt = 6 [(gogoproto.jsontag) = "claimed_upokt"];
}

// EventApplicationOverserviced is emitted when an application has less stake than
Expand Down
32 changes: 32 additions & 0 deletions tests/integration/service/relay_mining_difficulty_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ package integration_test

import (
"context"
"math"
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/pokt-network/smt"
"github.com/pokt-network/smt/kvstore/pebble"
"github.com/stretchr/testify/require"

"github.com/pokt-network/poktroll/app/volatile"
"github.com/pokt-network/poktroll/cmd/poktrolld/cmd"
"github.com/pokt-network/poktroll/pkg/crypto/protocol"
testutilevents "github.com/pokt-network/poktroll/testutil/events"
Expand Down Expand Up @@ -38,6 +41,20 @@ func TestUpdateRelayMiningDifficulty_NewServiceSeenForTheFirstTime(t *testing.T)
// Get the current session and shared params
session := getSession(t, integrationApp)
sharedParams := getSharedParams(t, integrationApp)
proofParams := getProofParams(t, integrationApp)

// Update the proof parameters to never require a proof, since this test is not
// submitting any proofs.
maxProofRequirementThreshold := sdk.NewInt64Coin(volatile.DenomuPOKT, math.MaxInt64)
proofParams.ProofRequirementThreshold = &maxProofRequirementThreshold
proofParams.ProofRequestProbability = 0

msgProofParams := prooftypes.MsgUpdateParams{
Authority: integrationApp.GetAuthority(),
Params: proofParams,
}
_, err := integrationApp.RunMsg(t, &msgProofParams)
require.NoError(t, err)

// Prepare the trie with several mined relays
expectedNumRelays := uint64(100)
Expand Down Expand Up @@ -138,6 +155,21 @@ func getSharedParams(t *testing.T, integrationApp *testutil.App) sharedtypes.Par
return sharedQueryRes.Params
}

// getProofParams returns the proof parameters for the current block height.
func getProofParams(t *testing.T, integrationApp *testutil.App) prooftypes.Params {
t.Helper()

sdkCtx := integrationApp.GetSdkCtx()

proofQueryClient := prooftypes.NewQueryClient(integrationApp.QueryHelper())
proofParamsReq := prooftypes.QueryParamsRequest{}

proofQueryRes, err := proofQueryClient.Params(sdkCtx, &proofParamsReq)
require.NoError(t, err)

return proofQueryRes.Params
}

// getSession returns the current session for the default application and service.
func getSession(t *testing.T, integrationApp *testutil.App) *sessiontypes.Session {
t.Helper()
Expand Down
Loading

0 comments on commit ac48a56

Please sign in to comment.