diff --git a/.gitignore b/.gitignore index 6dbdd3c40..c6e3508f1 100644 --- a/.gitignore +++ b/.gitignore @@ -62,4 +62,11 @@ localnet_config.yaml # Relase artifacts produced by `ignite chain build --release` release +# Only keep one go module in our codebase go.work.sum + +# Avoid accidently commiting gomock artifacts +**/gomock_reflect_* + + +gomock_reflect diff --git a/docs/static/openapi.yml b/docs/static/openapi.yml index 7c5739927..9d23a20d2 100644 --- a/docs/static/openapi.yml +++ b/docs/static/openapi.yml @@ -47427,7 +47427,59 @@ paths: additionalProperties: {} tags: - Query - /pocket/supplier/claim: + /pocket/supplier/claim/{session_id}/{supplier_address}: + get: + summary: Queries a list of Claim items. + operationId: PocketSupplierClaim + responses: + '200': + description: A successful response. + schema: + type: object + properties: + claim: + type: object + properties: + supplier_address: + type: string + title: the address of the supplier that submitted this claims + session_id: + type: string + title: session id from the SessionHeader + root_hash: + type: string + format: byte + title: smt.SMST#Root() + default: + description: An unexpected error response. + schema: + type: object + properties: + code: + type: integer + format: int32 + message: + type: string + details: + type: array + items: + type: object + properties: + '@type': + type: string + additionalProperties: {} + parameters: + - name: session_id + in: path + required: true + type: string + - name: supplier_address + in: path + required: true + type: string + tags: + - Query + /pocket/supplier/claims: get: operationId: PocketSupplierAllClaims responses: @@ -47554,31 +47606,37 @@ paths: in: query required: false type: boolean + - name: supplier_address + in: query + required: false + type: string + - name: session_id + in: query + required: false + type: string + - name: session_end_height + in: query + required: false + type: string + format: uint64 tags: - Query - /pocket/supplier/claim/{index}: + /pocket/supplier/params: get: - summary: Queries a list of Claim items. - operationId: PocketSupplierClaim + summary: Parameters queries the parameters of the module. + operationId: PocketSupplierParams responses: '200': description: A successful response. schema: type: object properties: - claim: + params: + description: params holds all the parameters of this module. type: object - properties: - supplier_address: - type: string - title: the address of the supplier that submitted this claims - session_id: - type: string - title: session id from the SessionHeader - root_hash: - type: string - format: byte - title: smt.SMST#Root() + description: >- + QueryParamsResponse is response type for the Query/Params RPC + method. default: description: An unexpected error response. schema: @@ -47597,29 +47655,131 @@ paths: '@type': type: string additionalProperties: {} - parameters: - - name: index - in: path - required: true - type: string tags: - Query - /pocket/supplier/params: + /pocket/supplier/supplier/{address}: get: - summary: Parameters queries the parameters of the module. - operationId: PocketSupplierParams + summary: Queries a list of Supplier items. + operationId: PocketSupplierSupplier responses: '200': description: A successful response. schema: type: object properties: - params: - description: params holds all the parameters of this module. + supplier: type: object - description: >- - QueryParamsResponse is response type for the Query/Params RPC - method. + properties: + address: + type: string + title: >- + The Bech32 address of the supplier using cosmos' + ScalarDescriptor to ensure deterministic encoding + stake: + title: The total amount of uPOKT the supplier has staked + type: object + properties: + denom: + type: string + amount: + type: string + description: >- + Coin defines a token with a denomination and an amount. + + + NOTE: The amount field is an Int which implements the + custom method + + signatures required by gogoproto. + services: + type: array + items: + type: object + properties: + service: + title: The Service for which the supplier is configured + type: object + properties: + id: + type: string + description: Unique identifier for the service + title: >- + 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 + endpoints: + type: array + items: + type: object + properties: + url: + type: string + title: URL of the endpoint + rpc_type: + title: Type of RPC exposed on the url above + type: string + enum: + - UNKNOWN_RPC + - GRPC + - WEBSOCKET + - JSON_RPC + default: UNKNOWN_RPC + description: |- + - UNKNOWN_RPC: Undefined RPC type + - GRPC: gRPC + - WEBSOCKET: WebSocket + - JSON_RPC: JSON-RPC + configs: + type: array + items: + type: object + properties: + key: + title: Config option key + type: string + enum: + - UNKNOWN_CONFIG + - TIMEOUT + default: UNKNOWN_CONFIG + description: >- + Enum to define configuration options + + TODO_RESEARCH: Should these be configs, + SLAs or something else? There will be + more discussion once we get closer to + implementing on-chain QoS. + + - UNKNOWN_CONFIG: Undefined config option + - TIMEOUT: Timeout setting + value: + type: string + title: Config option value + title: >- + Key-value wrapper for config options, as + proto maps can't be keyed by enums + title: >- + Additional configuration options for the + endpoint + title: >- + SupplierEndpoint message to hold service + configuration details + title: List of endpoints for the service + title: >- + SupplierServiceConfig holds the service configuration + the supplier stakes for + title: The service configs this supplier can support + description: >- + Supplier is the type defining the actor in Pocket Network that + provides RPC services. default: description: An unexpected error response. schema: @@ -47638,9 +47798,14 @@ paths: '@type': type: string additionalProperties: {} + parameters: + - name: address + in: path + required: true + type: string tags: - Query - /pocket/supplier/supplier: + /pocket/supplier/suppliers: get: operationId: PocketSupplierSupplierAll responses: @@ -47869,154 +48034,6 @@ paths: type: boolean tags: - Query - /pocket/supplier/supplier/{address}: - get: - summary: Queries a list of Supplier items. - operationId: PocketSupplierSupplier - responses: - '200': - description: A successful response. - schema: - type: object - properties: - supplier: - type: object - properties: - address: - type: string - title: >- - The Bech32 address of the supplier using cosmos' - ScalarDescriptor to ensure deterministic encoding - stake: - title: The total amount of uPOKT the supplier has staked - type: object - properties: - denom: - type: string - amount: - type: string - description: >- - Coin defines a token with a denomination and an amount. - - - NOTE: The amount field is an Int which implements the - custom method - - signatures required by gogoproto. - services: - type: array - items: - type: object - properties: - service: - title: The Service for which the supplier is configured - type: object - properties: - id: - type: string - description: Unique identifier for the service - title: >- - 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 - endpoints: - type: array - items: - type: object - properties: - url: - type: string - title: URL of the endpoint - rpc_type: - title: Type of RPC exposed on the url above - type: string - enum: - - UNKNOWN_RPC - - GRPC - - WEBSOCKET - - JSON_RPC - default: UNKNOWN_RPC - description: |- - - UNKNOWN_RPC: Undefined RPC type - - GRPC: gRPC - - WEBSOCKET: WebSocket - - JSON_RPC: JSON-RPC - configs: - type: array - items: - type: object - properties: - key: - title: Config option key - type: string - enum: - - UNKNOWN_CONFIG - - TIMEOUT - default: UNKNOWN_CONFIG - description: >- - Enum to define configuration options - - TODO_RESEARCH: Should these be configs, - SLAs or something else? There will be - more discussion once we get closer to - implementing on-chain QoS. - - - UNKNOWN_CONFIG: Undefined config option - - TIMEOUT: Timeout setting - value: - type: string - title: Config option value - title: >- - Key-value wrapper for config options, as - proto maps can't be keyed by enums - title: >- - Additional configuration options for the - endpoint - title: >- - SupplierEndpoint message to hold service - configuration details - title: List of endpoints for the service - title: >- - SupplierServiceConfig holds the service configuration - the supplier stakes for - title: The service configs this supplier can support - description: >- - Supplier is the type defining the actor in Pocket Network that - provides RPC services. - default: - description: An unexpected error response. - schema: - type: object - properties: - code: - type: integer - format: int32 - message: - type: string - details: - type: array - items: - type: object - properties: - '@type': - type: string - additionalProperties: {} - parameters: - - name: address - in: path - required: true - type: string - tags: - - Query definitions: cosmos.auth.v1beta1.AddressBytesToStringResponse: type: object diff --git a/proto/pocket/supplier/genesis.proto b/proto/pocket/supplier/genesis.proto index a35a4a994..5bba7baea 100644 --- a/proto/pocket/supplier/genesis.proto +++ b/proto/pocket/supplier/genesis.proto @@ -5,7 +5,6 @@ package pocket.supplier; import "gogoproto/gogo.proto"; import "pocket/supplier/params.proto"; import "pocket/shared/supplier.proto"; -import "pocket/supplier/claim.proto"; option go_package = "github.com/pokt-network/poktroll/x/supplier/types"; diff --git a/proto/pocket/supplier/query.proto b/proto/pocket/supplier/query.proto index 401165ee7..fdc90a4c2 100644 --- a/proto/pocket/supplier/query.proto +++ b/proto/pocket/supplier/query.proto @@ -24,15 +24,15 @@ service Query { option (google.api.http).get = "/pocket/supplier/supplier/{address}"; } rpc SupplierAll (QueryAllSupplierRequest) returns (QueryAllSupplierResponse) { - option (google.api.http).get = "/pocket/supplier/supplier"; + option (google.api.http).get = "/pocket/supplier/suppliers"; } // Queries a list of Claim items. rpc Claim (QueryGetClaimRequest) returns (QueryGetClaimResponse) { - option (google.api.http).get = "/pocket/supplier/claim/{index}"; + option (google.api.http).get = "/pocket/supplier/claim/{session_id}/{supplier_address}"; } rpc AllClaims (QueryAllClaimsRequest) returns (QueryAllClaimsResponse) { - option (google.api.http).get = "/pocket/supplier/claim"; + option (google.api.http).get = "/pocket/supplier/claims"; } } // QueryParamsRequest is request type for the Query/Params RPC method. @@ -62,7 +62,8 @@ message QueryAllSupplierResponse { } message QueryGetClaimRequest { - string supplier_address = 1; + string session_id = 1; + string supplier_address = 2; } message QueryGetClaimResponse { @@ -71,6 +72,11 @@ message QueryGetClaimResponse { message QueryAllClaimsRequest { cosmos.base.query.v1beta1.PageRequest pagination = 1; + oneof filter { + string supplier_address = 2; + string session_id = 3; + uint64 session_end_height = 4; + } } message QueryAllClaimsResponse { diff --git a/x/supplier/client/cli/query.go b/x/supplier/client/cli/query.go index f70e996ba..ab7697ac9 100644 --- a/x/supplier/client/cli/query.go +++ b/x/supplier/client/cli/query.go @@ -27,7 +27,7 @@ func GetQueryCmd(queryRoute string) *cobra.Command { cmd.AddCommand(CmdQueryParams()) cmd.AddCommand(CmdListSupplier()) cmd.AddCommand(CmdShowSupplier()) - cmd.AddCommand(CmdListClaim()) + cmd.AddCommand(CmdListClaims()) cmd.AddCommand(CmdShowClaim()) // this line is used by starport scaffolding # 1 diff --git a/x/supplier/client/cli/query_claim.go b/x/supplier/client/cli/query_claim.go index 7e742a017..ced71ad79 100644 --- a/x/supplier/client/cli/query_claim.go +++ b/x/supplier/client/cli/query_claim.go @@ -13,28 +13,26 @@ import ( // Prevent strconv unused error var _ = strconv.IntSize -func CmdListClaim() *cobra.Command { +func CmdListClaims() *cobra.Command { cmd := &cobra.Command{ Use: "list-claims", Short: "list all claims", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) + pageReq, err := client.ReadPageRequest(cmd.Flags()) if err != nil { return err } + params := &types.QueryAllClaimsRequest{ + Pagination: pageReq, + } - pageReq, err := client.ReadPageRequest(cmd.Flags()) + clientCtx, err := client.GetClientQueryContext(cmd) if err != nil { return err } - queryClient := types.NewQueryClient(clientCtx) - params := &types.QueryAllClaimsRequest{ - Pagination: pageReq, - } - res, err := queryClient.AllClaims(cmd.Context(), params) if err != nil { return err @@ -53,9 +51,20 @@ func CmdListClaim() *cobra.Command { func CmdShowClaim() *cobra.Command { cmd := &cobra.Command{ Use: "show-claim ", - Short: "shows a claim", + Short: "shows a specific claim", Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) (err error) { + sessionId := args[0] + supplierAddr := args[1] + + getClaimRequest := &types.QueryGetClaimRequest{ + SessionId: sessionId, + SupplierAddress: supplierAddr, + } + if err := getClaimRequest.ValidateBasic(); err != nil { + return err + } + clientCtx, err := client.GetClientQueryContext(cmd) if err != nil { return err @@ -63,13 +72,7 @@ func CmdShowClaim() *cobra.Command { queryClient := types.NewQueryClient(clientCtx) - argIndex := args[0] - - params := &types.QueryGetClaimRequest{ - Index: argIndex, - } - - res, err := queryClient.Claim(cmd.Context(), params) + res, err := queryClient.Claim(cmd.Context(), getClaimRequest) if err != nil { return err } diff --git a/x/supplier/keeper/claim.go b/x/supplier/keeper/claim.go index 3928cab3a..0be972f4b 100644 --- a/x/supplier/keeper/claim.go +++ b/x/supplier/keeper/claim.go @@ -1,8 +1,6 @@ package keeper import ( - "encoding/binary" - "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" @@ -11,90 +9,66 @@ import ( // InsertClaim adds a claim to the store func (k Keeper) InsertClaim(ctx sdk.Context, claim types.Claim) { + logger := k.Logger(ctx).With("method", "InsertClaim") + claimBz := k.cdc.MustMarshal(&claim) parentStore := ctx.KVStore(k.storeKey) - // Update the primary store - + // Update the primary store: ClaimPrimaryKey -> ClaimObject primaryStore := prefix.NewStore(parentStore, types.KeyPrefix(types.ClaimPrimaryKeyPrefix)) primaryKey := types.ClaimPrimaryKey(claim.SessionId, claim.SupplierAddress) primaryStore.Set(primaryKey, claimBz) - // Update the session index - // TODO + logger.Info("inserted claim with primaryKey %s", primaryKey) - // Update the height index - // TODO - - // Update the address index + // Update the address index: supplierAddress -> [ClaimPrimaryKey] addressStoreIndex := prefix.NewStore(parentStore, types.KeyPrefix(types.ClaimAddressPrefix)) - addressClaimCount := k.getCount(ctx, addressStoreIndex) - addressKey := types.ClaimSupplierAddressKey(claim.SupplierAddress, addressClaimCount) + addressKey := types.ClaimSupplierAddressKey(claim.SupplierAddress, primaryKey) addressStoreIndex.Set(addressKey, primaryKey) - k.setCount(ctx, addressStoreIndex, addressClaimCount+1) + + // TODO: Index by sessionId + // TODO: Index by sessionEndHeight +} + +// RemoveClaim removes a claim from the store +func (k Keeper) RemoveClaim(ctx sdk.Context, sessionId, supplierAddr string) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ClaimPrimaryKeyPrefix)) + + primaryKey := types.ClaimPrimaryKey(sessionId, supplierAddr) + claim, foundClaim := k.getClaimByPrimaryKey(ctx, primaryKey) + if !foundClaim { + k.Logger(ctx).Error("trying to delete non-existent claim with primary key %s for supplier %s and session %s", primaryKey, supplierAddr, sessionId) + } + + addressStore := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ClaimAddressPrefix)) + addressKey := types.ClaimSupplierAddressKey(claim.SupplierAddress, primaryKey) + + addressStore.Delete(addressKey) + store.Delete(primaryKey) } -// GetClaim returns a claim given a sessionId & supplierAddr +// GetClaim returns a Claim given a SessionId & SupplierAddr func (k Keeper) GetClaim(ctx sdk.Context, sessionId, supplierAddr string) (val types.Claim, found bool) { primaryKey := types.ClaimPrimaryKey(sessionId, supplierAddr) return k.getClaimByPrimaryKey(ctx, primaryKey) } -// SetClaim set a specific claim in the store from its index -// func (k Keeper) SetClaim(ctx sdk.Context, claim types.Claim) { -// store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ClaimKeyPrefix)) -// b := k.cdc.MustMarshal(&claim) -// store.Set(types.ClaimKey( -// claim.Index, -// ), b) -// } - -// // GetClaim returns a claim from its index -// func (k Keeper) GetClaim( -// ctx sdk.Context, -// index string, - -// ) (val types.Claim, found bool) { -// store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ClaimKeyPrefix)) - -// b := store.Get(types.ClaimKey( -// index, -// )) -// if b == nil { -// return val, false -// } - -// k.cdc.MustUnmarshal(b, &val) -// return val, true -// } - -// // RemoveClaim removes a claim from the store -// func (k Keeper) RemoveClaim( -// ctx sdk.Context, -// index string, - -// ) { -// store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ClaimKeyPrefix)) -// store.Delete(types.ClaimKey( -// index, -// )) -// } - -// // GetAllClaims returns all claim -// func (k Keeper) GetAllClaims(ctx sdk.Context) (list []types.Claim) { -// store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ClaimKeyPrefix)) -// iterator := sdk.KVStorePrefixIterator(store, []byte{}) -// defer iterator.Close() - -// for ; iterator.Valid(); iterator.Next() { -// var val types.Claim -// k.cdc.MustUnmarshal(iterator.Value(), &val) -// claims = append(claims, val) -// } - -// return -// } - -// When retrieving by address: +// GetAllClaims returns all claim +func (k Keeper) GetAllClaims(ctx sdk.Context) (claims []types.Claim) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ClaimPrimaryKeyPrefix)) + iterator := sdk.KVStorePrefixIterator(store, []byte{}) + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + var val types.Claim + k.cdc.MustUnmarshal(iterator.Value(), &val) + claims = append(claims, val) + } + + return +} + +// GetClaimsByAddress returns all claims for a given address func (k Keeper) GetClaimsByAddress(ctx sdk.Context, address sdk.AccAddress) (claims []types.Claim) { addressStore := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ClaimAddressPrefix)) @@ -112,6 +86,7 @@ func (k Keeper) GetClaimsByAddress(ctx sdk.Context, address sdk.AccAddress) (cla return claims } +// getClaimByPrimaryKey is a helper that retrieves, if exists, the Claim associated with the key provided func (k Keeper) getClaimByPrimaryKey(ctx sdk.Context, primaryKey []byte) (val types.Claim, found bool) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ClaimPrimaryKeyPrefix)) b := store.Get(primaryKey) @@ -121,17 +96,3 @@ func (k Keeper) getClaimByPrimaryKey(ctx sdk.Context, primaryKey []byte) (val ty k.cdc.MustUnmarshal(b, &val) return val, true } - -func (k Keeper) getCount(ctx sdk.Context, store prefix.Store) uint64 { - bz := store.Get(types.CountKey) - if bz == nil { - return 0 // Count doesn't exist: no element - } - return binary.BigEndian.Uint64(bz) -} - -func (k Keeper) setCount(ctx sdk.Context, store prefix.Store, count uint64) { - bz := make([]byte, 8) - binary.BigEndian.PutUint64(bz, count) - store.Set(types.CountKey, bz) -} diff --git a/x/supplier/keeper/claim_test.go b/x/supplier/keeper/claim_test.go index 443e83cf0..7b9a997f6 100644 --- a/x/supplier/keeper/claim_test.go +++ b/x/supplier/keeper/claim_test.go @@ -1,6 +1,7 @@ package keeper_test import ( + "fmt" "strconv" "testing" @@ -21,7 +22,8 @@ func createNClaims(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.Claim claims := make([]types.Claim, n) for i := range claims { claims[i].SupplierAddress = sample.AccAddress() - + claims[i].SessionId = fmt.Sprintf("session-%d", i) + claims[i].RootHash = []byte(fmt.Sprintf("rootHash-%d", i)) keeper.InsertClaim(ctx, claims[i]) } return claims @@ -32,7 +34,8 @@ func TestClaimGet(t *testing.T) { claims := createNClaims(keeper, ctx, 10) for _, claim := range claims { rst, found := keeper.GetClaim(ctx, - claim.Index, + claim.SessionId, + claim.SupplierAddress, ) require.True(t, found) require.Equal(t, diff --git a/x/supplier/keeper/query_claim.go b/x/supplier/keeper/query_claim.go index 9825587fc..15dd065f3 100644 --- a/x/supplier/keeper/query_claim.go +++ b/x/supplier/keeper/query_claim.go @@ -48,7 +48,8 @@ func (k Keeper) Claim(goCtx context.Context, req *types.QueryGetClaimRequest) (* val, found := k.GetClaim( ctx, - req.Index + req.SessionId, + req.SupplierAddress, ) if !found { return nil, status.Error(codes.NotFound, "not found") diff --git a/x/supplier/keeper/query_claim_test.go b/x/supplier/keeper/query_claim_test.go index 0d403a104..6b0abbcfd 100644 --- a/x/supplier/keeper/query_claim_test.go +++ b/x/supplier/keeper/query_claim_test.go @@ -1,7 +1,6 @@ package keeper_test import ( - "strconv" "testing" sdk "github.com/cosmos/cosmos-sdk/types" @@ -12,43 +11,71 @@ import ( keepertest "github.com/pokt-network/poktroll/testutil/keeper" "github.com/pokt-network/poktroll/testutil/nullify" + "github.com/pokt-network/poktroll/testutil/sample" "github.com/pokt-network/poktroll/x/supplier/types" ) func TestClaimQuerySingle(t *testing.T) { keeper, ctx := keepertest.SupplierKeeper(t) wctx := sdk.WrapSDKContext(ctx) - msgs := createNClaims(keeper, ctx, 2) + claims := createNClaims(keeper, ctx, 2) tests := []struct { - desc string - request *types.QueryGetClaimRequest + desc string + + request *types.QueryGetClaimRequest + response *types.QueryGetClaimResponse err error }{ { - desc: "First", + desc: "First Claim", + request: &types.QueryGetClaimRequest{ - Index: msgs[0].Index, + SessionId: claims[0].SessionId, + SupplierAddress: claims[0].SupplierAddress, }, - response: &types.QueryGetClaimResponse{Claim: msgs[0]}, + + response: &types.QueryGetClaimResponse{Claim: claims[0]}, }, { - desc: "Second", + desc: "Second Claim", + request: &types.QueryGetClaimRequest{ - Index: msgs[1].Index, + SessionId: claims[1].SessionId, + SupplierAddress: claims[1].SupplierAddress, }, - response: &types.QueryGetClaimResponse{Claim: msgs[1]}, + + response: &types.QueryGetClaimResponse{Claim: claims[1]}, }, { - desc: "KeyNotFound", + desc: "Claim Not Found - Random SessionId", + request: &types.QueryGetClaimRequest{ - Index: strconv.Itoa(100000), + SessionId: "not a real session id", + SupplierAddress: claims[0].SupplierAddress, }, + err: status.Error(codes.NotFound, "not found"), }, { - desc: "InvalidRequest", - err: status.Error(codes.InvalidArgument, "invalid request"), + desc: "Claim Not Found - Random Supplier Address", + + request: &types.QueryGetClaimRequest{ + SessionId: claims[0].SessionId, + SupplierAddress: sample.AccAddress(), + }, + + err: status.Error(codes.NotFound, "not found"), + }, + { + desc: "InvalidRequest - Missing SessionId", + + err: status.Error(codes.InvalidArgument, "invalid request"), + }, + { + desc: "InvalidRequest - Missing SessionId", + + err: status.Error(codes.InvalidArgument, "invalid request"), }, } for _, tc := range tests { diff --git a/x/supplier/types/key_claim.go b/x/supplier/types/key_claim.go index 64823ca36..ed11c5eae 100644 --- a/x/supplier/types/key_claim.go +++ b/x/supplier/types/key_claim.go @@ -25,7 +25,7 @@ const ( ClaimSessionIdPrefix = "Claim/sessionId/" ) -// ClaimPrimaryKey returns the primary store key to retrieve a Claim +// ClaimPrimaryKey returns the primary store key to retrieve a Claim by creating a composite key of the sessionId and supplierAddr func ClaimPrimaryKey(sessionId, supplierAddr string) []byte { var key []byte @@ -40,15 +40,12 @@ func ClaimPrimaryKey(sessionId, supplierAddr string) []byte { } // ClaimSupplierAddressKey returns the address key to iterate through claims given a supplier Address -func ClaimSupplierAddressKey(supplierAddr string, claimNum uint64) []byte { +func ClaimSupplierAddressKey(supplierAddr string, primaryKey []byte) []byte { var key []byte - numBz := make([]byte, 8) - binary.BigEndian.PutUint64(numBz, claimNum) - key = append(key, []byte(supplierAddr)...) - key = append(key, []byte("/num/")...) - key = append(key, numBz...) + key = append(key, []byte("/")...) + key = append(key, primaryKey...) key = append(key, []byte("/")...) return key diff --git a/x/supplier/types/message_create_claim.go b/x/supplier/types/message_create_claim.go index 0e702c956..0b810208c 100644 --- a/x/supplier/types/message_create_claim.go +++ b/x/supplier/types/message_create_claim.go @@ -67,4 +67,4 @@ func (msg *MsgCreateClaim) ValidateBasic() error { } return nil -} +} \ No newline at end of file diff --git a/x/supplier/types/query_get_claim.go b/x/supplier/types/query_get_claim.go new file mode 100644 index 000000000..97b968a2a --- /dev/null +++ b/x/supplier/types/query_get_claim.go @@ -0,0 +1,19 @@ +package types + +import ( + sdkerrors "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// NOTE: Please note that `QueryGetClaimRequest` 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 (query *QueryGetClaimRequest) ValidateBasic() error { + // Validate the supplier address + if _, err := sdk.AccAddressFromBech32(query.SupplierAddress); err != nil { + return sdkerrors.Wrapf(ErrSupplierInvalidAddress, "invalid supplier address for claim being retrieved %s; (%v)", query.SupplierAddress, err) + } + + // TODO_TECHDEBT: Validate the session ID once we have a deterministic way to generate it + return nil +}