diff --git a/Makefile b/Makefile index de0c67cd2..1860b6156 100644 --- a/Makefile +++ b/Makefile @@ -312,15 +312,18 @@ app_delegate: ## Delegate trust to a gateway (must specify the APP and GATEWAY_A .PHONY: app1_delegate_gateway1 app1_delegate_gateway1: ## Delegate trust to gateway1 - APP=app1 GATEWAY_ADDR=pokt15vzxjqklzjtlz7lahe8z2dfe9nm5vxwwmscne4 make app_delegate + GATEWAY1=$$(make poktrolld_addr ACC_NAME=gateway1) && \ + APP=app1 GATEWAY_ADDR=$$GATEWAY1 make app_delegate .PHONY: app2_delegate_gateway2 app2_delegate_gateway2: ## Delegate trust to gateway2 - APP=app2 GATEWAY_ADDR=pokt15w3fhfyc0lttv7r585e2ncpf6t2kl9uh8rsnyz make app_delegate + GATEWAY2=$$(make poktrolld_addr ACC_NAME=gateway2) && \ + APP=app2 GATEWAY_ADDR=$$GATEWAY2 make app_delegate .PHONY: app3_delegate_gateway3 app3_delegate_gateway3: ## Delegate trust to gateway3 - APP=app3 GATEWAY_ADDR=pokt1zhmkkd0rh788mc9prfq0m2h88t9ge0j83gnxya make app_delegate + GATEWAY3=$$(make poktrolld_addr ACC_NAME=gateway3) && \ + APP=app3 GATEWAY_ADDR=$$GATEWAY3 make app_delegate .PHONY: app_undelegate app_undelegate: ## Undelegate trust to a gateway (must specify the APP and GATEWAY_ADDR env vars). Requires the app to be staked @@ -328,15 +331,18 @@ app_undelegate: ## Undelegate trust to a gateway (must specify the APP and GATEW .PHONY: app1_undelegate_gateway1 app1_undelegate_gateway1: ## Undelegate trust to gateway1 - APP=app1 GATEWAY_ADDR=pokt15vzxjqklzjtlz7lahe8z2dfe9nm5vxwwmscne4 make app_undelegate + GATEWAY1=$$(make poktrolld_addr ACC_NAME=gateway1) && \ + APP=app1 GATEWAY_ADDR=$$GATEWAY1 make app_undelegate .PHONY: app2_undelegate_gateway2 app2_undelegate_gateway2: ## Undelegate trust to gateway2 - APP=app2 GATEWAY_ADDR=pokt15w3fhfyc0lttv7r585e2ncpf6t2kl9uh8rsnyz make app_undelegate + GATEWAY2=$$(make poktrolld_addr ACC_NAME=gateway2) && \ + APP=app2 GATEWAY_ADDR=$$GATEWAY2 make app_undelegate .PHONY: app3_undelegate_gateway3 app3_undelegate_gateway3: ## Undelegate trust to gateway3 - APP=app3 GATEWAY_ADDR=pokt1zhmkkd0rh788mc9prfq0m2h88t9ge0j83gnxya make app_undelegate + GATEWAY3=$$(make poktrolld_addr ACC_NAME=gateway3) && \ + APP=app3 GATEWAY_ADDR=$$GATEWAY3 make app_undelegate ################# ### Suppliers ### @@ -380,6 +386,29 @@ supplier2_unstake: ## Unstake supplier2 supplier3_unstake: ## Unstake supplier3 SUPPLIER=supplier3 make supplier_unstake +############### +### Session ### +############### + +.PHONY: get_session +get_session: ## Retrieve the session given the following env vars: (APP_ADDR, SVC, HEIGHT) + pocketd --home=$(POCKETD_HOME) q session get-session $(APP) $(SVC) $(HEIGHT) --node $(POCKET_NODE) + +.PHONY: get_session_app1_anvil +get_session_app1_anvil: ## Retrieve the session for (app1, anvil, latest_height) + APP1=$$(make poktrolld_addr ACC_NAME=app1) && \ + APP=$$APP1 SVC=anvil HEIGHT=0 make get_session + +.PHONY: get_session_app2_anvil +get_session_app2_anvil: ## Retrieve the session for (app2, anvil, latest_height) + APP2=$$(make poktrolld_addr ACC_NAME=app2) && \ + APP=$$APP2 SVC=anvil HEIGHT=0 make get_session + +.PHONY: get_session_app3_anvil +get_session_app3_anvil: ## Retrieve the session for (app3, anvil, latest_height) + APP3=$$(make poktrolld_addr ACC_NAME=app3) && \ + APP=$$APP3 SVC=anvil HEIGHT=0 make get_session + ################ ### Accounts ### ################ @@ -398,11 +427,13 @@ acc_balance_query_module_app: ## Query the balance of the network level "applica .PHONY: acc_balance_query_module_supplier acc_balance_query_module_supplier: ## Query the balance of the network level "supplier" module - make acc_balance_query ACC=pokt1j40dzzmn6cn9kxku7a5tjnud6hv37vesr5ccaa + SUPPLIER1=$(make poktrolld_addr ACC_NAME=supplier1) + make acc_balance_query ACC=SUPPLIER1 .PHONY: acc_balance_query_app1 acc_balance_query_app1: ## Query the balance of app1 - make acc_balance_query ACC=pokt1mrqt5f7qh8uxs27cjm9t7v9e74a9vvdnq5jva4 + APP1=$$(make poktrolld_addr ACC_NAME=app1) && \ + make acc_balance_query ACC=$$APP1 .PHONY: acc_balance_total_supply acc_balance_total_supply: ## Query the total supply of the network @@ -428,8 +459,20 @@ trigger_ci: ## Trigger the CI pipeline by submitting an empty commit; See https: ##################### ### Documentation ### ##################### + .PHONY: go_docs go_docs: check_godoc ## Generate documentation for the project echo "Visit http://localhost:6060/pkg/pocket/" godoc -http=:6060 +.PHONY: openapi_gen +openapi_gen: ## Generate the OpenAPI spec for the Ignite API + ignite generate openapi --yes + +###################### +### Ignite Helpers ### +###################### + +.PHONY: poktrolld_addr +poktrolld_addr: ## Retrieve the address for an account by ACC_NAME + @echo $(shell poktrolld keys show -a $(ACC_NAME)) diff --git a/app/app.go b/app/app.go index c6a48ee69..b34d4db68 100644 --- a/app/app.go +++ b/app/app.go @@ -575,17 +575,6 @@ func New( ) serviceModule := servicemodule.NewAppModule(appCodec, app.ServiceKeeper, app.AccountKeeper, app.BankKeeper) - app.SessionKeeper = *sessionmodulekeeper.NewKeeper( - appCodec, - keys[sessionmoduletypes.StoreKey], - keys[sessionmoduletypes.MemStoreKey], - app.GetSubspace(sessionmoduletypes.ModuleName), - - app.ApplicationKeeper, - app.SupplierKeeper, - ) - sessionModule := sessionmodule.NewAppModule(appCodec, app.SessionKeeper, app.AccountKeeper, app.BankKeeper) - app.SupplierKeeper = *suppliermodulekeeper.NewKeeper( appCodec, keys[suppliermoduletypes.StoreKey], @@ -618,6 +607,17 @@ func New( ) applicationModule := applicationmodule.NewAppModule(appCodec, app.ApplicationKeeper, app.AccountKeeper, app.BankKeeper) + app.SessionKeeper = *sessionmodulekeeper.NewKeeper( + appCodec, + keys[sessionmoduletypes.StoreKey], + keys[sessionmoduletypes.MemStoreKey], + app.GetSubspace(sessionmoduletypes.ModuleName), + + app.ApplicationKeeper, + app.SupplierKeeper, + ) + sessionModule := sessionmodule.NewAppModule(appCodec, app.SessionKeeper, app.AccountKeeper, app.BankKeeper) + // this line is used by starport scaffolding # stargate/app/keeperDefinition /**** IBC Routing ****/ diff --git a/docs/static/openapi.yml b/docs/static/openapi.yml index 687106365..8013d6531 100644 --- a/docs/static/openapi.yml +++ b/docs/static/openapi.yml @@ -46477,7 +46477,7 @@ paths: items: type: object properties: - service_id: + service: title: Unique and semantic identifier for the service type: object properties: @@ -46504,7 +46504,9 @@ paths: title: >- ApplicationServiceConfig holds the service configuration the application stakes for - title: The ID of the service this session is servicing + title: >- + The list of services this appliccation is configured to + request service for delegatee_gateway_addresses: type: array items: @@ -46659,7 +46661,7 @@ paths: items: type: object properties: - service_id: + service: title: Unique and semantic identifier for the service type: object properties: @@ -46686,7 +46688,9 @@ paths: title: >- ApplicationServiceConfig holds the service configuration the application stakes for - title: The ID of the service this session is servicing + title: >- + The list of services this appliccation is configured to + request service for delegatee_gateway_addresses: type: array items: @@ -47090,8 +47094,8 @@ paths: title: >- The Bech32 address of the application using cosmos' ScalarDescriptor to ensure deterministic encoding - service_id: - title: The ID of the service this session is servicing + service: + title: The service this session is for type: object properties: id: @@ -47173,7 +47177,7 @@ paths: items: type: object properties: - service_id: + service: title: Unique and semantic identifier for the service type: object properties: @@ -47200,7 +47204,9 @@ paths: title: >- ApplicationServiceConfig holds the service configuration the application stakes for - title: The ID of the service this session is servicing + title: >- + The list of services this appliccation is configured + to request service for delegatee_gateway_addresses: type: array items: @@ -47240,7 +47246,7 @@ paths: items: type: object properties: - service_id: + service: title: Unique and semantic identifier for the service type: object properties: @@ -47363,7 +47369,7 @@ paths: in: query required: false type: string - - name: service_id.id + - name: service.id description: >- NOTE: `ServiceId.Id` may seem redundant but was desigtned created to enable more complex service identification @@ -47376,7 +47382,7 @@ paths: in: query required: false type: string - - name: service_id.name + - name: service.name description: >- TODO_TECHDEBT: Name is currently unused but acts as a reminder than an optional onchain representation of the service is necessary @@ -76616,7 +76622,7 @@ definitions: items: type: object properties: - service_id: + service: title: Unique and semantic identifier for the service type: object properties: @@ -76640,7 +76646,9 @@ definitions: title: >- ApplicationServiceConfig holds the service configuration the application stakes for - title: The ID of the service this session is servicing + title: >- + The list of services this appliccation is configured to request + service for delegatee_gateway_addresses: type: array items: @@ -76701,7 +76709,7 @@ definitions: items: type: object properties: - service_id: + service: title: Unique and semantic identifier for the service type: object properties: @@ -76728,7 +76736,9 @@ definitions: title: >- ApplicationServiceConfig holds the service configuration the application stakes for - title: The ID of the service this session is servicing + title: >- + The list of services this appliccation is configured to request + service for delegatee_gateway_addresses: type: array items: @@ -76797,7 +76807,7 @@ definitions: items: type: object properties: - service_id: + service: title: Unique and semantic identifier for the service type: object properties: @@ -76822,7 +76832,9 @@ definitions: title: >- ApplicationServiceConfig holds the service configuration the application stakes for - title: The ID of the service this session is servicing + title: >- + The list of services this appliccation is configured to request + service for delegatee_gateway_addresses: type: array items: @@ -76850,7 +76862,7 @@ definitions: pocket.shared.ApplicationServiceConfig: type: object properties: - service_id: + service: title: Unique and semantic identifier for the service type: object properties: @@ -76873,7 +76885,7 @@ definitions: title: >- ApplicationServiceConfig holds the service configuration the application stakes for - pocket.shared.ServiceId: + pocket.shared.Service: type: object properties: id: @@ -76892,7 +76904,7 @@ definitions: TODO_TECHDEBT: Name is currently unused but acts as a reminder than an optional onchain representation of the service is necessary title: >- - ServiceId message to encapsulate unique and semantic identifiers for a + Service message to encapsulate unique and semantic identifiers for a service on the network pocket.gateway.Gateway: type: object @@ -77043,8 +77055,8 @@ definitions: title: >- The Bech32 address of the application using cosmos' ScalarDescriptor to ensure deterministic encoding - service_id: - title: The ID of the service this session is servicing + service: + title: The service this session is for type: object properties: id: @@ -77121,7 +77133,7 @@ definitions: items: type: object properties: - service_id: + service: title: Unique and semantic identifier for the service type: object properties: @@ -77148,7 +77160,9 @@ definitions: title: >- ApplicationServiceConfig holds the service configuration the application stakes for - title: The ID of the service this session is servicing + title: >- + The list of services this appliccation is configured to + request service for delegatee_gateway_addresses: type: array items: @@ -77187,7 +77201,7 @@ definitions: items: type: object properties: - service_id: + service: title: Unique and semantic identifier for the service type: object properties: @@ -77300,8 +77314,8 @@ definitions: title: >- The Bech32 address of the application using cosmos' ScalarDescriptor to ensure deterministic encoding - service_id: - title: The ID of the service this session is servicing + service: + title: The service this session is for type: object properties: id: @@ -77378,7 +77392,7 @@ definitions: items: type: object properties: - service_id: + service: title: Unique and semantic identifier for the service type: object properties: @@ -77403,7 +77417,9 @@ definitions: title: >- ApplicationServiceConfig holds the service configuration the application stakes for - title: The ID of the service this session is servicing + title: >- + The list of services this appliccation is configured to request + service for delegatee_gateway_addresses: type: array items: @@ -77442,7 +77458,7 @@ definitions: items: type: object properties: - service_id: + service: title: Unique and semantic identifier for the service type: object properties: @@ -77542,8 +77558,8 @@ definitions: title: >- The Bech32 address of the application using cosmos' ScalarDescriptor to ensure deterministic encoding - service_id: - title: The ID of the service this session is servicing + service: + title: The service this session is for type: object properties: id: @@ -77572,6 +77588,26 @@ definitions: title: >- NOTE: session_id can be derived from the above values using on-chain but is included in the header for convenience + service_id: + title: The ID of the service this session is servicing + type: object + properties: + id: + type: string + description: Unique identifier for the service + title: >- + NOTE: `ServiceId.Id` may seem redundant but was desigtned created + to enable more complex service identification + + For example, what if we want to request a session for a certain + service but with some additional configs that identify it? + name: + type: string + description: (Optional) Semantic human readable name for the service + title: >- + TODO_TECHDEBT: Name is currently unused but acts as a reminder + than an optional onchain representation of the service is + necessary description: >- SessionHeader is a lightweight header for a session that can be passed around. @@ -77657,7 +77693,7 @@ definitions: items: type: object properties: - service_id: + service: title: Unique and semantic identifier for the service type: object properties: @@ -77730,6 +77766,27 @@ definitions: title: Additional configuration options for the endpoint title: SupplierEndpoint message to hold service configuration details title: List of endpoints for the service + service_id: + title: Unique and semantic identifier for the service + type: object + properties: + id: + type: string + description: Unique identifier for the service + title: >- + NOTE: `ServiceId.Id` may seem redundant but was desigtned + created to enable more complex service identification + + For example, what if we want to request a session for a + certain service but with some additional configs that + identify it? + name: + type: string + description: (Optional) Semantic human readable name for the service + title: >- + TODO_TECHDEBT: Name is currently unused but acts as a + reminder than an optional onchain representation of the + service is necessary title: >- SupplierServiceConfig holds the service configuration the supplier stakes for @@ -77789,7 +77846,7 @@ definitions: pocket.shared.SupplierServiceConfig: type: object properties: - service_id: + service: title: Unique and semantic identifier for the service type: object properties: @@ -77861,9 +77918,50 @@ definitions: title: Additional configuration options for the endpoint title: SupplierEndpoint message to hold service configuration details title: List of endpoints for the service + service_id: + title: Unique and semantic identifier for the service + type: object + properties: + id: + type: string + description: Unique identifier for the service + title: >- + NOTE: `ServiceId.Id` may seem redundant but was desigtned created + to enable more complex service identification + + For example, what if we want to request a session for a certain + service but with some additional configs that identify it? + name: + type: string + description: (Optional) Semantic human readable name for the service + title: >- + TODO_TECHDEBT: Name is currently unused but acts as a reminder + than an optional onchain representation of the service is + necessary title: >- SupplierServiceConfig holds the service configuration the supplier stakes for + pocket.shared.ServiceId: + type: object + properties: + id: + type: string + description: Unique identifier for the service + title: >- + NOTE: `ServiceId.Id` may seem redundant but was desigtned created to + enable more complex service identification + + For example, what if we want to request a session for a certain + service but with some additional configs that identify it? + name: + type: string + description: (Optional) Semantic human readable name for the service + title: >- + TODO_TECHDEBT: Name is currently unused but acts as a reminder than an + optional onchain representation of the service is necessary + title: >- + ServiceId message to encapsulate unique and semantic identifiers for a + service on the network pocket.supplier.MsgCreateClaimResponse: type: object pocket.supplier.MsgStakeSupplierResponse: diff --git a/go.mod b/go.mod index b4658dfb1..6856b606c 100644 --- a/go.mod +++ b/go.mod @@ -9,10 +9,10 @@ require ( cosmossdk.io/math v1.0.1 github.com/cometbft/cometbft v0.37.2 github.com/cometbft/cometbft-db v0.8.0 - github.com/cosmos/cosmos-proto v1.0.0-beta.2 github.com/cosmos/cosmos-sdk v0.47.3 github.com/cosmos/gogoproto v1.4.10 github.com/cosmos/ibc-go/v7 v7.1.0 + github.com/gogo/status v1.1.1 github.com/golang/mock v1.6.0 github.com/golang/protobuf v1.5.3 github.com/gorilla/mux v1.8.0 @@ -28,7 +28,6 @@ require ( go.uber.org/multierr v1.11.0 golang.org/x/crypto v0.12.0 golang.org/x/sync v0.3.0 - google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 google.golang.org/grpc v1.56.1 gopkg.in/yaml.v2 v2.4.0 ) @@ -72,6 +71,7 @@ require ( github.com/containerd/cgroups v1.1.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect + github.com/cosmos/cosmos-proto v1.0.0-beta.2 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v0.20.0 // indirect @@ -267,6 +267,7 @@ require ( gonum.org/v1/gonum v0.11.0 // indirect google.golang.org/api v0.122.0 // indirect google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 64f7566f0..b554afc3b 100644 --- a/go.sum +++ b/go.sum @@ -688,10 +688,13 @@ github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.3.1+incompatible h1:0/KbAdpx3UXAx1kEOWHJeOkpbgRFGHVgv+CFIY7dBJI= github.com/gofrs/uuid v4.3.1+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.4.1-0.20201022092350-68b0159b7869/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= +github.com/gogo/status v1.1.1 h1:DuHXlSFHNKqTQ+/ACf5Vs6r4X/dH2EgIzR9Vr+H65kg= +github.com/gogo/status v1.1.1/go.mod h1:jpG3dM5QPcqu19Hg8lkUhBFBa3TcLs1DG7+2Jqci7oU= github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8= @@ -2610,6 +2613,7 @@ google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -2735,6 +2739,7 @@ google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnp google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= diff --git a/pkg/client/services.go b/pkg/client/services.go index 0d2ca060d..1e2667cf9 100644 --- a/pkg/client/services.go +++ b/pkg/client/services.go @@ -12,7 +12,7 @@ func NewTestApplicationServiceConfig(prefix string, count int) []*sharedtypes.Ap for i, _ := range appSvcCfg { serviceId := fmt.Sprintf("%s%d", prefix, i) appSvcCfg[i] = &sharedtypes.ApplicationServiceConfig{ - ServiceId: &sharedtypes.ServiceId{Id: serviceId}, + Service: &sharedtypes.Service{Id: serviceId}, } } return appSvcCfg diff --git a/pkg/relayer/proxy/interface.go b/pkg/relayer/proxy/interface.go index 27ee83e72..df4232588 100644 --- a/pkg/relayer/proxy/interface.go +++ b/pkg/relayer/proxy/interface.go @@ -41,6 +41,6 @@ type RelayServer interface { // Stop terminates the service server and returns an error if it fails. Stop(ctx context.Context) error - // ServiceId returns the serviceId of the service. - ServiceId() *sharedtypes.ServiceId + // Service returns the service to which the RelayServer relays. + Service() *sharedtypes.Service } diff --git a/pkg/relayer/proxy/jsonrpc.go b/pkg/relayer/proxy/jsonrpc.go index ac9295c6b..f6cc9cb22 100644 --- a/pkg/relayer/proxy/jsonrpc.go +++ b/pkg/relayer/proxy/jsonrpc.go @@ -12,8 +12,8 @@ import ( var _ RelayServer = (*jsonRPCServer)(nil) type jsonRPCServer struct { - // serviceId is the id of the service that the server is responsible for. - serviceId *sharedtypes.ServiceId + // service is the service that the server is responsible for. + service *sharedtypes.Service // serverEndpoint is the advertised endpoint configuration that the server uses to // listen for incoming relay requests. @@ -38,14 +38,14 @@ type jsonRPCServer struct { // It takes the serviceId, endpointUrl, and the main RelayerProxy as arguments and returns // a RelayServer that listens to incoming RelayRequests func NewJSONRPCServer( - serviceId *sharedtypes.ServiceId, + service *sharedtypes.Service, supplierEndpoint *sharedtypes.SupplierEndpoint, proxiedServiceEndpoint url.URL, servedRelaysProducer chan<- *types.Relay, proxy RelayerProxy, ) RelayServer { return &jsonRPCServer{ - serviceId: serviceId, + service: service, serverEndpoint: supplierEndpoint, server: &http.Server{Addr: supplierEndpoint.Url}, relayerProxy: proxy, @@ -71,9 +71,9 @@ func (j *jsonRPCServer) Stop(ctx context.Context) error { return j.server.Shutdown(ctx) } -// ServiceId returns the serviceId of the JSON-RPC service. -func (j *jsonRPCServer) ServiceId() *sharedtypes.ServiceId { - return j.serviceId +// Service returns the JSON-RPC service. +func (j *jsonRPCServer) Service() *sharedtypes.Service { + return j.service } // ServeHTTP listens for incoming relay requests. It implements the respective diff --git a/pkg/relayer/proxy/server_builder.go b/pkg/relayer/proxy/server_builder.go index eb21cc1f2..53e0c4d14 100644 --- a/pkg/relayer/proxy/server_builder.go +++ b/pkg/relayer/proxy/server_builder.go @@ -29,8 +29,8 @@ func (rp *relayerProxy) BuildProvidedServices(ctx context.Context) error { // Build the advertised relay servers map. For each service's endpoint, create the appropriate RelayServer. providedServices := make(relayServersMap) for _, serviceConfig := range services { - serviceId := serviceConfig.ServiceId - proxiedServicesEndpoints := rp.proxiedServicesEndpoints[serviceId.Id] + service := serviceConfig.Service + proxiedServicesEndpoints := rp.proxiedServicesEndpoints[service.Id] serviceEndpoints := make([]RelayServer, len(serviceConfig.Endpoints)) for _, endpoint := range serviceConfig.Endpoints { @@ -40,7 +40,7 @@ func (rp *relayerProxy) BuildProvidedServices(ctx context.Context) error { switch endpoint.RpcType { case sharedtypes.RPCType_JSON_RPC: server = NewJSONRPCServer( - serviceId, + service, endpoint, proxiedServicesEndpoints, rp.servedRelaysProducer, @@ -53,7 +53,7 @@ func (rp *relayerProxy) BuildProvidedServices(ctx context.Context) error { serviceEndpoints = append(serviceEndpoints, server) } - providedServices[serviceId.Id] = serviceEndpoints + providedServices[service.Id] = serviceEndpoints } rp.advertisedRelayServers = providedServices diff --git a/proto/pocket/application/application.proto b/proto/pocket/application/application.proto index e5763d697..f4d3610ca 100644 --- a/proto/pocket/application/application.proto +++ b/proto/pocket/application/application.proto @@ -13,6 +13,6 @@ import "pocket/shared/service.proto"; message Application { string address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; // The Bech32 address of the application using cosmos' ScalarDescriptor to ensure deterministic encoding cosmos.base.v1beta1.Coin stake = 2; // The total amount of uPOKT the application has staked - repeated shared.ApplicationServiceConfig service_configs = 3; // The ID of the service this session is servicing + repeated shared.ApplicationServiceConfig service_configs = 3; // The list of services this appliccation is configured to request service for repeated string delegatee_gateway_addresses = 4 [(cosmos_proto.scalar) = "cosmos.AddressString", (gogoproto.nullable) = false]; // The Bech32 encoded addresses for all delegatee Gateways, in a non-nullable slice } diff --git a/proto/pocket/session/query.proto b/proto/pocket/session/query.proto index f8b1c7187..08de287eb 100644 --- a/proto/pocket/session/query.proto +++ b/proto/pocket/session/query.proto @@ -38,7 +38,7 @@ message QueryParamsResponse { message QueryGetSessionRequest { string application_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; // The Bech32 address of the application using cosmos' ScalarDescriptor to ensure deterministic encoding - shared.ServiceId service_id = 2; // The service id to query the session for + shared.Service service = 2; // The service id to query the session for int64 block_height = 3; // The block height to query the session for } diff --git a/proto/pocket/session/session.proto b/proto/pocket/session/session.proto index e8f14b35e..3008e749f 100644 --- a/proto/pocket/session/session.proto +++ b/proto/pocket/session/session.proto @@ -14,7 +14,7 @@ import "pocket/shared/supplier.proto"; // It is the minimal amount of data required to hydrate & retrieve all data relevant to the session. message SessionHeader { string application_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; // The Bech32 address of the application using cosmos' ScalarDescriptor to ensure deterministic encoding - shared.ServiceId service_id = 2; // The ID of the service this session is servicing + shared.Service service = 2; // The service this session is for int64 session_start_block_height = 3; // The height at which this session started // NOTE: session_id can be derived from the above values using on-chain but is included in the header for convenience string session_id = 4; // A unique pseudoranom ID for this session diff --git a/proto/pocket/shared/service.proto b/proto/pocket/shared/service.proto index c911bad1f..4700035ce 100644 --- a/proto/pocket/shared/service.proto +++ b/proto/pocket/shared/service.proto @@ -8,22 +8,18 @@ option go_package = "github.com/pokt-network/poktroll/x/shared/types"; // TODO_CLEANUP(@Olshansk): Add native optional identifiers once its supported; https://github.com/ignite/cli/issues/3698 -// ServiceId message to encapsulate unique and semantic identifiers for a service on the network -message ServiceId { - // NOTE: `ServiceId.Id` may seem redundant but was desigtned created to enable more complex service identification +// Service message to encapsulate unique and semantic identifiers for a service on the network +message Service { // For example, what if we want to request a session for a certain service but with some additional configs that identify it? string id = 1; // Unique identifier for the service // TODO_TECHDEBT: Name is currently unused but acts as a reminder than an optional onchain representation of the service is necessary string name = 2; // (Optional) Semantic human readable name for the service - - // NOTE: `ServiceId.Id` may seem redundant but was designed to enable more complex service identification. - // For example, what if we want to request a session for a certain service but with some additional configs that identify it? } // ApplicationServiceConfig holds the service configuration the application stakes for message ApplicationServiceConfig { - ServiceId service_id = 1; // Unique and semantic identifier for the service + Service service = 1; // The Service for which the application is configured // TODO_RESEARCH: There is an opportunity for applications to advertise the max // they're willing to pay for a certain configuration/price, but this is outside of scope. @@ -32,7 +28,7 @@ message ApplicationServiceConfig { // SupplierServiceConfig holds the service configuration the supplier stakes for message SupplierServiceConfig { - ServiceId service_id = 1; // Unique and semantic identifier for the service + Service service = 1; // The Service for which the supplier is configured repeated SupplierEndpoint endpoints = 2; // List of endpoints for the service // TODO_RESEARCH: There is an opportunity for supplier to advertise the min // they're willing to earn for a certain configuration/price, but this is outside of scope. diff --git a/testutil/keeper/session.go b/testutil/keeper/session.go index e4be2537f..8b57ec0c4 100644 --- a/testutil/keeper/session.go +++ b/testutil/keeper/session.go @@ -27,33 +27,44 @@ import ( type option[V any] func(k *keeper.Keeper) var ( - TestServiceId1 = "svc1" - TestServiceId2 = "svc2" + TestServiceId1 = "svc1" // staked for by app1 & supplier1 + TestServiceId11 = "svc11" // staked for by app1 - TestApp1Address = "pokt106grzmkmep67pdfrm6ccl9snynryjqus6l3vct" // Generated via sample.AccAddress() + TestServiceId2 = "svc2" // staked for by app2 & supplier1 + TestServiceId22 = "svc22" // staked for by app2 + + TestServiceId12 = "svc12" // staked for by app1, app2 & supplier1 + + TestApp1Address = "pokt1mdccn4u38eyjdxkk4h0jaddw4n3c72u82m5m9e" // Generated via sample.AccAddress() TestApp1 = apptypes.Application{ Address: TestApp1Address, Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, ServiceConfigs: []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: TestServiceId1}, + Service: &sharedtypes.Service{Id: TestServiceId1}, + }, + { + Service: &sharedtypes.Service{Id: TestServiceId11}, }, { - ServiceId: &sharedtypes.ServiceId{Id: TestServiceId2}, + Service: &sharedtypes.Service{Id: TestServiceId12}, }, }, } - TestApp2Address = "pokt1dm7tr0a99ja232gzt5rjtrl7hj6z6h40669fwh" // Generated via sample.AccAddress() + TestApp2Address = "pokt133amv5suh75zwkxxcq896azvmmwszg99grvk9f" // Generated via sample.AccAddress() TestApp2 = apptypes.Application{ Address: TestApp1Address, Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, ServiceConfigs: []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: TestServiceId1}, + Service: &sharedtypes.Service{Id: TestServiceId2}, }, { - ServiceId: &sharedtypes.ServiceId{Id: TestServiceId2}, + Service: &sharedtypes.Service{Id: TestServiceId22}, + }, + { + Service: &sharedtypes.Service{Id: TestServiceId12}, }, }, } @@ -65,7 +76,7 @@ var ( Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: TestServiceId1}, + Service: &sharedtypes.Service{Id: TestServiceId1}, Endpoints: []*sharedtypes.SupplierEndpoint{ { Url: TestSupplierUrl, @@ -75,7 +86,17 @@ var ( }, }, { - ServiceId: &sharedtypes.ServiceId{Id: TestServiceId2}, + Service: &sharedtypes.Service{Id: TestServiceId2}, + Endpoints: []*sharedtypes.SupplierEndpoint{ + { + Url: TestSupplierUrl, + RpcType: sharedtypes.RPCType_GRPC, + Configs: make([]*sharedtypes.ConfigOption, 0), + }, + }, + }, + { + Service: &sharedtypes.Service{Id: TestServiceId12}, Endpoints: []*sharedtypes.SupplierEndpoint{ { Url: TestSupplierUrl, diff --git a/testutil/network/network.go b/testutil/network/network.go index c8ab3efcb..28f4eaa2f 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -111,7 +111,10 @@ func DefaultApplicationModuleGenesisState(t *testing.T, n int) *apptypes.Genesis Stake: &stake, ServiceConfigs: []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: fmt.Sprintf("svc%d", i)}, + Service: &sharedtypes.Service{Id: fmt.Sprintf("svc%d", i)}, + }, + { + Service: &sharedtypes.Service{Id: fmt.Sprintf("svc%d%d", i, i)}, }, }, } @@ -152,7 +155,7 @@ func DefaultSupplierModuleGenesisState(t *testing.T, n int) *suppliertypes.Genes Stake: &stake, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: fmt.Sprintf("svc%d", i)}, + Service: &sharedtypes.Service{Id: fmt.Sprintf("svc%d", i)}, Endpoints: []*sharedtypes.SupplierEndpoint{ { Url: fmt.Sprintf("http://localhost:%d", i), diff --git a/x/application/client/cli/query_application.go b/x/application/client/cli/query_application.go index 61a5eb35b..4fbf32228 100644 --- a/x/application/client/cli/query_application.go +++ b/x/application/client/cli/query_application.go @@ -46,7 +46,7 @@ func CmdListApplication() *cobra.Command { func CmdShowApplication() *cobra.Command { cmd := &cobra.Command{ - Use: "show-application [address]", + Use: "show-application ", Short: "shows a application", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) (err error) { diff --git a/x/application/client/cli/tx_delegate_to_gateway.go b/x/application/client/cli/tx_delegate_to_gateway.go index b27562215..f1363e6db 100644 --- a/x/application/client/cli/tx_delegate_to_gateway.go +++ b/x/application/client/cli/tx_delegate_to_gateway.go @@ -15,7 +15,7 @@ var _ = strconv.Itoa(0) func CmdDelegateToGateway() *cobra.Command { cmd := &cobra.Command{ - Use: "delegate-to-gateway [gateway address]", + Use: "delegate-to-gateway ", Short: "Delegate an application to a gateway", Long: `Delegate an application to the gateway with the provided address. This is a broadcast operation that delegates authority to the gateway specified to sign relays requests for the application, allowing the gateway diff --git a/x/application/client/cli/tx_stake_application.go b/x/application/client/cli/tx_stake_application.go index 86ba62893..2909eaf8e 100644 --- a/x/application/client/cli/tx_stake_application.go +++ b/x/application/client/cli/tx_stake_application.go @@ -21,7 +21,7 @@ func CmdStakeApplication() *cobra.Command { // TODO_HACK: For now we are only specifying the service IDs as a list of of strings separated by commas. // This needs to be expand to specify the full ApplicationServiceConfig. Furthermore, providing a flag to // a file where ApplicationServiceConfig specifying full service configurations in the CLI by providing a flag that accepts a JSON string - Use: "stake-application [amount] [svcId1,svcId2,...,svcIdN]", + Use: "stake-application ", Short: "Stake an application", Long: `Stake an application with the provided parameters. This is a broadcast operation that will stake the tokens and serviceIds and associate them with the application specified by the 'from' address. diff --git a/x/application/client/cli/tx_unstake_application.go b/x/application/client/cli/tx_unstake_application.go index 81011d0e0..c602def16 100644 --- a/x/application/client/cli/tx_unstake_application.go +++ b/x/application/client/cli/tx_unstake_application.go @@ -16,7 +16,7 @@ var _ = strconv.Itoa(0) func CmdUnstakeApplication() *cobra.Command { // fromAddress & signature is retrieved via `flags.FlagFrom` in the `clientCtx` cmd := &cobra.Command{ - Use: "unstake-application [amount]", + Use: "unstake-application", Short: "Unstake an application", Long: `Unstake an application. This is a broadcast operation that will unstake the application specified by the 'from' address. diff --git a/x/application/genesis_test.go b/x/application/genesis_test.go index 51d1f7ec9..74ac91f37 100644 --- a/x/application/genesis_test.go +++ b/x/application/genesis_test.go @@ -24,7 +24,7 @@ func TestGenesis(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, ServiceConfigs: []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: "svc1"}, + Service: &sharedtypes.Service{Id: "svc1"}, }, }, }, @@ -33,7 +33,7 @@ func TestGenesis(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, ServiceConfigs: []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: "svc2"}, + Service: &sharedtypes.Service{Id: "svc2"}, }, }, }, diff --git a/x/application/keeper/application_test.go b/x/application/keeper/application_test.go index 0fd7d7ea1..6af5e3d26 100644 --- a/x/application/keeper/application_test.go +++ b/x/application/keeper/application_test.go @@ -33,7 +33,7 @@ func createNApplication(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.A app.Stake = &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(int64(i))} app.ServiceConfigs = []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: fmt.Sprintf("svc%d", i)}, + Service: &sharedtypes.Service{Id: fmt.Sprintf("svc%d", i)}, }, } keeper.SetApplication(ctx, *app) diff --git a/x/application/keeper/msg_server_delegate_to_gateway_test.go b/x/application/keeper/msg_server_delegate_to_gateway_test.go index 2e48edf5f..80e0b586a 100644 --- a/x/application/keeper/msg_server_delegate_to_gateway_test.go +++ b/x/application/keeper/msg_server_delegate_to_gateway_test.go @@ -36,7 +36,7 @@ func TestMsgServer_DelegateToGateway_SuccessfullyDelegate(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: "svc1"}, + Service: &sharedtypes.Service{Id: "svc1"}, }, }, } @@ -100,7 +100,7 @@ func TestMsgServer_DelegateToGateway_FailDuplicate(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: "svc1"}, + Service: &sharedtypes.Service{Id: "svc1"}, }, }, } @@ -158,7 +158,7 @@ func TestMsgServer_DelegateToGateway_FailGatewayNotStaked(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: "svc1"}, + Service: &sharedtypes.Service{Id: "svc1"}, }, }, } @@ -203,7 +203,7 @@ func TestMsgServer_DelegateToGateway_FailMaxReached(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: "svc1"}, + Service: &sharedtypes.Service{Id: "svc1"}, }, }, } diff --git a/x/application/keeper/msg_server_stake_application_test.go b/x/application/keeper/msg_server_stake_application_test.go index 3b67cd20c..d3e858987 100644 --- a/x/application/keeper/msg_server_stake_application_test.go +++ b/x/application/keeper/msg_server_stake_application_test.go @@ -31,7 +31,7 @@ func TestMsgServer_StakeApplication_SuccessfulCreateAndUpdate(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: "svc1"}, + Service: &sharedtypes.Service{Id: "svc1"}, }, }, } @@ -46,7 +46,7 @@ func TestMsgServer_StakeApplication_SuccessfulCreateAndUpdate(t *testing.T) { require.Equal(t, addr, appFound.Address) require.Equal(t, int64(100), appFound.Stake.Amount.Int64()) require.Len(t, appFound.ServiceConfigs, 1) - require.Equal(t, "svc1", appFound.ServiceConfigs[0].ServiceId.Id) + require.Equal(t, "svc1", appFound.ServiceConfigs[0].Service.Id) // Prepare an updated application with a higher stake and another service updateStakeMsg := &types.MsgStakeApplication{ @@ -54,10 +54,10 @@ func TestMsgServer_StakeApplication_SuccessfulCreateAndUpdate(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(200)}, Services: []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: "svc1"}, + Service: &sharedtypes.Service{Id: "svc1"}, }, { - ServiceId: &sharedtypes.ServiceId{Id: "svc2"}, + Service: &sharedtypes.Service{Id: "svc2"}, }, }, } @@ -69,8 +69,8 @@ func TestMsgServer_StakeApplication_SuccessfulCreateAndUpdate(t *testing.T) { require.True(t, isAppFound) require.Equal(t, int64(200), appFound.Stake.Amount.Int64()) require.Len(t, appFound.ServiceConfigs, 2) - require.Equal(t, "svc1", appFound.ServiceConfigs[0].ServiceId.Id) - require.Equal(t, "svc2", appFound.ServiceConfigs[1].ServiceId.Id) + require.Equal(t, "svc1", appFound.ServiceConfigs[0].Service.Id) + require.Equal(t, "svc2", appFound.ServiceConfigs[1].Service.Id) } func TestMsgServer_StakeApplication_FailRestakingDueToInvalidServices(t *testing.T) { @@ -86,7 +86,7 @@ func TestMsgServer_StakeApplication_FailRestakingDueToInvalidServices(t *testing Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: "svc1"}, + Service: &sharedtypes.Service{Id: "svc1"}, }, }, } @@ -111,7 +111,7 @@ func TestMsgServer_StakeApplication_FailRestakingDueToInvalidServices(t *testing require.True(t, isAppFound) require.Equal(t, appAddr, app.Address) require.Len(t, app.ServiceConfigs, 1) - require.Equal(t, "svc1", app.ServiceConfigs[0].ServiceId.Id) + require.Equal(t, "svc1", app.ServiceConfigs[0].Service.Id) // Prepare the application stake message with an invalid service ID updateStakeMsg = &types.MsgStakeApplication{ @@ -119,7 +119,7 @@ func TestMsgServer_StakeApplication_FailRestakingDueToInvalidServices(t *testing Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: "svc1 INVALID ! & *"}, + Service: &sharedtypes.Service{Id: "svc1 INVALID ! & *"}, }, }, } @@ -133,7 +133,7 @@ func TestMsgServer_StakeApplication_FailRestakingDueToInvalidServices(t *testing require.True(t, isAppFound) require.Equal(t, appAddr, app.Address) require.Len(t, app.ServiceConfigs, 1) - require.Equal(t, "svc1", app.ServiceConfigs[0].ServiceId.Id) + require.Equal(t, "svc1", app.ServiceConfigs[0].Service.Id) } func TestMsgServer_StakeApplication_FailLoweringStake(t *testing.T) { @@ -148,7 +148,7 @@ func TestMsgServer_StakeApplication_FailLoweringStake(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: "svc1"}, + Service: &sharedtypes.Service{Id: "svc1"}, }, }, } @@ -165,7 +165,7 @@ func TestMsgServer_StakeApplication_FailLoweringStake(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(50)}, Services: []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: "svc1"}, + Service: &sharedtypes.Service{Id: "svc1"}, }, }, } diff --git a/x/application/keeper/msg_server_undelegate_from_gateway_test.go b/x/application/keeper/msg_server_undelegate_from_gateway_test.go index 30824a6d2..7a3b8283d 100644 --- a/x/application/keeper/msg_server_undelegate_from_gateway_test.go +++ b/x/application/keeper/msg_server_undelegate_from_gateway_test.go @@ -39,7 +39,7 @@ func TestMsgServer_UndelegateFromGateway_SuccessfullyUndelegate(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: "svc1"}, + Service: &sharedtypes.Service{Id: "svc1"}, }, }, } @@ -113,7 +113,7 @@ func TestMsgServer_UndelegateFromGateway_FailNotDelegated(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: "svc1"}, + Service: &sharedtypes.Service{Id: "svc1"}, }, }, } @@ -174,7 +174,7 @@ func TestMsgServer_UndelegateFromGateway_SuccessfullyUndelegateFromUnstakedGatew Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: "svc1"}, + Service: &sharedtypes.Service{Id: "svc1"}, }, }, } diff --git a/x/application/keeper/msg_server_unstake_application_test.go b/x/application/keeper/msg_server_unstake_application_test.go index fece27bd0..4d23ff0a0 100644 --- a/x/application/keeper/msg_server_unstake_application_test.go +++ b/x/application/keeper/msg_server_unstake_application_test.go @@ -32,7 +32,7 @@ func TestMsgServer_UnstakeApplication_Success(t *testing.T) { Stake: &initialStake, Services: []*sharedtypes.ApplicationServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: "svc1"}, + Service: &sharedtypes.Service{Id: "svc1"}, }, }, } diff --git a/x/application/types/genesis_test.go b/x/application/types/genesis_test.go index 01dd9c174..3e7ce0361 100644 --- a/x/application/types/genesis_test.go +++ b/x/application/types/genesis_test.go @@ -15,13 +15,13 @@ func TestGenesisState_Validate(t *testing.T) { addr1 := sample.AccAddress() stake1 := sdk.NewCoin("upokt", sdk.NewInt(100)) svc1AppConfig := &sharedtypes.ApplicationServiceConfig{ - ServiceId: &sharedtypes.ServiceId{Id: "svc1"}, + Service: &sharedtypes.Service{Id: "svc1"}, } addr2 := sample.AccAddress() stake2 := sdk.NewCoin("upokt", sdk.NewInt(100)) svc2AppConfig := &sharedtypes.ApplicationServiceConfig{ - ServiceId: &sharedtypes.ServiceId{Id: "svc2"}, + Service: &sharedtypes.Service{Id: "svc2"}, } emptyDelegatees := make([]string, 0) @@ -314,7 +314,7 @@ func TestGenesisState_Validate(t *testing.T) { Address: addr1, Stake: &stake1, ServiceConfigs: []*sharedtypes.ApplicationServiceConfig{ - {ServiceId: &sharedtypes.ServiceId{Id: "12345678901"}}, + {Service: &sharedtypes.Service{Id: "12345678901"}}, }, DelegateeGatewayAddresses: emptyDelegatees, }, @@ -333,7 +333,7 @@ func TestGenesisState_Validate(t *testing.T) { Address: addr1, Stake: &stake1, ServiceConfigs: []*sharedtypes.ApplicationServiceConfig{ - {ServiceId: &sharedtypes.ServiceId{ + {Service: &sharedtypes.Service{ Id: "123", Name: "abcdefghijklmnopqrstuvwxyzab-abcdefghijklmnopqrstuvwxyzab", }}, @@ -355,7 +355,7 @@ func TestGenesisState_Validate(t *testing.T) { Address: addr1, Stake: &stake1, ServiceConfigs: []*sharedtypes.ApplicationServiceConfig{ - {ServiceId: &sharedtypes.ServiceId{Id: "12 45 !"}}, + {Service: &sharedtypes.Service{Id: "12 45 !"}}, }, DelegateeGatewayAddresses: emptyDelegatees, }, diff --git a/x/application/types/message_stake_application.go b/x/application/types/message_stake_application.go index 9dba9eebf..a70a54815 100644 --- a/x/application/types/message_stake_application.go +++ b/x/application/types/message_stake_application.go @@ -23,7 +23,7 @@ func NewMsgStakeApplication( appServiceConfigs := make([]*sharedtypes.ApplicationServiceConfig, len(serviceIds)) for idx, serviceId := range serviceIds { appServiceConfigs[idx] = &sharedtypes.ApplicationServiceConfig{ - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: serviceId, }, } diff --git a/x/application/types/message_stake_application_test.go b/x/application/types/message_stake_application_test.go index c14119898..0d155f50c 100644 --- a/x/application/types/message_stake_application_test.go +++ b/x/application/types/message_stake_application_test.go @@ -23,7 +23,7 @@ func TestMsgStakeApplication_ValidateBasic(t *testing.T) { Address: "invalid_address", // Stake explicitly nil Services: []*sharedtypes.ApplicationServiceConfig{ - {ServiceId: &sharedtypes.ServiceId{Id: "svc1"}}, + {Service: &sharedtypes.Service{Id: "svc1"}}, }, }, err: ErrAppInvalidAddress, @@ -36,7 +36,7 @@ func TestMsgStakeApplication_ValidateBasic(t *testing.T) { Address: sample.AccAddress(), // Stake explicitly nil Services: []*sharedtypes.ApplicationServiceConfig{ - {ServiceId: &sharedtypes.ServiceId{Id: "svc1"}}, + {Service: &sharedtypes.Service{Id: "svc1"}}, }, }, err: ErrAppInvalidStake, @@ -46,7 +46,7 @@ func TestMsgStakeApplication_ValidateBasic(t *testing.T) { Address: sample.AccAddress(), Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.ApplicationServiceConfig{ - {ServiceId: &sharedtypes.ServiceId{Id: "svc1"}}, + {Service: &sharedtypes.Service{Id: "svc1"}}, }, }, }, { @@ -55,7 +55,7 @@ func TestMsgStakeApplication_ValidateBasic(t *testing.T) { Address: sample.AccAddress(), Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(0)}, Services: []*sharedtypes.ApplicationServiceConfig{ - {ServiceId: &sharedtypes.ServiceId{Id: "svc1"}}, + {Service: &sharedtypes.Service{Id: "svc1"}}, }, }, err: ErrAppInvalidStake, @@ -65,7 +65,7 @@ func TestMsgStakeApplication_ValidateBasic(t *testing.T) { Address: sample.AccAddress(), Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(-100)}, Services: []*sharedtypes.ApplicationServiceConfig{ - {ServiceId: &sharedtypes.ServiceId{Id: "svc1"}}, + {Service: &sharedtypes.Service{Id: "svc1"}}, }, }, err: ErrAppInvalidStake, @@ -75,7 +75,7 @@ func TestMsgStakeApplication_ValidateBasic(t *testing.T) { Address: sample.AccAddress(), Stake: &sdk.Coin{Denom: "invalid", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.ApplicationServiceConfig{ - {ServiceId: &sharedtypes.ServiceId{Id: "svc1"}}, + {Service: &sharedtypes.Service{Id: "svc1"}}, }, }, err: ErrAppInvalidStake, @@ -85,7 +85,7 @@ func TestMsgStakeApplication_ValidateBasic(t *testing.T) { Address: sample.AccAddress(), Stake: &sdk.Coin{Denom: "", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.ApplicationServiceConfig{ - {ServiceId: &sharedtypes.ServiceId{Id: "svc1"}}, + {Service: &sharedtypes.Service{Id: "svc1"}}, }, }, err: ErrAppInvalidStake, @@ -98,8 +98,8 @@ func TestMsgStakeApplication_ValidateBasic(t *testing.T) { Address: sample.AccAddress(), Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.ApplicationServiceConfig{ - {ServiceId: &sharedtypes.ServiceId{Id: "svc1"}}, - {ServiceId: &sharedtypes.ServiceId{Id: "svc2"}}, + {Service: &sharedtypes.Service{Id: "svc1"}}, + {Service: &sharedtypes.Service{Id: "svc2"}}, }, }, }, @@ -127,7 +127,7 @@ func TestMsgStakeApplication_ValidateBasic(t *testing.T) { Address: sample.AccAddress(), Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.ApplicationServiceConfig{ - {ServiceId: &sharedtypes.ServiceId{Id: "123456790"}}, + {Service: &sharedtypes.Service{Id: "123456790"}}, }, }, err: ErrAppInvalidServiceConfigs, @@ -138,7 +138,7 @@ func TestMsgStakeApplication_ValidateBasic(t *testing.T) { Address: sample.AccAddress(), Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.ApplicationServiceConfig{ - {ServiceId: &sharedtypes.ServiceId{ + {Service: &sharedtypes.Service{ Id: "123", Name: "abcdefghijklmnopqrstuvwxyzab-abcdefghijklmnopqrstuvwxyzab", }}, @@ -152,7 +152,7 @@ func TestMsgStakeApplication_ValidateBasic(t *testing.T) { Address: sample.AccAddress(), Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.ApplicationServiceConfig{ - {ServiceId: &sharedtypes.ServiceId{Id: "12 45 !"}}, + {Service: &sharedtypes.Service{Id: "12 45 !"}}, }, }, err: ErrAppInvalidServiceConfigs, diff --git a/x/gateway/client/cli/helpers_test.go b/x/gateway/client/cli/helpers_test.go index 927212a46..cf2ccf899 100644 --- a/x/gateway/client/cli/helpers_test.go +++ b/x/gateway/client/cli/helpers_test.go @@ -1,14 +1,24 @@ package cli_test import ( + "strconv" "testing" + "github.com/stretchr/testify/require" + + "github.com/pokt-network/poktroll/cmd/pocketd/cmd" "github.com/pokt-network/poktroll/testutil/network" "github.com/pokt-network/poktroll/x/gateway/types" - - "github.com/stretchr/testify/require" ) +// Dummy variable to avoid unused import error. +var _ = strconv.IntSize + +// init initializes the SDK configuration. +func init() { + cmd.InitSDKConfig() +} + // networkWithGatewayObjects creates a network with a populated gateway state of n gateway objects func networkWithGatewayObjects(t *testing.T, n int) (*network.Network, []types.Gateway) { t.Helper() diff --git a/x/gateway/client/cli/query_gateway.go b/x/gateway/client/cli/query_gateway.go index 30076ed22..124c515c8 100644 --- a/x/gateway/client/cli/query_gateway.go +++ b/x/gateway/client/cli/query_gateway.go @@ -46,7 +46,7 @@ func CmdListGateway() *cobra.Command { func CmdShowGateway() *cobra.Command { cmd := &cobra.Command{ - Use: "show-gateway [address]", + Use: "show-gateway ", Short: "shows a gateway", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) (err error) { diff --git a/x/gateway/client/cli/tx_stake_gateway.go b/x/gateway/client/cli/tx_stake_gateway.go index 97e93c812..3c4d29a30 100644 --- a/x/gateway/client/cli/tx_stake_gateway.go +++ b/x/gateway/client/cli/tx_stake_gateway.go @@ -3,20 +3,20 @@ package cli import ( "strconv" - "github.com/pokt-network/poktroll/x/gateway/types" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/spf13/cobra" + + "github.com/pokt-network/poktroll/x/gateway/types" ) var _ = strconv.Itoa(0) func CmdStakeGateway() *cobra.Command { cmd := &cobra.Command{ - Use: "stake-gateway [amount]", + Use: "stake-gateway ", Short: "Stake a gateway", Long: `Stake a gateway with the provided parameters. This is a broadcast operation that will stake the tokens and associate them with the gateway specified by the 'from' address. diff --git a/x/gateway/client/cli/tx_unstake_gateway.go b/x/gateway/client/cli/tx_unstake_gateway.go index bd2d38ebe..e97406495 100644 --- a/x/gateway/client/cli/tx_unstake_gateway.go +++ b/x/gateway/client/cli/tx_unstake_gateway.go @@ -16,7 +16,7 @@ var _ = strconv.Itoa(0) func CmdUnstakeGateway() *cobra.Command { // fromAddress & signature is retrieved via `flags.FlagFrom` in the `clientCtx` cmd := &cobra.Command{ - Use: "unstake-gateway [amount]", + Use: "unstake-gateway ", Short: "Unstake a gateway", Long: `Unstake a gateway. This is a broadcast operation that will unstake the gateway specified by the 'from' address. diff --git a/x/session/client/cli/helpers_test.go b/x/session/client/cli/helpers_test.go new file mode 100644 index 000000000..484bca4db --- /dev/null +++ b/x/session/client/cli/helpers_test.go @@ -0,0 +1,44 @@ +// Package cli_test provides unit tests for the CLI functionality. +package cli_test + +import ( + "strconv" + "testing" + + "github.com/pokt-network/poktroll/cmd/pocketd/cmd" + "github.com/pokt-network/poktroll/testutil/network" + apptypes "github.com/pokt-network/poktroll/x/application/types" + sharedtypes "github.com/pokt-network/poktroll/x/shared/types" + suppliertypes "github.com/pokt-network/poktroll/x/supplier/types" + "github.com/stretchr/testify/require" +) + +// Dummy variable to avoid unused import error. +var _ = strconv.IntSize + +// init initializes the SDK configuration. +func init() { + cmd.InitSDKConfig() +} + +// networkWithApplicationsAndSupplier creates a new network with a given number of supplier & application objects. +// It returns the network and a slice of the created supplier & application objects. +func networkWithApplicationsAndSupplier(t *testing.T, n int) (*network.Network, []sharedtypes.Supplier, []apptypes.Application) { + t.Helper() + cfg := network.DefaultConfig() + + // Prepare the application genesis state + applicationGenesisState := network.DefaultApplicationModuleGenesisState(t, n) + buf, err := cfg.Codec.MarshalJSON(applicationGenesisState) + require.NoError(t, err) + cfg.GenesisState[apptypes.ModuleName] = buf + + // Prepare the supplier genesis state + supplierGenesisState := network.DefaultSupplierModuleGenesisState(t, n) + buf, err = cfg.Codec.MarshalJSON(supplierGenesisState) + require.NoError(t, err) + cfg.GenesisState[suppliertypes.ModuleName] = buf + + // Start the network + return network.New(t, cfg), supplierGenesisState.SupplierList, applicationGenesisState.ApplicationList +} diff --git a/x/session/client/cli/query_get_session.go b/x/session/client/cli/query_get_session.go index 1c21aa881..41b441de7 100644 --- a/x/session/client/cli/query_get_session.go +++ b/x/session/client/cli/query_get_session.go @@ -1,6 +1,7 @@ package cli import ( + "fmt" "strconv" "github.com/cosmos/cosmos-sdk/client" @@ -12,26 +13,49 @@ import ( var _ = strconv.Itoa(0) -// TODO(@Olshansk): Implement the CLI component of `GetSession`. func CmdGetSession() *cobra.Command { cmd := &cobra.Command{ - Use: "get-session", + Use: "get-session [block_height]", Short: "Query get-session", - Args: cobra.ExactArgs(0), + Long: `Query the session data for a specific (app, service, height) tuple. + +[block_height] is optional. If unspecified, or set to 0, it defaults to the latest height of the node being queried. + +This is a query operation that will not result in a state transition but simply gives a view into the chain state. + +Example: +$ pocketd --home=$(POCKETD_HOME) q session get-session pokt1mrqt5f7qh8uxs27cjm9t7v9e74a9vvdnq5jva4 svc1 42 --node $(POCKET_NODE)`, + Args: cobra.RangeArgs(2, 3), RunE: func(cmd *cobra.Command, args []string) (err error) { + appAddressString := args[0] + serviceIdString := args[1] + blockHeightString := "0" // 0 will default to latest height + if len(args) == 3 { + blockHeightString = args[2] + } + + blockHeight, err := strconv.ParseInt(blockHeightString, 10, 64) + if err != nil { + return fmt.Errorf("couldn't convert block height to int: %s; (%v)", blockHeightString, err) + } + + getSessionReq := types.NewQueryGetSessionRequest(appAddressString, serviceIdString, blockHeight) + if err := getSessionReq.ValidateBasic(); err != nil { + return err + } + clientCtx, err := client.GetClientQueryContext(cmd) if err != nil { return err } queryClient := types.NewQueryClient(clientCtx) - req := &types.QueryGetSessionRequest{} - res, err := queryClient.GetSession(cmd.Context(), req) + getSessionRes, err := queryClient.GetSession(cmd.Context(), getSessionReq) if err != nil { return err } - return clientCtx.PrintProto(res) + return clientCtx.PrintProto(getSessionRes) }, } diff --git a/x/session/client/cli/query_get_session_test.go b/x/session/client/cli/query_get_session_test.go new file mode 100644 index 000000000..480bafa48 --- /dev/null +++ b/x/session/client/cli/query_get_session_test.go @@ -0,0 +1,197 @@ +package cli_test + +import ( + "fmt" + "testing" + + sdkerrors "cosmossdk.io/errors" + tmcli "github.com/cometbft/cometbft/libs/cli" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + "github.com/gogo/status" + "github.com/stretchr/testify/require" + + "github.com/pokt-network/poktroll/x/session/client/cli" + sessiontypes "github.com/pokt-network/poktroll/x/session/types" +) + +func TestCLI_GetSession(t *testing.T) { + // Prepare the network + net, suppliers, applications := networkWithApplicationsAndSupplier(t, 2) + _, err := net.WaitForHeight(10) // Wait for a sufficiently high block height to ensure the staking transactions have been processed + require.NoError(t, err) + val := net.Validators[0] + ctx := val.ClientCtx + + // Sanity check the application configs are what we expect them to be + appSvc0 := applications[0] + appSvc1 := applications[1] + + require.Len(t, appSvc0.ServiceConfigs, 2) + require.Len(t, appSvc1.ServiceConfigs, 2) + + require.Equal(t, appSvc0.ServiceConfigs[0].Service.Id, "svc0") // svc0 has a supplier + require.Equal(t, appSvc0.ServiceConfigs[1].Service.Id, "svc00") // svc00 doesn't have a supplier + require.Equal(t, appSvc1.ServiceConfigs[0].Service.Id, "svc1") // svc1 has a supplier + require.Equal(t, appSvc1.ServiceConfigs[1].Service.Id, "svc11") // svc11 doesn't have a supplier + + // Sanity check the supplier configs are what we expect them to be + supplierSvc0 := suppliers[0] // supplier for svc0 + supplierSvc1 := suppliers[1] // supplier for svc1 + + require.Len(t, supplierSvc0.Services, 1) + require.Len(t, supplierSvc1.Services, 1) + + require.Equal(t, supplierSvc0.Services[0].Service.Id, "svc0") + require.Equal(t, supplierSvc1.Services[0].Service.Id, "svc1") + + // Prepare the test cases + tests := []struct { + desc string + + appAddress string + serviceId string + blockHeight int64 + + expectedErr *sdkerrors.Error + expectedNumSuppliers int + }{ + // Valid requests + { + desc: "valid - block height specified and is zero", + + appAddress: appSvc0.Address, + serviceId: "svc0", + blockHeight: 0, + + expectedErr: nil, + expectedNumSuppliers: 1, + }, + { + desc: "valid - block height specified and is greater than zero", + + appAddress: appSvc1.Address, + serviceId: "svc1", + blockHeight: 10, + + expectedErr: nil, + expectedNumSuppliers: 1, + }, + { + desc: "valid - block height unspecified and defaults to 0", + + appAddress: appSvc0.Address, + serviceId: "svc0", + // blockHeight: intentionally omitted, + + expectedErr: nil, + expectedNumSuppliers: 1, + }, + + // Invalid requests - incompatible state + { + desc: "invalid - app not staked for service", + + appAddress: appSvc0.Address, + serviceId: "svc9001", // appSvc0 is only staked for svc0 (has supplier) and svc00 (doesn't have supplier) and is not staked for service over 9000 + blockHeight: 0, + + expectedErr: sessiontypes.ErrSessionAppNotStakedForService, + }, + { + desc: "invalid - no suppliers staked for service", + + appAddress: appSvc0.Address, // dynamically getting address from applications + serviceId: "svc00", // appSvc0 is only staked for svc0 (has supplier) and svc00 (doesn't have supplier) + blockHeight: 0, + + expectedErr: sessiontypes.ErrSessionSuppliersNotFound, + }, + { + desc: "invalid - block height is in the future", + + appAddress: appSvc0.Address, // dynamically getting address from applications + serviceId: "svc0", + blockHeight: 9001, // block height over 9000 is greater than the context height of 10 + + expectedErr: sessiontypes.ErrSessionInvalidBlockHeight, + }, + + // Invalid requests - bad app address input + { + desc: "invalid - invalid appAddress", + + appAddress: "invalidAddress", // providing a deliberately invalid address + serviceId: "svc0", + blockHeight: 0, + + expectedErr: sessiontypes.ErrSessionInvalidAppAddress, + }, + { + desc: "invalid - missing appAddress", + // appAddress: intentionally omitted + serviceId: "svc0", + blockHeight: 0, + + expectedErr: sessiontypes.ErrSessionInvalidAppAddress, + }, + + // Invalid requests - bad serviceID input + { + desc: "invalid - invalid service ID", + appAddress: appSvc0.Address, // dynamically getting address from applications + serviceId: "invalidServiceId", + blockHeight: 0, + + expectedErr: sessiontypes.ErrSessionInvalidService, + }, + { + desc: "invalid - missing service ID", + appAddress: appSvc0.Address, // dynamically getting address from applications + // serviceId: intentionally omitted + blockHeight: 0, + + expectedErr: sessiontypes.ErrSessionInvalidService, + }, + } + + // We want to use the `--output=json` flag for all tests so it's easy to unmarshal below + common := []string{ + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + } + + // Run the tests + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + // Prepare the arguments for the CLI command + args := []string{ + tt.appAddress, + tt.serviceId, + fmt.Sprintf("%d", tt.blockHeight), + } + args = append(args, common...) + + // Execute the command + getSessionOut, err := clitestutil.ExecTestCLICmd(ctx, cli.CmdGetSession(), args) + if tt.expectedErr != nil { + stat, ok := status.FromError(tt.expectedErr) + require.True(t, ok) + require.Contains(t, stat.Message(), tt.expectedErr.Error()) + return + } + require.NoError(t, err) + + var getSessionRes sessiontypes.QueryGetSessionResponse + err = net.Config.Codec.UnmarshalJSON(getSessionOut.Bytes(), &getSessionRes) + require.NoError(t, err) + require.NotNil(t, getSessionRes) + + session := getSessionRes.Session + require.NotNil(t, session) + + // Verify some data about the session + require.Equal(t, tt.appAddress, session.Application.Address) + require.Equal(t, tt.serviceId, session.Header.Service.Id) + require.Len(t, session.Suppliers, tt.expectedNumSuppliers) + }) + } +} diff --git a/x/session/keeper/query_get_session.go b/x/session/keeper/query_get_session.go index d9fd3deaf..e8931b343 100644 --- a/x/session/keeper/query_get_session.go +++ b/x/session/keeper/query_get_session.go @@ -15,9 +15,24 @@ func (k Keeper) GetSession(goCtx context.Context, req *types.QueryGetSessionRequ return nil, status.Error(codes.InvalidArgument, "invalid request") } + if err := req.ValidateBasic(); err != nil { + return nil, err + } + ctx := sdk.UnwrapSDKContext(goCtx) - sessionHydrator := NewSessionHydrator(req.ApplicationAddress, req.ServiceId.Id, req.BlockHeight) + // If block height is not specified, use the current (context's latest) block height + // Note that `GetSession` is called via the `Query` service rather than the `Msg` server. + // The former is stateful but does not lead to state transitions, while the latter one + // does. The request height depends on how much the node has synched and only acts as a read, + // while the `Msg` server handles the code flow of the validator/sequencer when a new block + // is being proposed. + blockHeight := req.BlockHeight + if blockHeight == 0 { + blockHeight = ctx.BlockHeight() + } + + sessionHydrator := NewSessionHydrator(req.ApplicationAddress, req.Service.Id, req.BlockHeight) session, err := k.HydrateSession(ctx, sessionHydrator) if err != nil { return nil, err diff --git a/x/session/keeper/query_get_session_test.go b/x/session/keeper/query_get_session_test.go index 5f15a94e9..a8b8ecedb 100644 --- a/x/session/keeper/query_get_session_test.go +++ b/x/session/keeper/query_get_session_test.go @@ -8,6 +8,7 @@ import ( "github.com/pokt-network/poktroll/cmd/pocketd/cmd" keepertest "github.com/pokt-network/poktroll/testutil/keeper" + "github.com/pokt-network/poktroll/testutil/sample" "github.com/pokt-network/poktroll/x/session/types" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" ) @@ -22,6 +23,7 @@ func init() { func TestSession_GetSession_Success(t *testing.T) { keeper, ctx := keepertest.SessionKeeper(t) + ctx = ctx.WithBlockHeight(100) // provide a sufficiently large block height to avoid errors wctx := sdk.WrapSDKContext(ctx) type test struct { @@ -45,7 +47,7 @@ func TestSession_GetSession_Success(t *testing.T) { blockHeight: 1, // Intentionally only checking a subset of the session metadata returned - expectedSessionId: "e1e51d087e447525d7beb648711eb3deaf016a8089938a158e6a0f600979370c", + expectedSessionId: "cf5bbdce56ee5a7c46c5d5482303907685a7e5dbb22703cd4a85df521b9ab6e9", expectedSessionNumber: 0, expectedNumSuppliers: 1, }, @@ -53,10 +55,9 @@ func TestSession_GetSession_Success(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - req := &types.QueryGetSessionRequest{ ApplicationAddress: tt.appAddr, - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: tt.serviceId, }, BlockHeight: 1, @@ -75,6 +76,7 @@ func TestSession_GetSession_Success(t *testing.T) { func TestSession_GetSession_Failure(t *testing.T) { keeper, ctx := keepertest.SessionKeeper(t) + ctx = ctx.WithBlockHeight(100) // provide a sufficiently large block height to avoid errors wctx := sdk.WrapSDKContext(ctx) type test struct { @@ -91,20 +93,56 @@ func TestSession_GetSession_Failure(t *testing.T) { { name: "application address does not reflected a staked application", - appAddr: "some string that is not a valid app address", + appAddr: sample.AccAddress(), // a random (valid) app address that's not staked serviceId: keepertest.TestServiceId1, blockHeight: 1, - expectedErrContains: types.ErrAppNotFound.Error(), + expectedErrContains: types.ErrSessionAppNotFound.Error(), + }, + { + name: "application staked for service that has no available suppliers", + + appAddr: keepertest.TestApp1Address, + serviceId: keepertest.TestServiceId11, + blockHeight: 1, + + expectedErrContains: types.ErrSessionSuppliersNotFound.Error(), }, { - name: "service ID does not reflect one with staked suppliers", + name: "application is valid but not staked for the specified service", appAddr: keepertest.TestApp1Address, - serviceId: "some string that is not a valid service Id", + serviceId: "svc9001", // App1 is not staked for service over 9000 blockHeight: 1, - expectedErrContains: types.ErrSuppliersNotFound.Error(), + expectedErrContains: types.ErrSessionAppNotStakedForService.Error(), + }, + { + name: "application address is invalid format", + + appAddr: "invalid_app_address", + serviceId: keepertest.TestServiceId1, + blockHeight: 1, + + expectedErrContains: types.ErrSessionInvalidAppAddress.Error(), + }, + { + name: "service ID is invalid", + + appAddr: keepertest.TestApp1Address, + serviceId: "service_id_is_too_long_to_be_valid", + blockHeight: 1, + + expectedErrContains: "invalid service in session", + }, + { + name: "negative block height", + + appAddr: keepertest.TestApp1Address, + serviceId: keepertest.TestServiceId1, + blockHeight: -1, + + expectedErrContains: "invalid block height for session being retrieved", }, } @@ -112,13 +150,12 @@ func TestSession_GetSession_Failure(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - req := &types.QueryGetSessionRequest{ ApplicationAddress: tt.appAddr, - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: tt.serviceId, }, - BlockHeight: 1, + BlockHeight: tt.blockHeight, } res, err := keeper.GetSession(wctx, req) diff --git a/x/session/keeper/session_hydrator.go b/x/session/keeper/session_hydrator.go index b6e78e2c8..7745153b4 100644 --- a/x/session/keeper/session_hydrator.go +++ b/x/session/keeper/session_hydrator.go @@ -12,6 +12,7 @@ import ( _ "golang.org/x/crypto/sha3" "github.com/pokt-network/poktroll/x/session/types" + sharedhelpers "github.com/pokt-network/poktroll/x/shared/helpers" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" ) @@ -45,7 +46,7 @@ func NewSessionHydrator( ) *sessionHydrator { sessionHeader := &types.SessionHeader{ ApplicationAddress: appAddress, - ServiceId: &sharedtypes.ServiceId{Id: serviceId}, + Service: &sharedtypes.Service{Id: serviceId}, } return &sessionHydrator{ sessionHeader: sessionHeader, @@ -61,22 +62,22 @@ func (k Keeper) HydrateSession(ctx sdk.Context, sh *sessionHydrator) (*types.Ses logger := k.Logger(ctx).With("method", "hydrateSession") if err := k.hydrateSessionMetadata(ctx, sh); err != nil { - return nil, sdkerrors.Wrapf(types.ErrHydratingSession, "failed to hydrate the session metadata: %v", err) + return nil, sdkerrors.Wrapf(types.ErrSessionHydration, "failed to hydrate the session metadata: %v", err) } logger.Debug("Finished hydrating session metadata") if err := k.hydrateSessionID(ctx, sh); err != nil { - return nil, sdkerrors.Wrapf(types.ErrHydratingSession, "failed to hydrate the session ID: %v", err) + return nil, sdkerrors.Wrapf(types.ErrSessionHydration, "failed to hydrate the session ID: %v", err) } logger.Info("Finished hydrating session ID: %s", sh.sessionHeader.SessionId) if err := k.hydrateSessionApplication(ctx, sh); err != nil { - return nil, sdkerrors.Wrapf(types.ErrHydratingSession, "failed to hydrate application for session: %v", err) + return nil, sdkerrors.Wrapf(types.ErrSessionHydration, "failed to hydrate application for session: %v", err) } logger.Debug("Finished hydrating session application: %+v", sh.session.Application) if err := k.hydrateSessionSuppliers(ctx, sh); err != nil { - return nil, sdkerrors.Wrapf(types.ErrHydratingSession, "failed to hydrate suppliers for session: %v", err) + return nil, sdkerrors.Wrapf(types.ErrSessionHydration, "failed to hydrate suppliers for session: %v", err) } logger.Debug("Finished hydrating session suppliers: %+v") @@ -90,6 +91,10 @@ func (k Keeper) HydrateSession(ctx sdk.Context, sh *sessionHydrator) (*types.Ses func (k Keeper) hydrateSessionMetadata(ctx sdk.Context, sh *sessionHydrator) error { // TODO_TECHDEBT: Add a test if `blockHeight` is ahead of the current chain or what this node is aware of + if sh.blockHeight > ctx.BlockHeight() { + return sdkerrors.Wrapf(types.ErrSessionHydration, "block height %d is ahead of the current block height %d", sh.blockHeight, ctx.BlockHeight()) + } + sh.session.NumBlocksPerSession = NumBlocksPerSession sh.session.SessionNumber = int64(sh.blockHeight / NumBlocksPerSession) sh.sessionHeader.SessionStartBlockHeight = sh.blockHeight - (sh.blockHeight % NumBlocksPerSession) @@ -105,10 +110,13 @@ func (k Keeper) hydrateSessionID(ctx sdk.Context, sh *sessionHydrator) error { prevHashBz := []byte("TODO_BLOCKER: See the comment above") appPubKeyBz := []byte(sh.sessionHeader.ApplicationAddress) - // TODO_TECHDEBT: In the future, we will need to valid that the ServiceId is a valid service depending on whether - // or not its permissioned or permissionless - // TODO(@Olshansk): Add a check to make sure `IsValidServiceName(ServiceId.Id)` returns True - serviceIdBz := []byte(sh.sessionHeader.ServiceId.Id) + // TODO_TECHDEBT: In the future, we will need to valid that the Service is a valid service depending on whether + // or not its permissioned or permissionless + + if !sharedhelpers.IsValidService(sh.sessionHeader.Service) { + return sdkerrors.Wrapf(types.ErrSessionHydration, "invalid service: %v", sh.sessionHeader.Service) + } + serviceIdBz := []byte(sh.sessionHeader.Service.Id) sessionHeightBz := make([]byte, 8) binary.LittleEndian.PutUint64(sessionHeightBz, uint64(sh.sessionHeader.SessionStartBlockHeight)) @@ -123,10 +131,17 @@ func (k Keeper) hydrateSessionID(ctx sdk.Context, sh *sessionHydrator) error { func (k Keeper) hydrateSessionApplication(ctx sdk.Context, sh *sessionHydrator) error { app, appIsFound := k.appKeeper.GetApplication(ctx, sh.sessionHeader.ApplicationAddress) if !appIsFound { - return sdkerrors.Wrapf(types.ErrAppNotFound, "could not find app with address: %s at height %d", sh.sessionHeader.ApplicationAddress, sh.sessionHeader.SessionStartBlockHeight) + return sdkerrors.Wrapf(types.ErrSessionAppNotFound, "could not find app with address: %s at height %d", sh.sessionHeader.ApplicationAddress, sh.sessionHeader.SessionStartBlockHeight) } - sh.session.Application = &app - return nil + + for _, appServiceConfig := range app.ServiceConfigs { + if appServiceConfig.Service.Id == sh.sessionHeader.Service.Id { + sh.session.Application = &app + return nil + } + } + + return sdkerrors.Wrapf(types.ErrSessionAppNotStakedForService, "application %s not staked for service %s", sh.sessionHeader.ApplicationAddress, sh.sessionHeader.Service.Id) } // hydrateSessionSuppliers finds the suppliers that are staked at the session height and populates the session with them @@ -144,7 +159,7 @@ func (k Keeper) hydrateSessionSuppliers(ctx sdk.Context, sh *sessionHydrator) er for _, supplier := range suppliers { // TODO_OPTIMIZE: If `supplier.Services` was a map[string]struct{}, we could eliminate `slices.Contains()`'s loop for _, supplierServiceConfig := range supplier.Services { - if supplierServiceConfig.ServiceId.Id == sh.sessionHeader.ServiceId.Id { + if supplierServiceConfig.Service.Id == sh.sessionHeader.Service.Id { candidateSuppliers = append(candidateSuppliers, &supplier) break } @@ -153,7 +168,7 @@ func (k Keeper) hydrateSessionSuppliers(ctx sdk.Context, sh *sessionHydrator) er if len(candidateSuppliers) == 0 { logger.Error("[ERROR] no suppliers found for session") - return sdkerrors.Wrapf(types.ErrSuppliersNotFound, "could not find suppliers for service %s at height %d", sh.sessionHeader.ServiceId, sh.sessionHeader.SessionStartBlockHeight) + return sdkerrors.Wrapf(types.ErrSessionSuppliersNotFound, "could not find suppliers for service %s at height %d", sh.sessionHeader.Service, sh.sessionHeader.SessionStartBlockHeight) } if len(candidateSuppliers) < NumSupplierPerSession { diff --git a/x/session/keeper/session_hydrator_test.go b/x/session/keeper/session_hydrator_test.go index c50d653ab..90a62575d 100644 --- a/x/session/keeper/session_hydrator_test.go +++ b/x/session/keeper/session_hydrator_test.go @@ -13,6 +13,7 @@ import ( func TestSession_HydrateSession_Success_BaseCase(t *testing.T) { sessionKeeper, ctx := keepertest.SessionKeeper(t) + ctx = ctx.WithBlockHeight(100) // provide a sufficiently large block height to avoid errors blockHeight := int64(10) sessionHydrator := keeper.NewSessionHydrator(keepertest.TestApp1Address, keepertest.TestServiceId1, blockHeight) @@ -22,84 +23,101 @@ func TestSession_HydrateSession_Success_BaseCase(t *testing.T) { // Check the header sessionHeader := session.Header require.Equal(t, keepertest.TestApp1Address, sessionHeader.ApplicationAddress) - require.Equal(t, keepertest.TestServiceId1, sessionHeader.ServiceId.Id) - require.Equal(t, "", sessionHeader.ServiceId.Name) + require.Equal(t, keepertest.TestServiceId1, sessionHeader.Service.Id) + require.Equal(t, "", sessionHeader.Service.Name) require.Equal(t, int64(8), sessionHeader.SessionStartBlockHeight) - require.Equal(t, "23f037a10f9d51d020d27763c42dd391d7e71765016d95d0d61f36c4a122efd0", sessionHeader.SessionId) + require.Equal(t, "5481d5ca2ddb15dc5edb792b8e20ba9c7d516a74475fc5feba6b6aeb95a26f58", sessionHeader.SessionId) // Check the session require.Equal(t, int64(4), session.NumBlocksPerSession) - require.Equal(t, "23f037a10f9d51d020d27763c42dd391d7e71765016d95d0d61f36c4a122efd0", session.SessionId) + require.Equal(t, "5481d5ca2ddb15dc5edb792b8e20ba9c7d516a74475fc5feba6b6aeb95a26f58", session.SessionId) require.Equal(t, int64(2), session.SessionNumber) // Check the application app := session.Application require.Equal(t, keepertest.TestApp1Address, app.Address) - require.Len(t, app.ServiceConfigs, 2) + require.Len(t, app.ServiceConfigs, 3) // Check the suppliers suppliers := session.Suppliers require.Len(t, suppliers, 1) supplier := suppliers[0] require.Equal(t, keepertest.TestSupplierAddress, supplier.Address) - require.Len(t, supplier.Services, 2) + require.Len(t, supplier.Services, 3) } func TestSession_HydrateSession_Metadata(t *testing.T) { type test struct { - name string + desc string blockHeight int64 expectedNumBlocksPerSession int64 expectedSessionNumber int64 expectedSessionStartBlock int64 + errExpected error } // TODO_TECHDEBT: Extend these tests once `NumBlocksPerSession` is configurable. // Currently assumes NumBlocksPerSession=4 tests := []test{ { - name: "blockHeight = 0", + desc: "blockHeight = 0", blockHeight: 0, expectedNumBlocksPerSession: 4, expectedSessionNumber: 0, expectedSessionStartBlock: 0, + errExpected: nil, }, { - name: "blockHeight = 1", + desc: "blockHeight = 1", blockHeight: 1, expectedNumBlocksPerSession: 4, expectedSessionNumber: 0, expectedSessionStartBlock: 0, + errExpected: nil, }, { - name: "blockHeight = sessionHeight", + desc: "blockHeight = sessionHeight", blockHeight: 4, expectedNumBlocksPerSession: 4, expectedSessionNumber: 1, expectedSessionStartBlock: 4, + errExpected: nil, }, { - name: "blockHeight != sessionHeight", + desc: "blockHeight != sessionHeight", blockHeight: 5, expectedNumBlocksPerSession: 4, expectedSessionNumber: 1, expectedSessionStartBlock: 4, + errExpected: nil, + }, + { + desc: "blockHeight > contextHeight", + blockHeight: 9001, // block height over 9000 is too height given that the context height is 100 + + errExpected: types.ErrSessionHydration, }, } appAddr := keepertest.TestApp1Address serviceId := keepertest.TestServiceId1 sessionKeeper, ctx := keepertest.SessionKeeper(t) + ctx = ctx.WithBlockHeight(100) // provide a sufficiently large block height to avoid errors for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { + t.Run(tt.desc, func(t *testing.T) { sessionHydrator := keeper.NewSessionHydrator(appAddr, serviceId, tt.blockHeight) session, err := sessionKeeper.HydrateSession(ctx, sessionHydrator) + + if tt.errExpected != nil { + require.ErrorIs(t, tt.errExpected, err) + return + } require.NoError(t, err) require.Equal(t, tt.expectedNumBlocksPerSession, session.NumBlocksPerSession) @@ -111,7 +129,7 @@ func TestSession_HydrateSession_Metadata(t *testing.T) { func TestSession_HydrateSession_SessionId(t *testing.T) { type test struct { - name string + desc string blockHeight1 int64 blockHeight2 int64 @@ -130,7 +148,7 @@ func TestSession_HydrateSession_SessionId(t *testing.T) { // Currently assumes NumBlocksPerSession=4 tests := []test{ { - name: "(app1, svc1): sessionId at first session block != sessionId at next session block", + desc: "(app1, svc1): sessionId at first session block != sessionId at next session block", blockHeight1: 4, blockHeight2: 8, @@ -141,11 +159,11 @@ func TestSession_HydrateSession_SessionId(t *testing.T) { serviceId1: keepertest.TestServiceId1, // svc1 serviceId2: keepertest.TestServiceId1, // svc1 - expectedSessionId1: "aabaa25668538f80395170be95ce1d1536d9228353ced71cc3b763171316fe39", - expectedSessionId2: "23f037a10f9d51d020d27763c42dd391d7e71765016d95d0d61f36c4a122efd0", + expectedSessionId1: "251665c7cf286a30fbd98acd983c63e9a34efc16496511373405e24eb02a8fb9", + expectedSessionId2: "5481d5ca2ddb15dc5edb792b8e20ba9c7d516a74475fc5feba6b6aeb95a26f58", }, { - name: "app1: sessionId for svc1 != sessionId for svc2", + desc: "app1: sessionId for svc1 != sessionId for svc12", blockHeight1: 4, blockHeight2: 4, @@ -153,14 +171,14 @@ func TestSession_HydrateSession_SessionId(t *testing.T) { appAddr1: keepertest.TestApp1Address, // app1 appAddr2: keepertest.TestApp1Address, // app1 - serviceId1: keepertest.TestServiceId1, // svc1 - serviceId2: keepertest.TestServiceId2, // svc2 + serviceId1: keepertest.TestServiceId1, // svc1 + serviceId2: keepertest.TestServiceId12, // svc12 - expectedSessionId1: "aabaa25668538f80395170be95ce1d1536d9228353ced71cc3b763171316fe39", - expectedSessionId2: "478d005769e5edf38d9bf2d8828a56d78b17348bb2c4796dd6d85b5d736a908a", + expectedSessionId1: "251665c7cf286a30fbd98acd983c63e9a34efc16496511373405e24eb02a8fb9", + expectedSessionId2: "44fce80205bece269429a5dc8b55f9d96e5bf7acdb9838f2ac9aa7216905a1cf", }, { - name: "svc1: sessionId for app1 != sessionId for app2", + desc: "svc12: sessionId for app1 != sessionId for app2", blockHeight1: 4, blockHeight2: 4, @@ -168,18 +186,19 @@ func TestSession_HydrateSession_SessionId(t *testing.T) { appAddr1: keepertest.TestApp1Address, // app1 appAddr2: keepertest.TestApp2Address, // app2 - serviceId1: keepertest.TestServiceId1, // svc1 - serviceId2: keepertest.TestServiceId1, // svc1 + serviceId1: keepertest.TestServiceId12, // svc12 + serviceId2: keepertest.TestServiceId12, // svc12 - expectedSessionId1: "aabaa25668538f80395170be95ce1d1536d9228353ced71cc3b763171316fe39", - expectedSessionId2: "b4b0d8747b1cf67050a7bfefd7e93ebbad80c534fa14fb3c69339886f2ed7061", + expectedSessionId1: "44fce80205bece269429a5dc8b55f9d96e5bf7acdb9838f2ac9aa7216905a1cf", + expectedSessionId2: "22328e12562532047c9d4200beaedc9be694cd99b38938ba64cf4cdca0a8ecba", }, } sessionKeeper, ctx := keepertest.SessionKeeper(t) + ctx = ctx.WithBlockHeight(100) // provide a sufficiently large block height to avoid errors for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { + t.Run(tt.desc, func(t *testing.T) { sessionHydrator1 := keeper.NewSessionHydrator(tt.appAddr1, tt.serviceId1, tt.blockHeight1) session1, err := sessionKeeper.HydrateSession(ctx, sessionHydrator1) require.NoError(t, err) @@ -198,30 +217,48 @@ func TestSession_HydrateSession_SessionId(t *testing.T) { // TODO_TECHDEBT: Expand these tests to account for application joining/leaving the network at different heights as well changing the services they support func TestSession_HydrateSession_Application(t *testing.T) { type test struct { - name string - appAddr string + // Description + desc string + // Inputs + appAddr string + serviceId string + // Outputs expectedErr error } tests := []test{ { - name: "app is found", - appAddr: keepertest.TestApp1Address, + desc: "app is found", + + appAddr: keepertest.TestApp1Address, + serviceId: keepertest.TestServiceId1, expectedErr: nil, }, { - name: "app is not found", - appAddr: sample.AccAddress(), // Generating a random address on the fly + desc: "app is not found", - expectedErr: types.ErrHydratingSession, + appAddr: sample.AccAddress(), // Generating a random address on the fly + serviceId: keepertest.TestServiceId1, + + expectedErr: types.ErrSessionHydration, }, { - name: "invalid app address", - appAddr: "invalid", + desc: "invalid app address", + + appAddr: "invalid", + serviceId: keepertest.TestServiceId1, - expectedErr: types.ErrHydratingSession, + expectedErr: types.ErrSessionHydration, + }, + { + desc: "invalid - app not staked for service", + + appAddr: keepertest.TestApp1Address, // app1 + serviceId: "svc9001", // app1 is only stake for svc1 and svc11 + + expectedErr: types.ErrSessionHydration, }, // TODO_TECHDEBT: Add tests for when: // - Application join/leaves (stakes/unstakes) altogether @@ -229,13 +266,13 @@ func TestSession_HydrateSession_Application(t *testing.T) { // - Application increases stakes mid-session } - serviceId := keepertest.TestServiceId1 blockHeight := int64(10) sessionKeeper, ctx := keepertest.SessionKeeper(t) + ctx = ctx.WithBlockHeight(100) // provide a sufficiently large block height to avoid errors for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - sessionHydrator := keeper.NewSessionHydrator(tt.appAddr, serviceId, blockHeight) + t.Run(tt.desc, func(t *testing.T) { + sessionHydrator := keeper.NewSessionHydrator(tt.appAddr, tt.serviceId, blockHeight) _, err := sessionKeeper.HydrateSession(ctx, sessionHydrator) if tt.expectedErr != nil { require.Error(t, err) @@ -249,10 +286,14 @@ func TestSession_HydrateSession_Application(t *testing.T) { // TODO_TECHDEBT: Expand these tests to account for supplier joining/leaving the network at different heights as well changing the services they support func TestSession_HydrateSession_Suppliers(t *testing.T) { type test struct { - name string + // Description + desc string + + // Inputs appAddr string serviceId string + // Outputs numExpectedSuppliers int expectedErr error } @@ -261,15 +302,17 @@ func TestSession_HydrateSession_Suppliers(t *testing.T) { // Currently assumes NumSupplierPerSession=15 tests := []test{ { - name: "num_suppliers_available = 0", + desc: "num_suppliers_available = 0", + appAddr: keepertest.TestApp1Address, // app1 - serviceId: "svc_unknown", + serviceId: keepertest.TestServiceId11, numExpectedSuppliers: 0, - expectedErr: types.ErrSuppliersNotFound, + expectedErr: types.ErrSessionSuppliersNotFound, }, { - name: "num_suppliers_available < num_suppliers_per_session_param", + desc: "num_suppliers_available < num_suppliers_per_session_param", + appAddr: keepertest.TestApp1Address, // app1 serviceId: keepertest.TestServiceId1, // svc1 @@ -288,9 +331,10 @@ func TestSession_HydrateSession_Suppliers(t *testing.T) { blockHeight := int64(10) sessionKeeper, ctx := keepertest.SessionKeeper(t) + ctx = ctx.WithBlockHeight(100) // provide a sufficiently large block height to avoid errors for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) {}) + t.Run(tt.desc, func(t *testing.T) {}) sessionHydrator := keeper.NewSessionHydrator(tt.appAddr, tt.serviceId, blockHeight) session, err := sessionKeeper.HydrateSession(ctx, sessionHydrator) diff --git a/x/session/types/errors.go b/x/session/types/errors.go index 3bf90eae7..dde73c1e6 100644 --- a/x/session/types/errors.go +++ b/x/session/types/errors.go @@ -8,7 +8,11 @@ import ( // x/session module sentinel errors var ( - ErrHydratingSession = sdkerrors.Register(ModuleName, 1, "error during session hydration") - ErrAppNotFound = sdkerrors.Register(ModuleName, 2, "application not found") - ErrSuppliersNotFound = sdkerrors.Register(ModuleName, 3, "suppliers not found") + ErrSessionHydration = sdkerrors.Register(ModuleName, 1, "error during session hydration") + ErrSessionAppNotFound = sdkerrors.Register(ModuleName, 2, "application for session not found not found ") + ErrSessionAppNotStakedForService = sdkerrors.Register(ModuleName, 3, "application in session not staked for requested service") + ErrSessionSuppliersNotFound = sdkerrors.Register(ModuleName, 4, "no suppliers not found for session") + ErrSessionInvalidAppAddress = sdkerrors.Register(ModuleName, 5, "invalid application address for session") + ErrSessionInvalidService = sdkerrors.Register(ModuleName, 6, "invalid service in session") + ErrSessionInvalidBlockHeight = sdkerrors.Register(ModuleName, 7, "invalid block height for session") ) diff --git a/x/session/types/query_get_session_request.go b/x/session/types/query_get_session_request.go new file mode 100644 index 000000000..31b705f8e --- /dev/null +++ b/x/session/types/query_get_session_request.go @@ -0,0 +1,40 @@ +package types + +import ( + sdkerrors "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + + sharedhelpers "github.com/pokt-network/poktroll/x/shared/helpers" + sharedtypes "github.com/pokt-network/poktroll/x/shared/types" +) + +// NOTE: Please note that `QueryGetSessionRequest` is not a `sdk.Msg`, and is therefore not a message/request +// that will be signable or invoke a state transition. However, following a similar `ValidateBasic` pattern +// allows us to localize & reuse validation logic. +func NewQueryGetSessionRequest(appAddress, serviceId string, blockHeight int64) *QueryGetSessionRequest { + return &QueryGetSessionRequest{ + ApplicationAddress: appAddress, + Service: &sharedtypes.Service{ + Id: serviceId, + }, + BlockHeight: blockHeight, + } +} + +func (query *QueryGetSessionRequest) ValidateBasic() error { + // Validate the application address + if _, err := sdk.AccAddressFromBech32(query.ApplicationAddress); err != nil { + return sdkerrors.Wrapf(ErrSessionInvalidAppAddress, "invalid app address for session being retrieved %s; (%v)", query.ApplicationAddress, err) + } + + // Validate the Service ID + if !sharedhelpers.IsValidService(query.Service) { + return sdkerrors.Wrapf(ErrSessionInvalidService, "invalid service for session being retrieved %s;", query.Service) + } + + // Validate the height for which a session is being retrieved + if query.BlockHeight < 0 { // Note that `0` defaults to the latest height rather than genesis + return sdkerrors.Wrapf(ErrSessionInvalidBlockHeight, "invalid block height for session being retrieved %d;", query.BlockHeight) + } + return nil +} diff --git a/x/shared/helpers/service.go b/x/shared/helpers/service.go index 3a4e56e5f..9825f26d4 100644 --- a/x/shared/helpers/service.go +++ b/x/shared/helpers/service.go @@ -3,6 +3,8 @@ package helpers import ( "net/url" "regexp" + + sharedtypes "github.com/pokt-network/poktroll/x/shared/types" ) const ( @@ -25,6 +27,14 @@ func init() { } +// IsValidService checks if the provided ServiceId struct has valid fields +func IsValidService(service *sharedtypes.Service) bool { + // Check if service Id and Name are valid using the provided helper functions + return service != nil && + IsValidServiceId(service.Id) && + IsValidServiceName(service.Name) +} + // IsValidServiceId checks if the input string is a valid serviceId func IsValidServiceId(serviceId string) bool { // ServiceId CANNOT be empty diff --git a/x/shared/helpers/service_configs.go b/x/shared/helpers/service_configs.go index 6884da7ae..95335d058 100644 --- a/x/shared/helpers/service_configs.go +++ b/x/shared/helpers/service_configs.go @@ -15,17 +15,9 @@ func ValidateAppServiceConfigs(services []*sharedtypes.ApplicationServiceConfig) if serviceConfig == nil { return fmt.Errorf("serviceConfig cannot be nil: %v", services) } - if serviceConfig.ServiceId == nil { - return fmt.Errorf("serviceId cannot be nil: %v", serviceConfig) - } - if serviceConfig.ServiceId.Id == "" { - return fmt.Errorf("serviceId.Id cannot be empty: %v", serviceConfig) - } - if !IsValidServiceId(serviceConfig.ServiceId.Id) { - return fmt.Errorf("invalid serviceId.Id: %v", serviceConfig) - } - if !IsValidServiceName(serviceConfig.ServiceId.Name) { - return fmt.Errorf("invalid serviceId.Name: %v", serviceConfig) + // Check the Service + if !IsValidService(serviceConfig.Service) { + return fmt.Errorf("invalid service: %v", serviceConfig.Service) } } return nil @@ -41,18 +33,9 @@ func ValidateSupplierServiceConfigs(services []*sharedtypes.SupplierServiceConfi return fmt.Errorf("serviceConfig cannot be nil: %v", services) } - // Check the ServiceId - if serviceConfig.ServiceId == nil { - return fmt.Errorf("serviceId cannot be nil: %v", serviceConfig) - } - if serviceConfig.ServiceId.Id == "" { - return fmt.Errorf("serviceId.Id cannot be empty: %v", serviceConfig) - } - if !IsValidServiceId(serviceConfig.ServiceId.Id) { - return fmt.Errorf("invalid serviceId.Id: %v", serviceConfig) - } - if !IsValidServiceName(serviceConfig.ServiceId.Name) { - return fmt.Errorf("invalid serviceId.Name: %v", serviceConfig) + // Check the Service + if !IsValidService(serviceConfig.Service) { + return fmt.Errorf("invalid service: %v", serviceConfig.Service) } // Check the Endpoints diff --git a/x/shared/helpers/service_test.go b/x/shared/helpers/service_test.go index 335cbcd51..d74b77afa 100644 --- a/x/shared/helpers/service_test.go +++ b/x/shared/helpers/service_test.go @@ -1,82 +1,261 @@ package helpers -import "testing" +import ( + "testing" + + "github.com/stretchr/testify/require" + + sharedtypes "github.com/pokt-network/poktroll/x/shared/types" +) + +func TestIsValidService(t *testing.T) { + tests := []struct { + desc string + + serviceId string + serviceName string + + expectedIsValid bool + }{ + { + desc: "Valid ID and Name", + + serviceId: "Service1", + serviceName: "Valid Service Name", + + expectedIsValid: true, + }, + { + desc: "Valid ID and empty Name", + + serviceId: "Srv", + serviceName: "", // Valid because the service name can be empty + + expectedIsValid: true, + }, + { + desc: "ID exceeds max length", + + serviceId: "TooLongId123", // Exceeds maxServiceIdLength + serviceName: "Valid Name", + + expectedIsValid: false, + }, + { + desc: "Name exceeds max length", + + serviceId: "ValidID", + serviceName: "This service name is way too long to be considered valid since it exceeds the max length", + + expectedIsValid: false, + }, + { + desc: "Empty ID is invalid", + + serviceId: "", // Invalid because the service ID cannot be empty + serviceName: "Valid Name", + + expectedIsValid: false, + }, + { + desc: "Invalid characters in ID", + + serviceId: "ID@Invalid", // Invalid character '@' + serviceName: "Valid Name", + + expectedIsValid: false, + }, + } + + for _, test := range tests { + t.Run(test.desc, func(t *testing.T) { + service := &sharedtypes.Service{ + Id: test.serviceId, + Name: test.serviceName, + } + result := IsValidService(service) + require.Equal(t, test.expectedIsValid, result) + }) + } +} + +func TestIsValidServiceName(t *testing.T) { + tests := []struct { + desc string + input string + expected bool + }{ + { + desc: "Valid with hyphen and number", + input: "ValidName-1", + expected: true, + }, + { + desc: "Valid with space and underscore", + input: "Valid Name_1", + expected: true, + }, + { + desc: "Valid name with spaces", + input: "valid name with spaces", + expected: true, + }, + { + desc: "Invalid character '@'", + input: "invalid@name", + expected: false, + }, + { + desc: "Invalid character '.'", + input: "Valid.Name", + expected: false, + }, + { + desc: "Empty string", + input: "", + expected: true, + }, + { + desc: "Exceeds maximum length", + input: "validnamebuttoolongvalidnamebuttoolongvalidnamebuttoolong", + expected: false, + }, + } + + for _, test := range tests { + t.Run(test.desc, func(t *testing.T) { + result := IsValidServiceName(test.input) + require.Equal(t, test.expected, result) + }) + } +} func TestIsValidServiceId(t *testing.T) { tests := []struct { + desc string + input string expected bool }{ - {"Hello-1", true}, - {"Hello_2", true}, - {"hello-world", false}, // exceeds maxServiceIdLength - {"Hello@", false}, // contains invalid character '@' - {"HELLO", true}, - {"12345678", true}, // exactly maxServiceIdLength - {"123456789", false}, // exceeds maxServiceIdLength - {"Hello.World", false}, // contains invalid character '.' - {"", false}, // empty string + { + desc: "Valid alphanumeric with hyphen", + + input: "Hello-1", + expected: true, + }, + { + desc: "Valid alphanumeric with underscore", + + input: "Hello_2", + expected: true, + }, + { + desc: "Exceeds maximum length", + + input: "hello-world", + expected: false, // exceeds maxServiceIdLength + }, + { + desc: "Contains invalid character '@'", + + input: "Hello@", + expected: false, // contains invalid character '@' + }, + { + desc: "All uppercase", + + input: "HELLO", + expected: true, + }, + { + desc: "Maximum length boundary", + + input: "12345678", + expected: true, // exactly maxServiceIdLength + }, + { + desc: "Above maximum length boundary", + + input: "123456789", + expected: false, // exceeds maxServiceIdLength + }, + { + desc: "Contains invalid character '.'", + + input: "Hello.World", + expected: false, // contains invalid character '.' + }, + { + desc: "Empty string", + + input: "", + expected: false, // empty string + }, } for _, test := range tests { - t.Run(test.input, func(t *testing.T) { + t.Run(test.desc, func(t *testing.T) { result := IsValidServiceId(test.input) - if result != test.expected { - t.Errorf("For input %s, expected %v but got %v", test.input, test.expected, result) - } + require.Equal(t, test.expected, result) }) } } func TestIsValidEndpointUrl(t *testing.T) { tests := []struct { - name string + desc string + input string expected bool }{ { - name: "valid http URL", + desc: "valid http URL", + input: "http://example.com", expected: true, }, { - name: "valid https URL", + desc: "valid https URL", + input: "https://example.com/path?query=value#fragment", expected: true, }, { - name: "valid localhost URL with scheme", + desc: "valid localhost URL with scheme", + input: "https://localhost:8081", expected: true, }, { - name: "valid loopback URL with scheme", + desc: "valid loopback URL with scheme", + input: "http://127.0.0.1:8081", expected: true, }, { - name: "invalid scheme", + desc: "invalid scheme", + input: "ftp://example.com", expected: false, }, { - name: "missing scheme", + desc: "missing scheme", + input: "example.com", expected: false, }, { - name: "invalid URL", + desc: "invalid URL", + input: "not-a-valid-url", expected: false, }, } for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { + t.Run(tt.desc, func(t *testing.T) { got := IsValidEndpointUrl(tt.input) - if got != tt.expected { - t.Errorf("IsValidEndpointUrl(%q) = %v, want %v", tt.input, got, tt.expected) - } + require.Equal(t, tt.expected, got) }) } } diff --git a/x/supplier/client/cli/query_supplier.go b/x/supplier/client/cli/query_supplier.go index cfbc6b4ec..604c1182f 100644 --- a/x/supplier/client/cli/query_supplier.go +++ b/x/supplier/client/cli/query_supplier.go @@ -46,7 +46,7 @@ func CmdListSupplier() *cobra.Command { func CmdShowSupplier() *cobra.Command { cmd := &cobra.Command{ - Use: "show-supplier [address]", + Use: "show-supplier ", Short: "shows a supplier", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) (err error) { diff --git a/x/supplier/client/cli/tx_create_claim.go b/x/supplier/client/cli/tx_create_claim.go index db951891f..2869ce95d 100644 --- a/x/supplier/client/cli/tx_create_claim.go +++ b/x/supplier/client/cli/tx_create_claim.go @@ -2,9 +2,8 @@ package cli import ( "encoding/base64" - "strconv" - "encoding/json" + "strconv" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" @@ -21,7 +20,7 @@ var _ = strconv.Itoa(0) func CmdCreateClaim() *cobra.Command { cmd := &cobra.Command{ - Use: "create-claim [session-header] [root-hash-base64]", + Use: "create-claim ", Short: "Broadcast message create-claim", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) (err error) { diff --git a/x/supplier/client/cli/tx_stake_supplier.go b/x/supplier/client/cli/tx_stake_supplier.go index 81a0425fa..83a1413e2 100644 --- a/x/supplier/client/cli/tx_stake_supplier.go +++ b/x/supplier/client/cli/tx_stake_supplier.go @@ -23,7 +23,7 @@ func CmdStakeSupplier() *cobra.Command { // TODO_HACK: For now we are only specifying the service IDs as a list of of strings separated by commas. // This needs to be expand to specify the full SupplierServiceConfig. Furthermore, providing a flag to // a file where SupplierServiceConfig specifying full service configurations in the CLI by providing a flag that accepts a JSON string - Use: "stake-supplier [amount] [svcId1;url1,svcId2;url2,...,svcIdN;urlN]", + Use: "stake-supplier ", Short: "Stake a supplier", Long: `Stake an supplier with the provided parameters. This is a broadcast operation that will stake the tokens and associate them with the supplier specified by the 'from' address. @@ -84,7 +84,7 @@ func hackStringToServices(servicesArg string) ([]*sharedtypes.SupplierServiceCon return nil, fmt.Errorf("invalid service string: %s. Expected it to be of the form 'service;url'", serviceString) } service := &sharedtypes.SupplierServiceConfig{ - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: serviceParts[0], }, Endpoints: []*sharedtypes.SupplierEndpoint{ diff --git a/x/supplier/client/cli/tx_submit_proof.go b/x/supplier/client/cli/tx_submit_proof.go index 64c498026..0c3ba758f 100644 --- a/x/supplier/client/cli/tx_submit_proof.go +++ b/x/supplier/client/cli/tx_submit_proof.go @@ -2,9 +2,8 @@ package cli import ( "encoding/base64" - "strconv" - "encoding/json" + "strconv" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" @@ -15,13 +14,13 @@ import ( "github.com/pokt-network/poktroll/x/supplier/types" ) -var _ = strconv.Itoa(0) - // TODO(@bryanchriswhite): Add unit tests for the CLI command when implementing the business logic. +var _ = strconv.Itoa(0) + func CmdSubmitProof() *cobra.Command { cmd := &cobra.Command{ - Use: "submit-proof [session-header] [proof-base64]", + Use: "submit-proof ", Short: "Broadcast message submit-proof", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) (err error) { diff --git a/x/supplier/genesis_test.go b/x/supplier/genesis_test.go index b6af0545c..ba9b521f8 100644 --- a/x/supplier/genesis_test.go +++ b/x/supplier/genesis_test.go @@ -24,7 +24,7 @@ func TestGenesis(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "svcId1", }, Endpoints: []*sharedtypes.SupplierEndpoint{ @@ -42,7 +42,7 @@ func TestGenesis(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "svcId2", }, Endpoints: []*sharedtypes.SupplierEndpoint{ diff --git a/x/supplier/keeper/msg_server_stake_supplier_test.go b/x/supplier/keeper/msg_server_stake_supplier_test.go index 7ac0ee031..cd6158a81 100644 --- a/x/supplier/keeper/msg_server_stake_supplier_test.go +++ b/x/supplier/keeper/msg_server_stake_supplier_test.go @@ -31,7 +31,7 @@ func TestMsgServer_StakeSupplier_SuccessfulCreateAndUpdate(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "svcId", }, Endpoints: []*sharedtypes.SupplierEndpoint{ @@ -55,7 +55,7 @@ func TestMsgServer_StakeSupplier_SuccessfulCreateAndUpdate(t *testing.T) { require.Equal(t, addr, supplierFound.Address) require.Equal(t, int64(100), supplierFound.Stake.Amount.Int64()) require.Len(t, supplierFound.Services, 1) - require.Equal(t, "svcId", supplierFound.Services[0].ServiceId.Id) + require.Equal(t, "svcId", supplierFound.Services[0].Service.Id) require.Len(t, supplierFound.Services[0].Endpoints, 1) require.Equal(t, "http://localhost:8080", supplierFound.Services[0].Endpoints[0].Url) @@ -65,7 +65,7 @@ func TestMsgServer_StakeSupplier_SuccessfulCreateAndUpdate(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(200)}, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "svcId2", }, Endpoints: []*sharedtypes.SupplierEndpoint{ @@ -86,7 +86,7 @@ func TestMsgServer_StakeSupplier_SuccessfulCreateAndUpdate(t *testing.T) { require.True(t, isSupplierFound) require.Equal(t, int64(200), supplierFound.Stake.Amount.Int64()) require.Len(t, supplierFound.Services, 1) - require.Equal(t, "svcId2", supplierFound.Services[0].ServiceId.Id) + require.Equal(t, "svcId2", supplierFound.Services[0].Service.Id) require.Len(t, supplierFound.Services[0].Endpoints, 1) require.Equal(t, "http://localhost:8082", supplierFound.Services[0].Endpoints[0].Url) } @@ -104,7 +104,7 @@ func TestMsgServer_StakeSupplier_FailRestakingDueToInvalidServices(t *testing.T) Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "svcId", }, Endpoints: []*sharedtypes.SupplierEndpoint{ @@ -128,7 +128,7 @@ func TestMsgServer_StakeSupplier_FailRestakingDueToInvalidServices(t *testing.T) Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: "svcId"}, + Service: &sharedtypes.Service{Id: "svcId"}, Endpoints: []*sharedtypes.SupplierEndpoint{}, }, }, @@ -143,7 +143,7 @@ func TestMsgServer_StakeSupplier_FailRestakingDueToInvalidServices(t *testing.T) require.True(t, isSupplierFound) require.Equal(t, supplierAddr, supplierFound.Address) require.Len(t, supplierFound.Services, 1) - require.Equal(t, "svcId", supplierFound.Services[0].ServiceId.Id) + require.Equal(t, "svcId", supplierFound.Services[0].Service.Id) require.Len(t, supplierFound.Services[0].Endpoints, 1) require.Equal(t, "http://localhost:8080", supplierFound.Services[0].Endpoints[0].Url) @@ -153,7 +153,7 @@ func TestMsgServer_StakeSupplier_FailRestakingDueToInvalidServices(t *testing.T) Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: "svc1 INVALID ! & *"}, + Service: &sharedtypes.Service{Id: "svc1 INVALID ! & *"}, }, }, } @@ -167,7 +167,7 @@ func TestMsgServer_StakeSupplier_FailRestakingDueToInvalidServices(t *testing.T) require.True(t, isSupplierFound) require.Equal(t, supplierAddr, supplierFound.Address) require.Len(t, supplierFound.Services, 1) - require.Equal(t, "svcId", supplierFound.Services[0].ServiceId.Id) + require.Equal(t, "svcId", supplierFound.Services[0].Service.Id) require.Len(t, supplierFound.Services[0].Endpoints, 1) require.Equal(t, "http://localhost:8080", supplierFound.Services[0].Endpoints[0].Url) } @@ -184,7 +184,7 @@ func TestMsgServer_StakeSupplier_FailLoweringStake(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "svcId", }, Endpoints: []*sharedtypes.SupplierEndpoint{ @@ -210,7 +210,7 @@ func TestMsgServer_StakeSupplier_FailLoweringStake(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(50)}, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "svcId", }, Endpoints: []*sharedtypes.SupplierEndpoint{ diff --git a/x/supplier/keeper/msg_server_unstake_supplier_test.go b/x/supplier/keeper/msg_server_unstake_supplier_test.go index 163cbe5ae..993201971 100644 --- a/x/supplier/keeper/msg_server_unstake_supplier_test.go +++ b/x/supplier/keeper/msg_server_unstake_supplier_test.go @@ -32,7 +32,7 @@ func TestMsgServer_UnstakeSupplier_Success(t *testing.T) { Stake: &initialStake, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "svcId", }, Endpoints: []*sharedtypes.SupplierEndpoint{ diff --git a/x/supplier/keeper/supplier.go b/x/supplier/keeper/supplier.go index 0c31db2be..559ca4a97 100644 --- a/x/supplier/keeper/supplier.go +++ b/x/supplier/keeper/supplier.go @@ -64,5 +64,5 @@ func (k Keeper) GetAllSupplier(ctx sdk.Context) (suppliers []sharedtypes.Supplie return } -// TODO_OPTIMIZE: Index suppliers by serviceId so we can easily query `k.GetAllSupplier(ctx, ServiceId)` +// TODO_OPTIMIZE: Index suppliers by service so we can easily query `k.GetAllSupplier(ctx, Service)` // func (k Keeper) GetAllSupplier(ctx, sdkContext, serviceId string) (suppliers []sharedtypes.Supplier) {} diff --git a/x/supplier/keeper/supplier_test.go b/x/supplier/keeper/supplier_test.go index c02c5758e..e7b901489 100644 --- a/x/supplier/keeper/supplier_test.go +++ b/x/supplier/keeper/supplier_test.go @@ -33,7 +33,7 @@ func createNSupplier(keeper *keeper.Keeper, ctx sdk.Context, n int) []sharedtype supplier.Stake = &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(int64(i))} supplier.Services = []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{Id: fmt.Sprintf("svc%d", i)}, + Service: &sharedtypes.Service{Id: fmt.Sprintf("svc%d", i)}, Endpoints: []*sharedtypes.SupplierEndpoint{ { Url: fmt.Sprintf("http://localhost:%d", i), diff --git a/x/supplier/types/errors.go b/x/supplier/types/errors.go index 02a76a573..9403950e1 100644 --- a/x/supplier/types/errors.go +++ b/x/supplier/types/errors.go @@ -8,9 +8,11 @@ import ( // x/supplier module sentinel errors var ( - ErrSupplierInvalidStake = sdkerrors.Register(ModuleName, 1, "invalid supplier stake") - ErrSupplierInvalidAddress = sdkerrors.Register(ModuleName, 2, "invalid supplier address") - ErrSupplierUnauthorized = sdkerrors.Register(ModuleName, 3, "unauthorized supplier signer") - ErrSupplierNotFound = sdkerrors.Register(ModuleName, 4, "supplier not found") - ErrSupplierInvalidServiceConfig = sdkerrors.Register(ModuleName, 5, "invalid service config") + ErrSupplierInvalidStake = sdkerrors.Register(ModuleName, 1, "invalid supplier stake") + ErrSupplierInvalidAddress = sdkerrors.Register(ModuleName, 2, "invalid supplier address") + ErrSupplierUnauthorized = sdkerrors.Register(ModuleName, 3, "unauthorized supplier signer") + ErrSupplierNotFound = sdkerrors.Register(ModuleName, 4, "supplier not found") + ErrSupplierInvalidServiceConfig = sdkerrors.Register(ModuleName, 5, "invalid service config") + ErrSupplierInvalidSessionStartHeight = sdkerrors.Register(ModuleName, 6, "invalid session start height") + ErrSupplierInvalidSessionId = sdkerrors.Register(ModuleName, 7, "invalid session ID") ) diff --git a/x/supplier/types/genesis.go b/x/supplier/types/genesis.go index 2f4ff1872..b68751dcd 100644 --- a/x/supplier/types/genesis.go +++ b/x/supplier/types/genesis.go @@ -56,7 +56,6 @@ func (gs GenesisState) Validate() error { return sdkerrors.Wrapf(ErrSupplierInvalidStake, "invalid stake amount denom for supplier %v", supplier.Stake) } - // Valid the application service configs // Validate the application service configs if err := servicehelpers.ValidateSupplierServiceConfigs(supplier.Services); err != nil { return sdkerrors.Wrapf(ErrSupplierInvalidServiceConfig, err.Error()) diff --git a/x/supplier/types/genesis_test.go b/x/supplier/types/genesis_test.go index ba806c98b..5625fa435 100644 --- a/x/supplier/types/genesis_test.go +++ b/x/supplier/types/genesis_test.go @@ -15,7 +15,7 @@ func TestGenesisState_Validate(t *testing.T) { addr1 := sample.AccAddress() stake1 := sdk.NewCoin("upokt", sdk.NewInt(100)) serviceConfig1 := &sharedtypes.SupplierServiceConfig{ - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "svcId1", }, Endpoints: []*sharedtypes.SupplierEndpoint{ @@ -31,7 +31,7 @@ func TestGenesisState_Validate(t *testing.T) { addr2 := sample.AccAddress() stake2 := sdk.NewCoin("upokt", sdk.NewInt(100)) serviceConfig2 := &sharedtypes.SupplierServiceConfig{ - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "svcId2", }, Endpoints: []*sharedtypes.SupplierEndpoint{ @@ -250,7 +250,7 @@ func TestGenesisState_Validate(t *testing.T) { Stake: &stake2, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "svcId1", }, Endpoints: []*sharedtypes.SupplierEndpoint{ @@ -281,7 +281,7 @@ func TestGenesisState_Validate(t *testing.T) { Stake: &stake2, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "svcId1", }, Endpoints: []*sharedtypes.SupplierEndpoint{ diff --git a/x/supplier/types/message_stake_supplier_test.go b/x/supplier/types/message_stake_supplier_test.go index 57ce3e4fd..158fd8ff3 100644 --- a/x/supplier/types/message_stake_supplier_test.go +++ b/x/supplier/types/message_stake_supplier_test.go @@ -17,7 +17,7 @@ func TestMsgStakeSupplier_ValidateBasic(t *testing.T) { defaultServicesList := []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "svcId1", }, Endpoints: []*sharedtypes.SupplierEndpoint{ @@ -103,7 +103,7 @@ func TestMsgStakeSupplier_ValidateBasic(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "svcId1", }, Endpoints: []*sharedtypes.SupplierEndpoint{ @@ -115,7 +115,7 @@ func TestMsgStakeSupplier_ValidateBasic(t *testing.T) { }, }, { - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "svcId2", }, Endpoints: []*sharedtypes.SupplierEndpoint{ @@ -154,7 +154,7 @@ func TestMsgStakeSupplier_ValidateBasic(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "123456790", }, Endpoints: []*sharedtypes.SupplierEndpoint{ @@ -176,7 +176,7 @@ func TestMsgStakeSupplier_ValidateBasic(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "123", Name: "abcdefghijklmnopqrstuvwxyzab-abcdefghijklmnopqrstuvwxyzab", }, @@ -199,7 +199,7 @@ func TestMsgStakeSupplier_ValidateBasic(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "12 45 !", }, Endpoints: []*sharedtypes.SupplierEndpoint{ @@ -221,7 +221,7 @@ func TestMsgStakeSupplier_ValidateBasic(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "svcId", Name: "name", }, @@ -244,7 +244,7 @@ func TestMsgStakeSupplier_ValidateBasic(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "svcId", Name: "name", }, @@ -267,7 +267,7 @@ func TestMsgStakeSupplier_ValidateBasic(t *testing.T) { Stake: &sdk.Coin{Denom: "upokt", Amount: sdk.NewInt(100)}, Services: []*sharedtypes.SupplierServiceConfig{ { - ServiceId: &sharedtypes.ServiceId{ + Service: &sharedtypes.Service{ Id: "svcId", Name: "name", },