Skip to content

Commit

Permalink
[Relay Mining] Use per-service difficulty in the relayer (#745)
Browse files Browse the repository at this point in the history
<!-- README: DELETE THIS COMMENT BLOCK after:
    5. Specify _Epic_ and _Iteration_ under _Project_
-->

## Summary

- Relayer is updated to query the tokenmoics module to get the relay
difficulty target hash specific to the service corresponding to the
relay. This is used to determine if a relay is volume applicable.

- Relayer is updated to query the service module to get the compute
units per relay specific to the service corresponding to the relay. This
is used as the weight of the relay when updating the Relayer's SMT for
the session corresponding to the relay.

- Claims are validated at the time of submission to ensure the total
claimed compute units is equal to the number of relays multiplied by the
compute units per relay for the corresponding service.

- All #705 references in the code have been addressed.

- Relay test fixture generator has been updated to use the difficulty
threshold hash to be consistent with how the relayer now operates.

## Issue

- Relayer should use a service-specific difficulty target hash.
- Relayer should use the service-specific ComputeUnitsPerRelay when
adding a relay to the SMT for claiming.

- #705

## UPNEXT 
- Remove the relay_difficulty_target_hash parameter
- Addressing any remaining instances of `TODO_FOLLOWUP(@Olshansk, #690)`

These have been skipped to: 1) align on the PR before making further
changes and 2) restrict the PR size and scope, as these were not
strictly required for the above enhancements to function.

Depending on the review results, I can add commits to address the above
in this PR as well.

## Type of change

Select one or more:

- [x] New feature, functionality or library
- [ ] Bug fix
- [x] Code health or cleanup
- [ ] Documentation
- [ ] Other (specify)

## Testing

**Documentation changes** (only if making doc changes)
- [ ] `make docusaurus_start`; only needed if you make doc changes

**Local Testing** (only if making code changes)
- [x] **Unit Tests**: `make go_develop_and_test`
- [ ] **LocalNet E2E Tests**: `make test_e2e`
- See [quickstart
guide](https://dev.poktroll.com/developer_guide/quickstart) for
instructions

**PR Testing** (only if making code changes)
- [ ] **DevNet E2E Tests**: Add the `devnet-test-e2e` label to the PR.
- **THIS IS VERY EXPENSIVE**, so only do it after all the reviews are
complete.
- Optionally run `make trigger_ci` if you want to re-trigger tests
without any code changes
- If tests fail, try re-running failed tests only using the GitHub UI as
shown
[here](https://github.com/pokt-network/poktroll/assets/1892194/607984e9-0615-4569-9452-4c730190c1d2)


## 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
- [x] I create and reference any new tickets, if applicable
- [x] I have left TODOs throughout the codebase, if applicable


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Added new interfaces for querying tokenomics data, enhancing the app's
ability to handle tokenomics-related queries.
- Introduced a structured approach to query service information and
tokenomics data, improving the overall querying functionality.
- Implemented functionality to retrieve compute units per relay for
services, optimizing session management.
  
- **Bug Fixes**
- Improved error handling for service retrieval and compute units
mismatch scenarios.

- **Tests**
- Enhanced test coverage for tokenomics and service querying
functionalities, ensuring robust testing of new features.

- **Chores**
- Updated test utilities and dependencies to support new service
management capabilities.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Bryan White <[email protected]>
Co-authored-by: Daniel Olshansky <[email protected]>
  • Loading branch information
3 people authored Sep 5, 2024
1 parent ff05ce6 commit 1556a8f
Show file tree
Hide file tree
Showing 29 changed files with 731 additions and 133 deletions.
10 changes: 9 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ test_verbose: check_go_version ## Run all go tests verbosely
# It is not compatible with `-race`, which is why it's omitted here.
# See ref for more details: https://github.com/golang/go/issues/54482#issuecomment-1251124908
.PHONY: test_all
test_all: warn_flaky_tests check_go_version ## Run all go tests showing detailed output only on failures
test_all: warn_flaky_tests check_go_version test_gen_fixtures ## Run all go tests showing detailed output only on failures
go test -count=1 -buildmode=pie -tags test ./...

.PHONY: test_all_with_integration
Expand All @@ -466,6 +466,14 @@ test_integration: check_go_version ## Run only the in-memory integration "unit"
itest: check_go_version ## Run tests iteratively (see usage for more)
./tools/scripts/itest.sh $(filter-out $@,$(MAKECMDGOALS))

# Verify there are no compile errors in pkg/relayer/miner/gen directory.
# This is done by overriding the build tags through passing a `*.go` argument to `go test`.
# .go files in that directory contain a `go:build ignore` directive to avoid introducing
# unintentional churn in the randomly generated fixtures.
.PHONY: test_gen_fixtures
test_gen_fixtures: check_go_version ## Run all go tests verbosely
go test -count=1 -v -race ./pkg/relayer/miner/gen/*.go

.PHONY: go_mockgen
go_mockgen: ## Use `mockgen` to generate mocks used for testing purposes of all the modules.
find . -name "*_mock.go" | xargs --no-run-if-empty rm
Expand Down
20 changes: 19 additions & 1 deletion pkg/client/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
//go:generate mockgen -destination=../../testutil/mockclient/session_query_client_mock.go -package=mockclient . SessionQueryClient
//go:generate mockgen -destination=../../testutil/mockclient/shared_query_client_mock.go -package=mockclient . SharedQueryClient
//go:generate mockgen -destination=../../testutil/mockclient/proof_query_client_mock.go -package=mockclient . ProofQueryClient
//go:generate mockgen -destination=../../testutil/mockclient/tokenomics_query_client_mock.go -package=mockclient . TokenomicsQueryClient
//go:generate mockgen -destination=../../testutil/mockclient/service_query_client_mock.go -package=mockclient . ServiceQueryClient
//go:generate mockgen -destination=../../testutil/mockclient/cosmos_tx_builder_mock.go -package=mockclient github.com/cosmos/cosmos-sdk/client TxBuilder
//go:generate mockgen -destination=../../testutil/mockclient/cosmos_keyring_mock.go -package=mockclient github.com/cosmos/cosmos-sdk/crypto/keyring Keyring
//go:generate mockgen -destination=../../testutil/mockclient/cosmos_client_mock.go -package=mockclient github.com/cosmos/cosmos-sdk/client AccountRetriever
Expand Down Expand Up @@ -335,7 +337,6 @@ type BlockQueryClient interface {
// protobuf message. Since the generated go types don't include interface types, this
// is necessary to prevent dependency cycles.
type ProofParams interface {
GetRelayDifficultyTargetHash() []byte
GetProofRequestProbability() float32
GetProofRequirementThreshold() uint64
GetProofMissingPenalty() *cosmostypes.Coin
Expand All @@ -347,3 +348,20 @@ type ProofQueryClient interface {
// GetParams queries the chain for the current shared module parameters.
GetParams(ctx context.Context) (ProofParams, error)
}

// TokenomicsRelayMiningDifficulty is a go interface type which corresponding to the poktroll.tokenomics.RelayMiningDifficulty
// protobuf message. This is necessary to prevent dependency cycles.
type TokenomicsRelayMiningDifficulty interface {
GetTargetHash() []byte
}

type TokenomicsQueryClient interface {
GetServiceRelayDifficultyTargetHash(ctx context.Context, serviceId string) (TokenomicsRelayMiningDifficulty, error)
}

// ServiceQueryClient defines an interface that enables the querying of the
// on-chain service information
type ServiceQueryClient interface {
// GetService queries the chain for the details of the service provided
GetService(ctx context.Context, serviceId string) (sharedtypes.Service, error)
}
1 change: 1 addition & 0 deletions pkg/client/query/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ var (
ErrQueryRetrieveSession = sdkerrors.Register(codespace, 3, "error while trying to retrieve a session")
ErrQueryPubKeyNotFound = sdkerrors.Register(codespace, 4, "account pub key not found")
ErrQuerySessionParams = sdkerrors.Register(codespace, 5, "unable to query session params")
ErrQueryRetrieveService = sdkerrors.Register(codespace, 6, "error while trying to retrieve a service")
)
62 changes: 62 additions & 0 deletions pkg/client/query/servicequerier.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package query

import (
"context"

"cosmossdk.io/depinject"
"github.com/cosmos/gogoproto/grpc"

"github.com/pokt-network/poktroll/pkg/client"
servicetypes "github.com/pokt-network/poktroll/x/service/types"
sharedtypes "github.com/pokt-network/poktroll/x/shared/types"
)

var _ client.ServiceQueryClient = (*serviceQuerier)(nil)

// serviceQuerier is a wrapper around the servicetypes.QueryClient that enables the
// querying of on-chain service information through a single exposed method
// which returns a sharedtypes.Service struct
type serviceQuerier struct {
clientConn grpc.ClientConn
serviceQuerier servicetypes.QueryClient
}

// NewServiceQuerier returns a new instance of a client.ServiceQueryClient by
// injecting the dependecies provided by the depinject.Config.
//
// Required dependencies:
// - clientCtx (grpc.ClientConn)
func NewServiceQuerier(deps depinject.Config) (client.ServiceQueryClient, error) {
servq := &serviceQuerier{}

if err := depinject.Inject(
deps,
&servq.clientConn,
); err != nil {
return nil, err
}

servq.serviceQuerier = servicetypes.NewQueryClient(servq.clientConn)

return servq, nil
}

// GetService returns a sharedtypes.Service struct for a given serviceId.
// It implements the ServiceQueryClient#GetService function.
func (servq *serviceQuerier) GetService(
ctx context.Context,
serviceId string,
) (sharedtypes.Service, error) {
req := &servicetypes.QueryGetServiceRequest{
Id: serviceId,
}

res, err := servq.serviceQuerier.Service(ctx, req)
if err != nil {
return sharedtypes.Service{}, ErrQueryRetrieveService.Wrapf(
"serviceId: %s; error: [%v]",
serviceId, err,
)
}
return res.Service, nil
}
55 changes: 55 additions & 0 deletions pkg/client/query/tokenomicsquerier.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package query

import (
"context"

"cosmossdk.io/depinject"
"github.com/cosmos/gogoproto/grpc"

"github.com/pokt-network/poktroll/pkg/client"
tokenomicstypes "github.com/pokt-network/poktroll/x/tokenomics/types"
)

// tokenomicsQuerier is a wrapper around the tokenomicstypes.QueryClient that enables the
// querying of on-chain tokenomics module data.
type tokenomicsQuerier struct {
clientConn grpc.ClientConn
tokenomicsQuerier tokenomicstypes.QueryClient
}

// NewTokenomicsQuerier returns a new instance of a client.TokenomicsQueryClient by
// injecting the dependecies provided by the depinject.Config.
//
// Required dependencies:
// - grpc.ClientConn
func NewTokenomicsQuerier(deps depinject.Config) (client.TokenomicsQueryClient, error) {
querier := &tokenomicsQuerier{}

if err := depinject.Inject(
deps,
&querier.clientConn,
); err != nil {
return nil, err
}

querier.tokenomicsQuerier = tokenomicstypes.NewQueryClient(querier.clientConn)

return querier, nil
}

// GetServiceRelayDifficultyTargetHash queries the onchain data for
// the relay mining difficulty associated with the given service.
func (tq *tokenomicsQuerier) GetServiceRelayDifficultyTargetHash(
ctx context.Context,
serviceId string,
) (client.TokenomicsRelayMiningDifficulty, error) {
req := &tokenomicstypes.QueryGetRelayMiningDifficultyRequest{
ServiceId: serviceId,
}

res, err := tq.tokenomicsQuerier.RelayMiningDifficulty(ctx, req)
if err != nil {
return nil, err
}
return &res.RelayMiningDifficulty, nil
}
36 changes: 36 additions & 0 deletions pkg/deps/config/suppliers.go
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,42 @@ func NewSupplyProofQueryClientFn() SupplierFn {
}
}

// NewSupplyTokenomicsQueryClientFn returns a function which constructs a
// TokenomicsQueryClient instance and returns a new depinject.Config which
// is supplied with the given deps and the new TokenomicsQueryClient.
func NewSupplyTokenomicsQueryClientFn() SupplierFn {
return func(
_ context.Context,
deps depinject.Config,
_ *cobra.Command,
) (depinject.Config, error) {
tokenomicsQuerier, err := query.NewTokenomicsQuerier(deps)
if err != nil {
return nil, err
}

return depinject.Configs(deps, depinject.Supply(tokenomicsQuerier)), nil
}
}

// NewSupplyServiceQueryClientFn returns a function which constructs a
// NewSupplyServiceQueryClient instance and returns a new depinject.Config which
// is supplied with the given deps and the new ServiceQueryClient.
func NewSupplyServiceQueryClientFn() SupplierFn {
return func(
_ context.Context,
deps depinject.Config,
_ *cobra.Command,
) (depinject.Config, error) {
serviceQuerier, err := query.NewServiceQuerier(deps)
if err != nil {
return nil, err
}

return depinject.Configs(deps, depinject.Supply(serviceQuerier)), nil
}
}

// newSupplyTxClientFn returns a new depinject.Config which is supplied with
// the given deps and the new TxClient.
func newSupplyTxClientsFn(ctx context.Context, deps depinject.Config, signingKeyName string) (depinject.Config, error) {
Expand Down
3 changes: 2 additions & 1 deletion pkg/relayer/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,12 +194,13 @@ func setupRelayerDependencies(
config.NewSupplyTxClientContextFn(queryNodeGRPCUrl, txNodeRPCUrl), // leaf
config.NewSupplyDelegationClientFn(), // leaf
config.NewSupplySharedQueryClientFn(), // leaf
config.NewSupplyProofQueryClientFn(),
config.NewSupplyTokenomicsQueryClientFn(),
supplyMiner,
config.NewSupplyAccountQuerierFn(),
config.NewSupplyApplicationQuerierFn(),
config.NewSupplySupplierQuerierFn(),
config.NewSupplySessionQuerierFn(),
config.NewSupplyServiceQueryClientFn(),
config.NewSupplyRingCacheFn(),
supplyTxFactory,
supplyTxContext,
Expand Down
Loading

0 comments on commit 1556a8f

Please sign in to comment.