Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Utility] trustless relays servicer token validation #803

Merged
merged 28 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
bcd29fe
merge main
adshmh Jun 1, 2023
21e88c0
Validate trustless relay: available service tokens for the application
adshmh Jun 2, 2023
0c64aaa
merge main
adshmh Jun 2, 2023
6b9e44d
Fix double error wrapping until we move to go 1.20
adshmh Jun 2, 2023
934d5a3
Feature: use persistence module for token usage maintenance
adshmh Jun 6, 2023
f37b394
Add relay execution logic to servicer
adshmh Jun 6, 2023
eb1bb93
Address review comments
adshmh Jun 12, 2023
9729440
Merge remote-tracking branch 'origin/main' into feat-utility-trustles…
adshmh Jun 12, 2023
a64822b
Fix proto files
adshmh Jun 12, 2023
9ae0912
Remove gomock temp program
adshmh Jun 12, 2023
c1a6a92
Fix linter errors
adshmh Jun 13, 2023
a98595f
Fix failing unit test in runtime
adshmh Jun 13, 2023
3790f07
Address review comments round 2
adshmh Jun 17, 2023
30750ff
Merge remote-tracking branch 'origin/main' into feat-utility-trustles…
adshmh Jun 17, 2023
1400396
Fix linter warnings
adshmh Jun 17, 2023
f3bfe13
Fix default configuration override
adshmh Jun 19, 2023
58625a0
Address review comments
adshmh Jun 21, 2023
c276c99
Merge main
adshmh Jun 21, 2023
7a8dda0
Revert "Fix default configuration override"
adshmh Jun 25, 2023
821925a
Use an INCOMPLETE item for default servicer config
adshmh Jun 25, 2023
c21f729
Fix failing unit test
adshmh Jun 25, 2023
0014e20
Address review comments
adshmh Jun 26, 2023
76fa1b4
Merge main
adshmh Jun 26, 2023
b758fef
Fix failing unit tests
adshmh Jun 26, 2023
98e4930
Address review comments
adshmh Jun 29, 2023
08fb9b9
Merge main
adshmh Jun 29, 2023
e8021e3
Fix linter warning
adshmh Jun 29, 2023
bc1f3d4
Address review comments
adshmh Jun 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,10 @@ test_persistence: ## Run all go unit tests in the Persistence module
test_persistence_state_hash: ## Run all go unit tests in the Persistence module related to the state hash
go test ${VERBOSE_TEST} -count=1 -tags=test -run TestStateHash ./persistence/...

.PHONY: test_servicer_relay
test_servicer_relay: ## Run all go unit tests related to servicer relays
go test ${VERBOSE_TEST} -count=1 -tags=test ./utility/servicer -run TestRelay

.PHONY: test_p2p
test_p2p: ## Run all p2p related tests
go test ${VERBOSE_TEST} -count=1 -tags=test ./p2p/...
Expand Down
4 changes: 4 additions & 0 deletions persistence/docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.0.0.60] - 2023-06-26

- Add place-holder for local context and servicer token usage support methods

## [0.0.0.59] - 2023-06-14

- Refactors the persistence treeStore to be an IntegratableModule
Expand Down
80 changes: 80 additions & 0 deletions persistence/local/module.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package local
adshmh marked this conversation as resolved.
Show resolved Hide resolved

import (
"math/big"

"github.com/pokt-network/pocket/logger"
coreTypes "github.com/pokt-network/pocket/shared/core/types"
"github.com/pokt-network/pocket/shared/modules"
"github.com/pokt-network/pocket/shared/modules/base_modules"
)

const (
LocalModuleName = "local"
)

var _ modules.PersistenceLocalContext = &persistenceLocalContext{}

type persistenceLocalContext struct {
base_modules.IntegratableModule

logger *modules.Logger
databasePath string
}

func WithLocalDatabasePath(databasePath string) modules.ModuleOption {
return func(m modules.InitializableModule) {
if plc, ok := m.(*persistenceLocalContext); ok {
plc.databasePath = databasePath
}
}
}

func CreateLocalContext(bus modules.Bus, options ...modules.ModuleOption) (modules.PersistenceLocalContext, error) {
m, err := new(persistenceLocalContext).Create(bus, options...)
if err != nil {
return nil, err
}
return m.(modules.PersistenceLocalContext), nil
}

func (*persistenceLocalContext) Create(bus modules.Bus, options ...modules.ModuleOption) (modules.Module, error) {
m := &persistenceLocalContext{}

for _, option := range options {
option(m)
}

bus.RegisterModule(m)

m.logger = logger.Global.CreateLoggerForModule(m.GetModuleName())

return m, nil
}

func (m *persistenceLocalContext) GetModuleName() string {
return LocalModuleName
}

// INCOMPLETE(#826): implement this
func (m *persistenceLocalContext) Start() error {
return nil
}

// INCOMPLETE(#826): implement this
func (m *persistenceLocalContext) Stop() error {
return nil
}

// INCOMPLETE(#826): implement this
// OPTIMIZE: both the relay and the response can be large structures: we may need to truncate the stored values
// StoreServicedRelay implements the PersistenceLocalContext interface
func (local *persistenceLocalContext) StoreServicedRelay(session *coreTypes.Session, relayDigest, relayReqResBytes []byte) error {
return nil
}

// INCOMPLETE(#826): implement this
// GetSessionTokensUsed implements the PersistenceLocalContext interface
func (local *persistenceLocalContext) GetSessionTokensUsed(*coreTypes.Session) (*big.Int, error) {
return nil, nil
}
7 changes: 7 additions & 0 deletions persistence/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/pokt-network/pocket/logger"
"github.com/pokt-network/pocket/persistence/blockstore"
"github.com/pokt-network/pocket/persistence/indexer"
"github.com/pokt-network/pocket/persistence/local"
"github.com/pokt-network/pocket/persistence/trees"
"github.com/pokt-network/pocket/runtime/configs"
"github.com/pokt-network/pocket/runtime/genesis"
Expand Down Expand Up @@ -249,6 +250,12 @@ func (m *persistenceModule) NewWriteContext() modules.PersistenceRWContext {
return m.writeContext
}

// INCOMPLETE(#826): implement this
// GetLocalContext returns a new local context for storing off-chain, i.e. node-specific, data.
func (m *persistenceModule) GetLocalContext() (modules.PersistenceLocalContext, error) {
return local.CreateLocalContext(m.GetBus())
}

// HACK(olshansky): Simplify and externalize the logic for whether genesis should be populated and
//
// move the if logic out of this file.
Expand Down
13 changes: 13 additions & 0 deletions persistence/servicer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package persistence

import (
"encoding/hex"
"math/big"

"github.com/pokt-network/pocket/persistence/types"
coreTypes "github.com/pokt-network/pocket/shared/core/types"
Expand Down Expand Up @@ -79,3 +80,15 @@ func (p *PostgresContext) SetServicerPauseHeight(address []byte, height int64) e
func (p *PostgresContext) GetServicerOutputAddress(operator []byte, height int64) (output []byte, err error) {
return p.GetActorOutputAddress(types.ServicerActor, operator, height)
}

// INCOMPLETE: implement this
// DISCUSS: both the relay and the response can be large structures: we may need to truncate the stored values
Olshansk marked this conversation as resolved.
Show resolved Hide resolved
func (p *PostgresContext) RecordRelayService(applicationAddress string, key []byte, relay *coreTypes.Relay, response *coreTypes.RelayResponse) error {
return nil
}

// INCOMPLETE: implement this
// GetServicerTokenUsage returns the number of tokens used by the servicer in the current session, i.e. for the application associated with the session
Olshansk marked this conversation as resolved.
Show resolved Hide resolved
func (p *PostgresContext) GetServicerTokenUsage(session *coreTypes.Session) (*big.Int, error) {
return nil, nil
}
4 changes: 4 additions & 0 deletions rpc/doc/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.0.0.24] - 2023-06-21

- Update handlers to use the new relay payload types

## [0.0.0.23] - 2023-06-19

- Remove AAT reference from handlers
Expand Down
3 changes: 2 additions & 1 deletion rpc/v1/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1696,11 +1696,12 @@ components:
Payload:
type: object
required:
- method
- jsonrpc
- method
properties:
id:
type: string
format: byte
jsonrpc:
type: string
method:
Expand Down
21 changes: 21 additions & 0 deletions runtime/configs/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ func NewDefaultConfig(options ...func(*Config)) *Config {
VaultMountPath: defaults.DefaultKeybaseVaultMountPath,
},
Validator: &ValidatorConfig{},
// INCOMPLETE(#858): use defaultServicerConfig once the default configuration issue is resolved, i.e. once configuring fisherman disables default servicer
Servicer: &ServicerConfig{},
Fisherman: &FishermanConfig{},
IBC: &IBCConfig{
Expand Down Expand Up @@ -214,3 +215,23 @@ func CreateTempConfig(cfg *Config) (*Config, error) {

return ParseConfig(tmpfile.Name()), nil
}

// INCOMPLETE(#858): enable default servicer config once the default config is adjusted based on user-defined config
// nolint:unused // Use the servicer default config once #858 is resolved: see above description
func defaultServicerConfig() *ServicerConfig {
return &ServicerConfig{
Enabled: true,
RelayMiningVolumeAccuracy: 0.2,
Services: map[string]*ServiceConfig{
// TODO(#831): Design how Chain/Service IDs should be described/defined.
"POKT-LocalNet": {
Url: "http://localhost",
TimeoutMsec: 5000,
BasicAuth: &BasicAuth{
UserName: "user",
Password: "password",
},
},
},
}
}
2 changes: 2 additions & 0 deletions runtime/configs/proto/persistence_config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ message PersistenceConfig {
string max_conn_lifetime = 8; // See pkg.go.dev/time#ParseDuration for reference
string max_conn_idle_time = 9; // See pkg.go.dev/time#ParseDuration for reference
string health_check_period = 10; // See pkg.go.dev/time#ParseDuration for reference
// TODO: `local_database_path` may need to be expanded to multiple stores depending on how usage evolves
string local_database_path = 11; // The path used to store local, i.e. off-chain and node-specific, data.
adshmh marked this conversation as resolved.
Show resolved Hide resolved
}
25 changes: 24 additions & 1 deletion runtime/configs/proto/servicer_config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,34 @@ package configs;

option go_package = "github.com/pokt-network/pocket/runtime/configs";

// TODO: Reevaluate whether each utility actor should contain address/pubKey configs or if it should be shared
// ServicerConfig defines the configuration for the node acting as a servicer. Servicers earn rewards for providing Web3 access over a function of volume and quality
message ServicerConfig {
// Enabled defines whether or not the node is a servicer.
bool enabled = 1;
string public_key = 2;
string address = 3;
repeated string chains = 4;
map<string, ServiceConfig> services = 4;

// relay_mining_volume_accuracy is a parameter used to adjust the calculated number of service tokens for an application.
adshmh marked this conversation as resolved.
Show resolved Hide resolved
// It is introduced to minimize the chance of under-utilization of application's tokens, while removing the overhead of
// communication between servicers which would be necessary otherwise.
// See the following for more details:
// https://arxiv.org/abs/2305.10672
double relay_mining_volume_accuracy = 5;
}

// ServiceConfig holds configurations related to where/how the application/client can access the backing RPC service. It is analogous to "ChainConfig" in v0 but can support any RPC service.
message ServiceConfig {
adshmh marked this conversation as resolved.
Show resolved Hide resolved
string url = 1; // url specifies the URL at which the service is provided/requested
uint64 timeout_msec = 2; // timeout specifes the maximum amount of time, in milliseconds, to allow for the service to return a response
BasicAuth basic_auth = 3; // optional: basic authentication for HTTP services.
}

// BasicAuth stores authentication data for HTTP services
// When supplied, this data will be used as specified by the HTTP basic authentication scheme.
message BasicAuth {
string user_name = 1;
// IMPROVE: enforce encryption of plaintext password
string password = 2;
}
4 changes: 4 additions & 0 deletions runtime/docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.0.0.44] - 2023-06-26

- Add a new ServiceConfig field to servicer config

## [0.0.0.43] - 2023-06-14

- Rename package import types to coreTypes for consitency and clarity
Expand Down
7 changes: 2 additions & 5 deletions runtime/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1816,11 +1816,8 @@ func TestNewManagerFromReaders(t *testing.T) {
Timeout: 30000,
UseCors: false,
},
Keybase: defaultCfg.Keybase,
Servicer: &configs.ServicerConfig{
Enabled: true,
Chains: []string{"0001"},
},
Keybase: defaultCfg.Keybase,
Servicer: &configs.ServicerConfig{Enabled: true},
Validator: &configs.ValidatorConfig{Enabled: true},
Fisherman: defaultCfg.Fisherman,
IBC: &configs.IBCConfig{Enabled: true},
Expand Down
5 changes: 5 additions & 0 deletions shared/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.0.0.60] - 2023-06-21

- Add a LocalContext type and place-holders for servicer token usage support to persistence
- Add a TODO comment for supporting different relay payload types in core types

## [0.0.0.59] - 2023-06-14

- Added validators for JSONRPC and REST payloads to shared types
Expand Down
12 changes: 11 additions & 1 deletion shared/core/types/proto/relay.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ option go_package = "github.com/pokt-network/pocket/shared/core/types";

message Relay {
RelayMeta meta = 1;
// Every different chain/service may have its own custom payload (e.g. HTTP, JSON, GRPC, non-chain services)
oneof relay_payload {
JSONRPCPayload json_rpc_payload = 2;
RESTPayload rest_payload = 3;
Expand All @@ -16,6 +17,7 @@ message Relay {
}
}

// INCOMPLETE: add REST relay payload fields
message RESTPayload {
string contents = 1;
string http_path = 2;
Expand Down Expand Up @@ -50,7 +52,8 @@ message JSONRPCPayload {
message RelayMeta {
int64 block_height = 1;
string servicer_public_key = 2;
// TODO: Make Chain identifier type consistent in Session and Meta: use Identifiable for Chain in Session (or a string here to match the session)
// TODO(M5): Consider renaming `relay_chain` to `rpc_service` or something similar
// TODO: Make Chain/Service identifier type consistent in Session and Meta: use Identifiable for Chain/Service in Session (or a string here to match the session)
Identifiable relay_chain = 3;
Identifiable geo_zone = 4;
string signature = 5; // TECHDEBT: Consolidate with `Signature` proto used elsewhere in the future
Expand All @@ -73,3 +76,10 @@ message Identifiable {
string id = 1;
string name = 2;
}


// RelayReqRes contains a relay request and its response, used for persistence of relay service evidence
message RelayReqRes {
adshmh marked this conversation as resolved.
Show resolved Hide resolved
Relay relay = 1;
RelayResponse response = 2;
}
2 changes: 1 addition & 1 deletion shared/core/types/proto/session.proto
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import "actor.proto";
message Session {
string id = 1; // a universally unique ID for the session
int64 session_number = 2; // a monotonically increasing number representing the # on the chain
int64 session_height = 3; // the number of blocks (out of numBlocksPerSession) in this session
int64 session_height = 3; // the height at which the session starts
int64 num_session_blocks = 4; // the number of blocks the session is valid from
// CONSIDERATION: Should we add a `RelayChain` enum and use it across the board?
// CONSIDERATION: Should a single session support multiple relay chains?
Expand Down
31 changes: 30 additions & 1 deletion shared/modules/persistence_module.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package modules

//go:generate mockgen -destination=./mocks/persistence_module_mock.go github.com/pokt-network/pocket/shared/modules PersistenceModule,PersistenceRWContext,PersistenceReadContext,PersistenceWriteContext
//go:generate mockgen -destination=./mocks/persistence_module_mock.go github.com/pokt-network/pocket/shared/modules PersistenceModule,PersistenceRWContext,PersistenceReadContext,PersistenceWriteContext,PersistenceLocalContext

import (
"math/big"

"github.com/pokt-network/pocket/persistence/blockstore"
"github.com/pokt-network/pocket/persistence/indexer"
"github.com/pokt-network/pocket/runtime/genesis"
Expand All @@ -18,6 +20,9 @@ type PersistenceModule interface {

// Context operations
NewRWContext(height int64) (PersistenceRWContext, error)
// TODO(#406): removing height from "NewReadContext" input and passing it to specific methods seems a better choice.
// This could prevent confusion when retrieving the value of a parameter for a height less than the current height,
// e.g. when getting the App Token sessions multiplier for the starting height of a session.
NewReadContext(height int64) (PersistenceReadContext, error)
ReleaseWriteContext() error // The module can maintain many read contexts, but only one write context can exist at a time

Expand All @@ -35,6 +40,11 @@ type PersistenceModule interface {

// Debugging / development only
HandleDebugMessage(*messaging.DebugMessage) error

// GetLocalContext returns a local persistence context that can be used to store/retrieve node-specific, i.e. off-chain, data
// The module can maintain a single (i.e. a singleton) local context for both read and write operations: subsequent calls to GetLocalContext return
// the same local context.
GetLocalContext() (PersistenceLocalContext, error)
}

// Interface defining the context within which the node can operate with the persistence layer.
Expand Down Expand Up @@ -133,6 +143,8 @@ type PersistenceWriteContext interface {
// Flag Operations
InitFlags() error
SetFlag(paramName string, value any, enabled bool) error

Olshansk marked this conversation as resolved.
Show resolved Hide resolved
RecordRelayService(applicationAddress string, key []byte, relay *coreTypes.Relay, response *coreTypes.RelayResponse) error
Olshansk marked this conversation as resolved.
Show resolved Hide resolved
}

type PersistenceReadContext interface {
Expand Down Expand Up @@ -224,3 +236,20 @@ type PersistenceReadContext interface {
GetStringFlag(paramName string, height int64) (string, bool, error)
GetBytesFlag(paramName string, height int64) ([]byte, bool, error)
}

// PersistenceLocalContext defines the set of operations specific to local persistence.
//
// This context should be used for node-specific data, e.g. records of served relays.
// This is in contrast to PersistenceRWContext which should be used to store on-chain data.
type PersistenceLocalContext interface {
// StoreServicedRelay stores record of a serviced relay and its response in the local context.
// The stored service relays will be used to:
// a) check the number of tokens used per session, and
// b) prepare claim/proof messages once the session is over
// The "relayDigest" and "relayReqResBytes" parameters will be used as key and leaf contents in the constructed SMT, respectively.
StoreServicedRelay(session *coreTypes.Session, relayDigest, relayReqResBytes []byte) error
// GetSessionTokensUsed returns the number of tokens that have been used for the provided session.
// It returns the count of tokens used by the servicer instance
// for the application associated with the session
GetSessionTokensUsed(*coreTypes.Session) (*big.Int, error)
}
Loading