From 1780b1ba7bfcf8bd9c811381c341a7ec14a68b0b Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Thu, 16 Nov 2023 16:44:50 -0800 Subject: [PATCH 01/16] Add a comment on scaffolding --- go.mod | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/go.mod b/go.mod index adbedcf85..50813a644 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,12 @@ +// NB: Since this repostiory was scaffolded using `ignite s chain pocket` +// but the module was later rename to the github repo name seen above, we +// need to swap the two lines below only during the scaffolding operation. +// Note that the operation will but all the necesary types will be generated. +// Ref: https://github.com/ignite/cli/issues/3737 module github.com/pokt-network/poktroll +// module pocket + + go 1.20 @@ -22,6 +30,7 @@ require ( github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 github.com/noot/ring-go v0.0.0-20231019173746-6c4b33bcf03f + github.com/pokt-network/poktroll v0.0.0-20231116164404-dd3434115ee1 github.com/pokt-network/smt v0.7.1 github.com/regen-network/gocuke v0.6.2 github.com/spf13/cast v1.5.1 From 1745b6af2696d9da73016c43805873080f78c0dc Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Thu, 16 Nov 2023 16:45:02 -0800 Subject: [PATCH 02/16] ignite scaffold map proof --module supplier supplier_address session_id root_hash --no-message --yes --- app/app.go | 1 - go.sum | 2 + proto/pocket/supplier/genesis.proto | 5 +- proto/pocket/supplier/proof.proto | 13 ++ proto/pocket/supplier/query.proto | 47 ++++++- proto/poktroll/supplier/tx.proto | 7 + x/supplier/client/cli/query.go | 4 +- x/supplier/client/cli/query_proof.go | 80 +++++++++++ x/supplier/client/cli/query_proof_test.go | 162 ++++++++++++++++++++++ x/supplier/genesis.go | 9 +- x/supplier/genesis_test.go | 13 +- x/supplier/keeper/msg_server_test.go | 7 +- x/supplier/keeper/proof.go | 63 +++++++++ x/supplier/keeper/proof_test.go | 66 +++++++++ x/supplier/keeper/query_proof.go | 57 ++++++++ x/supplier/keeper/query_proof_test.go | 130 +++++++++++++++++ x/supplier/types/codec.go | 3 + x/supplier/types/genesis.go | 15 +- x/supplier/types/genesis_test.go | 26 +++- x/supplier/types/key_proof.go | 23 +++ 20 files changed, 712 insertions(+), 21 deletions(-) create mode 100644 proto/pocket/supplier/proof.proto create mode 100644 proto/poktroll/supplier/tx.proto create mode 100644 x/supplier/client/cli/query_proof.go create mode 100644 x/supplier/client/cli/query_proof_test.go create mode 100644 x/supplier/keeper/proof.go create mode 100644 x/supplier/keeper/proof_test.go create mode 100644 x/supplier/keeper/query_proof.go create mode 100644 x/supplier/keeper/query_proof_test.go create mode 100644 x/supplier/types/key_proof.go diff --git a/app/app.go b/app/app.go index b34d4db68..eda44776f 100644 --- a/app/app.go +++ b/app/app.go @@ -6,7 +6,6 @@ import ( "io" "os" "path/filepath" - // this line is used by starport scaffolding # stargate/app/moduleImport autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" diff --git a/go.sum b/go.sum index 24322a896..2d5018511 100644 --- a/go.sum +++ b/go.sum @@ -1591,6 +1591,8 @@ github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qR github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pokt-network/poktroll v0.0.0-20231116164404-dd3434115ee1 h1:Y0eeoa4cDqykM3dPmXW4D6nMKNlalV5YjGqzCbAglqE= +github.com/pokt-network/poktroll v0.0.0-20231116164404-dd3434115ee1/go.mod h1:YLe1YzoVPuhPXiyIzUzhKpwf/70mjUZxdbKpFpX6js8= github.com/pokt-network/smt v0.7.1 h1:WHcZeMLe+9U1/kCAhdbssdyTYzYxxb74sf8MCvG34M8= github.com/pokt-network/smt v0.7.1/go.mod h1:K7BLEOWoZGZmY5USQuYvTkZ3qXjE6m39BMufBvVo3U8= github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4= diff --git a/proto/pocket/supplier/genesis.proto b/proto/pocket/supplier/genesis.proto index b8f184ef9..030daa3c5 100644 --- a/proto/pocket/supplier/genesis.proto +++ b/proto/pocket/supplier/genesis.proto @@ -6,6 +6,7 @@ import "gogoproto/gogo.proto"; import "pocket/supplier/params.proto"; import "pocket/shared/supplier.proto"; import "pocket/supplier/claim.proto"; +import "pocket/supplier/proof.proto"; option go_package = "github.com/pokt-network/poktroll/x/supplier/types"; @@ -13,7 +14,9 @@ option go_package = "github.com/pokt-network/poktroll/x/supplier/types"; message GenesisState { Params params = 1 [(gogoproto.nullable) = false]; repeated pocket.shared.Supplier supplierList = 2 [(gogoproto.nullable) = false]; + // TODO_UPNEXT(@Olshansk): Delete `claimList` from the genesis state. - repeated Claim claimList = 3 [(gogoproto.nullable) = false]; + repeated Claim claimList = 3 [(gogoproto.nullable) = false]; + repeated Proof proofList = 4 [(gogoproto.nullable) = false]; } diff --git a/proto/pocket/supplier/proof.proto b/proto/pocket/supplier/proof.proto new file mode 100644 index 000000000..6d27a25d2 --- /dev/null +++ b/proto/pocket/supplier/proof.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; +package pocket.supplier; + +option go_package = "pocket/x/supplier/types"; + +message Proof { + string index = 1; + string supplierAddress = 2; + string sessionId = 3; + string rootHash = 4; + +} + diff --git a/proto/pocket/supplier/query.proto b/proto/pocket/supplier/query.proto index 8e15e041a..1cc1d3a37 100644 --- a/proto/pocket/supplier/query.proto +++ b/proto/pocket/supplier/query.proto @@ -8,31 +8,47 @@ import "cosmos/base/query/v1beta1/pagination.proto"; import "pocket/supplier/params.proto"; import "pocket/shared/supplier.proto"; import "pocket/supplier/claim.proto"; +import "pocket/supplier/proof.proto"; option go_package = "github.com/pokt-network/poktroll/x/supplier/types"; // Query defines the gRPC querier service. service Query { - + // Parameters queries the parameters of the module. rpc Params (QueryParamsRequest) returns (QueryParamsResponse) { option (google.api.http).get = "/pocket/supplier/params"; + } - + // Queries a list of Supplier items. - rpc Supplier (QueryGetSupplierRequest) returns (QueryGetSupplierResponse) { + rpc Supplier (QueryGetSupplierRequest) returns (QueryGetSupplierResponse) { option (google.api.http).get = "/pocket/supplier/supplier/{address}"; + } rpc SupplierAll (QueryAllSupplierRequest) returns (QueryAllSupplierResponse) { option (google.api.http).get = "/pocket/supplier/supplier"; + } - + // Queries a list of Claim items. - rpc Claim (QueryGetClaimRequest) returns (QueryGetClaimResponse) { + rpc Claim (QueryGetClaimRequest ) returns (QueryGetClaimResponse ) { option (google.api.http).get = "/pocket/supplier/claim/{index}"; + } rpc AllClaims (QueryAllClaimsRequest) returns (QueryAllClaimsResponse) { option (google.api.http).get = "/pocket/supplier/claim"; + + } + + // Queries a list of Proof items. + rpc Proof (QueryGetProofRequest) returns (QueryGetProofResponse) { + option (google.api.http).get = "/pocket/supplier/proof/{index}"; + + } + rpc ProofAll (QueryAllProofRequest) returns (QueryAllProofResponse) { + option (google.api.http).get = "/pocket/supplier/proof"; + } } // QueryParamsRequest is request type for the Query/Params RPC method. @@ -40,6 +56,7 @@ message QueryParamsRequest {} // QueryParamsResponse is response type for the Query/Params RPC method. message QueryParamsResponse { + // params holds all the parameters of this module. Params params = 1 [(gogoproto.nullable) = false]; } @@ -76,4 +93,22 @@ message QueryAllClaimsRequest { message QueryAllClaimsResponse { repeated Claim claim = 1 [(gogoproto.nullable) = false]; cosmos.base.query.v1beta1.PageResponse pagination = 2; -} \ No newline at end of file +} + +message QueryGetProofRequest { + string index = 1; +} + +message QueryGetProofResponse { + Proof proof = 1 [(gogoproto.nullable) = false]; +} + +message QueryAllProofRequest { + cosmos.base.query.v1beta1.PageRequest pagination = 1; +} + +message QueryAllProofResponse { + repeated Proof proof = 1 [(gogoproto.nullable) = false]; + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + diff --git a/proto/poktroll/supplier/tx.proto b/proto/poktroll/supplier/tx.proto new file mode 100644 index 000000000..a79dbc183 --- /dev/null +++ b/proto/poktroll/supplier/tx.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; +package poktroll.supplier; + +option go_package = "github.com/pokt-network/poktroll/x/supplier/types"; + +// Msg defines the Msg service. +service Msg {} \ No newline at end of file diff --git a/x/supplier/client/cli/query.go b/x/supplier/client/cli/query.go index f70e996ba..09916e9f0 100644 --- a/x/supplier/client/cli/query.go +++ b/x/supplier/client/cli/query.go @@ -29,7 +29,9 @@ func GetQueryCmd(queryRoute string) *cobra.Command { cmd.AddCommand(CmdShowSupplier()) cmd.AddCommand(CmdListClaim()) cmd.AddCommand(CmdShowClaim()) - // this line is used by starport scaffolding # 1 + cmd.AddCommand(CmdListProof()) + cmd.AddCommand(CmdShowProof()) +// this line is used by starport scaffolding # 1 return cmd } diff --git a/x/supplier/client/cli/query_proof.go b/x/supplier/client/cli/query_proof.go new file mode 100644 index 000000000..1fbcbcb87 --- /dev/null +++ b/x/supplier/client/cli/query_proof.go @@ -0,0 +1,80 @@ +package cli + +import ( + "github.com/spf13/cobra" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + + + "pocket/x/supplier/types" +) + +func CmdListProof() *cobra.Command { + cmd := &cobra.Command{ + Use: "list-proof", + Short: "list all proof", + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + + params := &types.QueryAllProofRequest{ + Pagination: pageReq, + } + + res, err := queryClient.ProofAll(cmd.Context(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddPaginationFlagsToCmd(cmd, cmd.Use) + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +func CmdShowProof() *cobra.Command { + cmd := &cobra.Command{ + Use: "show-proof [index]", + Short: "shows a proof", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) (err error) { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + + argIndex := args[0] + + params := &types.QueryGetProofRequest{ + Index: argIndex, + + } + + res, err := queryClient.Proof(cmd.Context(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/x/supplier/client/cli/query_proof_test.go b/x/supplier/client/cli/query_proof_test.go new file mode 100644 index 000000000..5bfc25421 --- /dev/null +++ b/x/supplier/client/cli/query_proof_test.go @@ -0,0 +1,162 @@ +package cli_test + +import ( + "fmt" + "strconv" + "testing" + + "github.com/cosmos/cosmos-sdk/client/flags" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + "github.com/stretchr/testify/require" + tmcli "github.com/cometbft/cometbft/libs/cli" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "pocket/testutil/network" + "pocket/testutil/nullify" + "pocket/x/supplier/client/cli" + "pocket/x/supplier/types" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func networkWithProofObjects(t *testing.T, n int) (*network.Network, []types.Proof) { + t.Helper() + cfg := network.DefaultConfig() + state := types.GenesisState{} + for i := 0; i < n; i++ { + proof := types.Proof{ + Index: strconv.Itoa(i), + + } + nullify.Fill(&proof) + state.ProofList = append(state.ProofList, proof) + } + buf, err := cfg.Codec.MarshalJSON(&state) + require.NoError(t, err) + cfg.GenesisState[types.ModuleName] = buf + return network.New(t, cfg), state.ProofList +} + +func TestShowProof(t *testing.T) { + net, objs := networkWithProofObjects(t, 2) + + ctx := net.Validators[0].ClientCtx + common := []string{ + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + } + tests := []struct { + desc string + idIndex string + + args []string + err error + obj types.Proof + }{ + { + desc: "found", + idIndex: objs[0].Index, + + args: common, + obj: objs[0], + }, + { + desc: "not found", + idIndex: strconv.Itoa(100000), + + args: common, + err: status.Error(codes.NotFound, "not found"), + }, + } + for _, tc := range tests { + t.Run(tc.desc, func(t *testing.T) { + args := []string{ + tc.idIndex, + + } + args = append(args, tc.args...) + out, err := clitestutil.ExecTestCLICmd(ctx, cli.CmdShowProof(), args) + if tc.err != nil { + stat, ok := status.FromError(tc.err) + require.True(t, ok) + require.ErrorIs(t, stat.Err(), tc.err) + } else { + require.NoError(t, err) + var resp types.QueryGetProofResponse + require.NoError(t, net.Config.Codec.UnmarshalJSON(out.Bytes(), &resp)) + require.NotNil(t, resp.Proof) + require.Equal(t, + nullify.Fill(&tc.obj), + nullify.Fill(&resp.Proof), + ) + } + }) + } +} + +func TestListProof(t *testing.T) { + net, objs := networkWithProofObjects(t, 5) + + ctx := net.Validators[0].ClientCtx + request := func(next []byte, offset, limit uint64, total bool) []string { + args := []string{ + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + } + if next == nil { + args = append(args, fmt.Sprintf("--%s=%d", flags.FlagOffset, offset)) + } else { + args = append(args, fmt.Sprintf("--%s=%s", flags.FlagPageKey, next)) + } + args = append(args, fmt.Sprintf("--%s=%d", flags.FlagLimit, limit)) + if total { + args = append(args, fmt.Sprintf("--%s", flags.FlagCountTotal)) + } + return args + } + t.Run("ByOffset", func(t *testing.T) { + step := 2 + for i := 0; i < len(objs); i += step { + args := request(nil, uint64(i), uint64(step), false) + out, err := clitestutil.ExecTestCLICmd(ctx, cli.CmdListProof(), args) + require.NoError(t, err) + var resp types.QueryAllProofResponse + require.NoError(t, net.Config.Codec.UnmarshalJSON(out.Bytes(), &resp)) + require.LessOrEqual(t, len(resp.Proof), step) + require.Subset(t, + nullify.Fill(objs), + nullify.Fill(resp.Proof), + ) + } + }) + t.Run("ByKey", func(t *testing.T) { + step := 2 + var next []byte + for i := 0; i < len(objs); i += step { + args := request(next, 0, uint64(step), false) + out, err := clitestutil.ExecTestCLICmd(ctx, cli.CmdListProof(), args) + require.NoError(t, err) + var resp types.QueryAllProofResponse + require.NoError(t, net.Config.Codec.UnmarshalJSON(out.Bytes(), &resp)) + require.LessOrEqual(t, len(resp.Proof), step) + require.Subset(t, + nullify.Fill(objs), + nullify.Fill(resp.Proof), + ) + next = resp.Pagination.NextKey + } + }) + t.Run("Total", func(t *testing.T) { + args := request(nil, 0, uint64(len(objs)), true) + out, err := clitestutil.ExecTestCLICmd(ctx, cli.CmdListProof(), args) + require.NoError(t, err) + var resp types.QueryAllProofResponse + require.NoError(t, net.Config.Codec.UnmarshalJSON(out.Bytes(), &resp)) + require.NoError(t, err) + require.Equal(t, len(objs), int(resp.Pagination.Total)) + require.ElementsMatch(t, + nullify.Fill(objs), + nullify.Fill(resp.Proof), + ) + }) +} diff --git a/x/supplier/genesis.go b/x/supplier/genesis.go index bda688fb9..ceb285cb4 100644 --- a/x/supplier/genesis.go +++ b/x/supplier/genesis.go @@ -18,7 +18,11 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) for _, elem := range genState.ClaimList { k.SetClaim(ctx, elem) } - // this line is used by starport scaffolding # genesis/module/init + // Set all the proof +for _, elem := range genState.ProofList { + k.SetProof(ctx, elem) +} +// this line is used by starport scaffolding # genesis/module/init k.SetParams(ctx, genState.Params) } @@ -29,7 +33,8 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { genesis.SupplierList = k.GetAllSupplier(ctx) genesis.ClaimList = k.GetAllClaims(ctx) - // this line is used by starport scaffolding # genesis/module/export + genesis.ProofList = k.GetAllProof(ctx) +// this line is used by starport scaffolding # genesis/module/export return genesis } diff --git a/x/supplier/genesis_test.go b/x/supplier/genesis_test.go index 3afdd0a8a..cde2322d1 100644 --- a/x/supplier/genesis_test.go +++ b/x/supplier/genesis_test.go @@ -64,7 +64,15 @@ func TestGenesis(t *testing.T) { Index: "1", }, }, - // this line is used by starport scaffolding # genesis/test/state + ProofList: []types.Proof{ + { + Index: "0", +}, + { + Index: "1", +}, + }, + // this line is used by starport scaffolding # genesis/test/state } k, ctx := keepertest.SupplierKeeper(t) @@ -77,5 +85,6 @@ func TestGenesis(t *testing.T) { require.ElementsMatch(t, genesisState.SupplierList, got.SupplierList) require.ElementsMatch(t, genesisState.ClaimList, got.ClaimList) - // this line is used by starport scaffolding # genesis/test/assert + require.ElementsMatch(t, genesisState.ProofList, got.ProofList) +// this line is used by starport scaffolding # genesis/test/assert } diff --git a/x/supplier/keeper/msg_server_test.go b/x/supplier/keeper/msg_server_test.go index 7e4d01f27..39fc0075f 100644 --- a/x/supplier/keeper/msg_server_test.go +++ b/x/supplier/keeper/msg_server_test.go @@ -6,10 +6,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" - - keepertest "github.com/pokt-network/poktroll/testutil/keeper" - "github.com/pokt-network/poktroll/x/supplier/keeper" - "github.com/pokt-network/poktroll/x/supplier/types" + "github.com/pokt-network/poktroll/x/supplier/types" + "github.com/pokt-network/poktroll/x/supplier/keeper" + keepertest "github.com/pokt-network/poktroll/testutil/keeper" ) func setupMsgServer(t testing.TB) (types.MsgServer, context.Context) { diff --git a/x/supplier/keeper/proof.go b/x/supplier/keeper/proof.go new file mode 100644 index 000000000..a1ee384a5 --- /dev/null +++ b/x/supplier/keeper/proof.go @@ -0,0 +1,63 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "pocket/x/supplier/types" + "github.com/cosmos/cosmos-sdk/store/prefix" +) + +// SetProof set a specific proof in the store from its index +func (k Keeper) SetProof(ctx sdk.Context, proof types.Proof) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ProofKeyPrefix)) + b := k.cdc.MustMarshal(&proof) + store.Set(types.ProofKey( + proof.Index, + ), b) +} + +// GetProof returns a proof from its index +func (k Keeper) GetProof( + ctx sdk.Context, + index string, + +) (val types.Proof, found bool) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ProofKeyPrefix)) + + b := store.Get(types.ProofKey( + index, + )) + if b == nil { + return val, false + } + + k.cdc.MustUnmarshal(b, &val) + return val, true +} + +// RemoveProof removes a proof from the store +func (k Keeper) RemoveProof( + ctx sdk.Context, + index string, + +) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ProofKeyPrefix)) + store.Delete(types.ProofKey( + index, + )) +} + +// GetAllProof returns all proof +func (k Keeper) GetAllProof(ctx sdk.Context) (list []types.Proof) { + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ProofKeyPrefix)) + iterator := sdk.KVStorePrefixIterator(store, []byte{}) + + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + var val types.Proof + k.cdc.MustUnmarshal(iterator.Value(), &val) + list = append(list, val) + } + + return +} diff --git a/x/supplier/keeper/proof_test.go b/x/supplier/keeper/proof_test.go new file mode 100644 index 000000000..27ee00272 --- /dev/null +++ b/x/supplier/keeper/proof_test.go @@ -0,0 +1,66 @@ +package keeper_test + +import ( + "strconv" + "testing" + + "pocket/x/supplier/keeper" + "pocket/x/supplier/types" + keepertest "pocket/testutil/keeper" + "pocket/testutil/nullify" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func createNProof(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.Proof { + items := make([]types.Proof, n) + for i := range items { + items[i].Index = strconv.Itoa(i) + + keeper.SetProof(ctx, items[i]) + } + return items +} + +func TestProofGet(t *testing.T) { + keeper, ctx := keepertest.SupplierKeeper(t) + items := createNProof(keeper, ctx, 10) + for _, item := range items { + rst, found := keeper.GetProof(ctx, + item.Index, + + ) + require.True(t, found) + require.Equal(t, + nullify.Fill(&item), + nullify.Fill(&rst), + ) + } +} +func TestProofRemove(t *testing.T) { + keeper, ctx := keepertest.SupplierKeeper(t) + items := createNProof(keeper, ctx, 10) + for _, item := range items { + keeper.RemoveProof(ctx, + item.Index, + + ) + _, found := keeper.GetProof(ctx, + item.Index, + + ) + require.False(t, found) + } +} + +func TestProofGetAll(t *testing.T) { + keeper, ctx := keepertest.SupplierKeeper(t) + items := createNProof(keeper, ctx, 10) + require.ElementsMatch(t, + nullify.Fill(items), + nullify.Fill(keeper.GetAllProof(ctx)), + ) +} diff --git a/x/supplier/keeper/query_proof.go b/x/supplier/keeper/query_proof.go new file mode 100644 index 000000000..a029b9953 --- /dev/null +++ b/x/supplier/keeper/query_proof.go @@ -0,0 +1,57 @@ +package keeper + +import ( + "context" + + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + "pocket/x/supplier/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (k Keeper) ProofAll(goCtx context.Context, req *types.QueryAllProofRequest) (*types.QueryAllProofResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + var proofs []types.Proof + ctx := sdk.UnwrapSDKContext(goCtx) + + store := ctx.KVStore(k.storeKey) + proofStore := prefix.NewStore(store, types.KeyPrefix(types.ProofKeyPrefix)) + + pageRes, err := query.Paginate(proofStore, req.Pagination, func(key []byte, value []byte) error { + var proof types.Proof + if err := k.cdc.Unmarshal(value, &proof); err != nil { + return err + } + + proofs = append(proofs, proof) + return nil + }) + + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return &types.QueryAllProofResponse{Proof: proofs, Pagination: pageRes}, nil +} + +func (k Keeper) Proof(goCtx context.Context, req *types.QueryGetProofRequest) (*types.QueryGetProofResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + ctx := sdk.UnwrapSDKContext(goCtx) + + val, found := k.GetProof( + ctx, + req.Index, + ) + if !found { + return nil, status.Error(codes.NotFound, "not found") + } + + return &types.QueryGetProofResponse{Proof: val}, nil +} \ No newline at end of file diff --git a/x/supplier/keeper/query_proof_test.go b/x/supplier/keeper/query_proof_test.go new file mode 100644 index 000000000..ae29f46cf --- /dev/null +++ b/x/supplier/keeper/query_proof_test.go @@ -0,0 +1,130 @@ +package keeper_test + +import ( + "strconv" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "pocket/x/supplier/types" + "pocket/testutil/nullify" + keepertest "pocket/testutil/keeper" +) + +// Prevent strconv unused error +var _ = strconv.IntSize + +func TestProofQuerySingle(t *testing.T) { + keeper, ctx := keepertest.SupplierKeeper(t) + wctx := sdk.WrapSDKContext(ctx) + msgs := createNProof(keeper, ctx, 2) + tests := []struct { + desc string + request *types.QueryGetProofRequest + response *types.QueryGetProofResponse + err error + }{ + { + desc: "First", + request: &types.QueryGetProofRequest{ + Index: msgs[0].Index, + + }, + response: &types.QueryGetProofResponse{Proof: msgs[0]}, + }, + { + desc: "Second", + request: &types.QueryGetProofRequest{ + Index: msgs[1].Index, + + }, + response: &types.QueryGetProofResponse{Proof: msgs[1]}, + }, + { + desc: "KeyNotFound", + request: &types.QueryGetProofRequest{ + Index:strconv.Itoa(100000), + + }, + err: status.Error(codes.NotFound, "not found"), + }, + { + desc: "InvalidRequest", + err: status.Error(codes.InvalidArgument, "invalid request"), + }, + } + for _, tc := range tests { + t.Run(tc.desc, func(t *testing.T) { + response, err := keeper.Proof(wctx, tc.request) + if tc.err != nil { + require.ErrorIs(t, err, tc.err) + } else { + require.NoError(t, err) + require.Equal(t, + nullify.Fill(tc.response), + nullify.Fill(response), + ) + } + }) + } +} + +func TestProofQueryPaginated(t *testing.T) { + keeper, ctx := keepertest.SupplierKeeper(t) + wctx := sdk.WrapSDKContext(ctx) + msgs := createNProof(keeper, ctx, 5) + + request := func(next []byte, offset, limit uint64, total bool) *types.QueryAllProofRequest { + return &types.QueryAllProofRequest{ + Pagination: &query.PageRequest{ + Key: next, + Offset: offset, + Limit: limit, + CountTotal: total, + }, + } + } + t.Run("ByOffset", func(t *testing.T) { + step := 2 + for i := 0; i < len(msgs); i += step { + resp, err := keeper.ProofAll(wctx, request(nil, uint64(i), uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.Proof), step) + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(resp.Proof), + ) + } + }) + t.Run("ByKey", func(t *testing.T) { + step := 2 + var next []byte + for i := 0; i < len(msgs); i += step { + resp, err := keeper.ProofAll(wctx, request(next, 0, uint64(step), false)) + require.NoError(t, err) + require.LessOrEqual(t, len(resp.Proof), step) + require.Subset(t, + nullify.Fill(msgs), + nullify.Fill(resp.Proof), + ) + next = resp.Pagination.NextKey + } + }) + t.Run("Total", func(t *testing.T) { + resp, err := keeper.ProofAll(wctx, request(nil, 0, 0, true)) + require.NoError(t, err) + require.Equal(t, len(msgs), int(resp.Pagination.Total)) + require.ElementsMatch(t, + nullify.Fill(msgs), + nullify.Fill(resp.Proof), + ) + }) + t.Run("InvalidRequest", func(t *testing.T) { + _, err := keeper.ProofAll(wctx, nil) + require.ErrorIs(t, err, status.Error(codes.InvalidArgument, "invalid request")) + }) +} diff --git a/x/supplier/types/codec.go b/x/supplier/types/codec.go index 364fde198..02d5e43a5 100644 --- a/x/supplier/types/codec.go +++ b/x/supplier/types/codec.go @@ -1,6 +1,7 @@ package types import ( +"github.com/cosmos/cosmos-sdk/types/msgservice" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -28,6 +29,8 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { ) // this line is used by starport scaffolding # 3 +msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) diff --git a/x/supplier/types/genesis.go b/x/supplier/types/genesis.go index 521bfdc0d..3e685dc14 100644 --- a/x/supplier/types/genesis.go +++ b/x/supplier/types/genesis.go @@ -18,7 +18,8 @@ func DefaultGenesis() *GenesisState { return &GenesisState{ SupplierList: []sharedtypes.Supplier{}, ClaimList: []Claim{}, - // this line is used by starport scaffolding # genesis/types/default + ProofList: []Proof{}, +// this line is used by starport scaffolding # genesis/types/default Params: DefaultParams(), } } @@ -73,7 +74,17 @@ func (gs GenesisState) Validate() error { } claimIndexMap[index] = struct{}{} } - // this line is used by starport scaffolding # genesis/types/validate + // Check for duplicated index in proof +proofIndexMap := make(map[string]struct{}) + +for _, elem := range gs.ProofList { + index := string(ProofKey(elem.Index)) + if _, ok := proofIndexMap[index]; ok { + return fmt.Errorf("duplicated index for proof") + } + proofIndexMap[index] = struct{}{} +} +// this line is used by starport scaffolding # genesis/types/validate return gs.Params.Validate() } diff --git a/x/supplier/types/genesis_test.go b/x/supplier/types/genesis_test.go index 6a0c11190..c851c4ec9 100644 --- a/x/supplier/types/genesis_test.go +++ b/x/supplier/types/genesis_test.go @@ -78,7 +78,15 @@ func TestGenesisState_Validate(t *testing.T) { Index: "1", }, }, - // this line is used by starport scaffolding # types/genesis/validField + ProofList: []types.Proof{ + { + Index: "0", +}, + { + Index: "1", +}, +}, +// this line is used by starport scaffolding # types/genesis/validField }, valid: true, }, @@ -320,7 +328,21 @@ func TestGenesisState_Validate(t *testing.T) { }, valid: false, }, - // this line is used by starport scaffolding # types/genesis/testcase + { + desc: "duplicated proof", + genState: &types.GenesisState{ + ProofList: []types.Proof{ + { + Index: "0", +}, + { + Index: "0", +}, + }, + }, + valid: false, +}, +// this line is used by starport scaffolding # types/genesis/testcase } for _, tc := range tests { t.Run(tc.desc, func(t *testing.T) { diff --git a/x/supplier/types/key_proof.go b/x/supplier/types/key_proof.go new file mode 100644 index 000000000..5a2f19a4c --- /dev/null +++ b/x/supplier/types/key_proof.go @@ -0,0 +1,23 @@ +package types + +import "encoding/binary" + +var _ binary.ByteOrder + +const ( + // ProofKeyPrefix is the prefix to retrieve all Proof + ProofKeyPrefix = "Proof/value/" +) + +// ProofKey returns the store key to retrieve a Proof from the index fields +func ProofKey( +index string, +) []byte { + var key []byte + + indexBytes := []byte(index) + key = append(key, indexBytes...) + key = append(key, []byte("/")...) + + return key +} \ No newline at end of file From a0e9e8d0d8a1368ce07a537d2502be318b6988be Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Thu, 16 Nov 2023 18:12:36 -0800 Subject: [PATCH 03/16] Remove proof list --- docs/static/openapi.yml | 265 ++++++++++++++++++++ go.mod | 17 +- go.sum | 2 - proto/pocket/supplier/genesis.proto | 3 +- proto/pocket/supplier/proof.proto | 13 +- proto/poktroll/supplier/tx.proto | 7 - x/supplier/client/cli/query_proof.go | 84 ++++--- x/supplier/client/cli/query_proof_test.go | 287 ++++++++++------------ x/supplier/genesis.go | 10 +- x/supplier/genesis_test.go | 16 +- x/supplier/keeper/proof.go | 42 ++-- x/supplier/keeper/proof_test.go | 16 +- x/supplier/keeper/query_proof.go | 12 +- x/supplier/keeper/query_proof_test.go | 40 ++- x/supplier/types/genesis.go | 15 +- x/supplier/types/genesis_test.go | 30 +-- x/supplier/types/message_create_claim.go | 1 - 17 files changed, 526 insertions(+), 334 deletions(-) delete mode 100644 proto/poktroll/supplier/tx.proto diff --git a/docs/static/openapi.yml b/docs/static/openapi.yml index f55a851f2..7762ac8a9 100644 --- a/docs/static/openapi.yml +++ b/docs/static/openapi.yml @@ -47646,6 +47646,189 @@ paths: additionalProperties: {} tags: - Query + /pocket/supplier/proof: + get: + operationId: PocketSupplierProofAll + responses: + '200': + description: A successful response. + schema: + type: object + properties: + proof: + type: array + items: + type: object + properties: + index: + type: string + supplier_address: + type: string + session_id: + type: string + merkle_proof: + type: string + description: >- + TODO_UPNEXT(@Olshansk): The structure below is the default + (untouched) scaffolded type. Update + + and productionize it for our use case. + pagination: + type: object + properties: + next_key: + type: string + format: byte + description: |- + next_key is the key to be passed to PageRequest.key to + query the next page most efficiently. It will be empty if + there are no more results. + total: + type: string + format: uint64 + title: >- + total is total number of results available if + PageRequest.count_total + + was set, its value is undefined otherwise + description: >- + PageResponse is to be embedded in gRPC response messages where + the + + corresponding request message has used PageRequest. + + message SomeResponse { + repeated Bar results = 1; + PageResponse page = 2; + } + 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: pagination.key + description: |- + key is a value returned in PageResponse.next_key to begin + querying the next page most efficiently. Only one of offset or key + should be set. + in: query + required: false + type: string + format: byte + - name: pagination.offset + description: >- + offset is a numeric offset that can be used when key is unavailable. + + It is less efficient than using key. Only one of offset or key + should + + be set. + in: query + required: false + type: string + format: uint64 + - name: pagination.limit + description: >- + limit is the total number of results to be returned in the result + page. + + If left empty it will default to a value to be set by each app. + in: query + required: false + type: string + format: uint64 + - name: pagination.count_total + description: >- + count_total is set to true to indicate that the result set should + include + + a count of the total number of items available for pagination in + UIs. + + count_total is only respected when offset is used. It is ignored + when key + + is set. + in: query + required: false + type: boolean + - name: pagination.reverse + description: >- + reverse is set to true if results are to be returned in the + descending order. + + + Since: cosmos-sdk 0.43 + in: query + required: false + type: boolean + tags: + - Query + /pocket/supplier/proof/{index}: + get: + summary: Queries a list of Proof items. + operationId: PocketSupplierProof + responses: + '200': + description: A successful response. + schema: + type: object + properties: + proof: + type: object + properties: + index: + type: string + supplier_address: + type: string + session_id: + type: string + merkle_proof: + type: string + description: >- + TODO_UPNEXT(@Olshansk): The structure below is the default + (untouched) scaffolded type. Update + + and productionize it for our use case. + 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: index + in: path + required: true + type: string + tags: + - Query /pocket/supplier/supplier: get: operationId: PocketSupplierSupplierAll @@ -78043,6 +78226,22 @@ definitions: pocket.supplier.Params: type: object description: Params defines the parameters for the module. + pocket.supplier.Proof: + type: object + properties: + index: + type: string + supplier_address: + type: string + session_id: + type: string + merkle_proof: + type: string + description: >- + TODO_UPNEXT(@Olshansk): The structure below is the default (untouched) + scaffolded type. Update + + and productionize it for our use case. pocket.supplier.QueryAllClaimsResponse: type: object properties: @@ -78090,6 +78289,53 @@ definitions: repeated Bar results = 1; PageResponse page = 2; } + pocket.supplier.QueryAllProofResponse: + type: object + properties: + proof: + type: array + items: + type: object + properties: + index: + type: string + supplier_address: + type: string + session_id: + type: string + merkle_proof: + type: string + description: >- + TODO_UPNEXT(@Olshansk): The structure below is the default + (untouched) scaffolded type. Update + + and productionize it for our use case. + pagination: + type: object + properties: + next_key: + type: string + format: byte + description: |- + next_key is the key to be passed to PageRequest.key to + query the next page most efficiently. It will be empty if + there are no more results. + total: + type: string + format: uint64 + title: >- + total is total number of results available if + PageRequest.count_total + + was set, its value is undefined otherwise + description: |- + PageResponse is to be embedded in gRPC response messages where the + corresponding request message has used PageRequest. + + message SomeResponse { + repeated Bar results = 1; + PageResponse page = 2; + } pocket.supplier.QueryAllSupplierResponse: type: object properties: @@ -78250,6 +78496,25 @@ definitions: TODO_UPNEXT(@Olshansk): The structure below is the default (untouched) scaffolded type. Update + and productionize it for our use case. + pocket.supplier.QueryGetProofResponse: + type: object + properties: + proof: + type: object + properties: + index: + type: string + supplier_address: + type: string + session_id: + type: string + merkle_proof: + type: string + description: >- + TODO_UPNEXT(@Olshansk): The structure below is the default (untouched) + scaffolded type. Update + and productionize it for our use case. pocket.supplier.QueryGetSupplierResponse: type: object diff --git a/go.mod b/go.mod index 50813a644..35cb81d15 100644 --- a/go.mod +++ b/go.mod @@ -1,12 +1,18 @@ // NB: Since this repostiory was scaffolded using `ignite s chain pocket` -// but the module was later rename to the github repo name seen above, we +// but the module was later rename to github.com/pokt-network/poktroll, we // need to swap the two lines below only during the scaffolding operation. -// Note that the operation will but all the necesary types will be generated. +// NOTE that the operation is expected to error out but all the necesary +// types and functions will be scaffolded correctly. // Ref: https://github.com/ignite/cli/issues/3737 -module github.com/pokt-network/poktroll -// module pocket - +// +// The following will need to be done manually after the scaffold: +// - Reverting the module name in go.mod (this file) +// - Manually updating imports in .go files: "pocket/x/" => "github.com/pokt-network/pocket/x/" +// - Manually `option go_package` in .proto files: `option go_package = "pocket` => `option go_package = "github.com/pokt-network/poktroll` +// - If an empty `service Msg {}` is generated in a `tx.proto` file, remove it +// module pocket +module github.com/pokt-network/poktroll go 1.20 @@ -30,7 +36,6 @@ require ( github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 github.com/noot/ring-go v0.0.0-20231019173746-6c4b33bcf03f - github.com/pokt-network/poktroll v0.0.0-20231116164404-dd3434115ee1 github.com/pokt-network/smt v0.7.1 github.com/regen-network/gocuke v0.6.2 github.com/spf13/cast v1.5.1 diff --git a/go.sum b/go.sum index 2d5018511..24322a896 100644 --- a/go.sum +++ b/go.sum @@ -1591,8 +1591,6 @@ github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qR github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pokt-network/poktroll v0.0.0-20231116164404-dd3434115ee1 h1:Y0eeoa4cDqykM3dPmXW4D6nMKNlalV5YjGqzCbAglqE= -github.com/pokt-network/poktroll v0.0.0-20231116164404-dd3434115ee1/go.mod h1:YLe1YzoVPuhPXiyIzUzhKpwf/70mjUZxdbKpFpX6js8= github.com/pokt-network/smt v0.7.1 h1:WHcZeMLe+9U1/kCAhdbssdyTYzYxxb74sf8MCvG34M8= github.com/pokt-network/smt v0.7.1/go.mod h1:K7BLEOWoZGZmY5USQuYvTkZ3qXjE6m39BMufBvVo3U8= github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4= diff --git a/proto/pocket/supplier/genesis.proto b/proto/pocket/supplier/genesis.proto index 030daa3c5..31daadb1b 100644 --- a/proto/pocket/supplier/genesis.proto +++ b/proto/pocket/supplier/genesis.proto @@ -14,9 +14,8 @@ option go_package = "github.com/pokt-network/poktroll/x/supplier/types"; message GenesisState { Params params = 1 [(gogoproto.nullable) = false]; repeated pocket.shared.Supplier supplierList = 2 [(gogoproto.nullable) = false]; - + // TODO_UPNEXT(@Olshansk): Delete `claimList` from the genesis state. repeated Claim claimList = 3 [(gogoproto.nullable) = false]; - repeated Proof proofList = 4 [(gogoproto.nullable) = false]; } diff --git a/proto/pocket/supplier/proof.proto b/proto/pocket/supplier/proof.proto index 6d27a25d2..26c1ab120 100644 --- a/proto/pocket/supplier/proof.proto +++ b/proto/pocket/supplier/proof.proto @@ -1,13 +1,14 @@ syntax = "proto3"; package pocket.supplier; -option go_package = "pocket/x/supplier/types"; +option go_package = "github.com/pokt-network/poktroll/x/supplier/types"; +// TODO_UPNEXT(@Olshansk): The structure below is the default (untouched) scaffolded type. Update +// and productionize it for our use case. message Proof { - string index = 1; - string supplierAddress = 2; - string sessionId = 3; - string rootHash = 4; - + string index = 1; + string supplier_address = 2; + string session_id = 3; + string merkle_proof = 4; } diff --git a/proto/poktroll/supplier/tx.proto b/proto/poktroll/supplier/tx.proto deleted file mode 100644 index a79dbc183..000000000 --- a/proto/poktroll/supplier/tx.proto +++ /dev/null @@ -1,7 +0,0 @@ -syntax = "proto3"; -package poktroll.supplier; - -option go_package = "github.com/pokt-network/poktroll/x/supplier/types"; - -// Msg defines the Msg service. -service Msg {} \ No newline at end of file diff --git a/x/supplier/client/cli/query_proof.go b/x/supplier/client/cli/query_proof.go index 1fbcbcb87..2c7dfea7a 100644 --- a/x/supplier/client/cli/query_proof.go +++ b/x/supplier/client/cli/query_proof.go @@ -1,12 +1,11 @@ package cli import ( - "github.com/spf13/cobra" + "github.com/pokt-network/poktroll/x/supplier/types" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" - - - "pocket/x/supplier/types" + "github.com/spf13/cobra" ) func CmdListProof() *cobra.Command { @@ -14,35 +13,35 @@ func CmdListProof() *cobra.Command { Use: "list-proof", Short: "list all proof", RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } - pageReq, err := client.ReadPageRequest(cmd.Flags()) - if err != nil { - return err - } + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } - queryClient := types.NewQueryClient(clientCtx) + queryClient := types.NewQueryClient(clientCtx) - params := &types.QueryAllProofRequest{ - Pagination: pageReq, - } + params := &types.QueryAllProofRequest{ + Pagination: pageReq, + } - res, err := queryClient.ProofAll(cmd.Context(), params) - if err != nil { - return err - } + res, err := queryClient.ProofAll(cmd.Context(), params) + if err != nil { + return err + } - return clientCtx.PrintProto(res) + return clientCtx.PrintProto(res) }, } flags.AddPaginationFlagsToCmd(cmd, cmd.Use) flags.AddQueryFlagsToCmd(cmd) - return cmd + return cmd } func CmdShowProof() *cobra.Command { @@ -51,30 +50,29 @@ func CmdShowProof() *cobra.Command { Short: "shows a proof", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) (err error) { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - - queryClient := types.NewQueryClient(clientCtx) - - argIndex := args[0] - - params := &types.QueryGetProofRequest{ - Index: argIndex, - - } - - res, err := queryClient.Proof(cmd.Context(), params) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + + argIndex := args[0] + + params := &types.QueryGetProofRequest{ + Index: argIndex, + } + + res, err := queryClient.Proof(cmd.Context(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) }, } flags.AddQueryFlagsToCmd(cmd) - return cmd + return cmd } diff --git a/x/supplier/client/cli/query_proof_test.go b/x/supplier/client/cli/query_proof_test.go index 5bfc25421..b87f4e24f 100644 --- a/x/supplier/client/cli/query_proof_test.go +++ b/x/supplier/client/cli/query_proof_test.go @@ -1,162 +1,145 @@ package cli_test -import ( - "fmt" - "strconv" - "testing" +// TODO_UPNEXT(@Olshansk): Add these tests back in after updating how Proofs are stored on-chain. +// Prevent strconv unused error +// var _ = strconv.IntSize - "github.com/cosmos/cosmos-sdk/client/flags" - clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" - "github.com/stretchr/testify/require" - tmcli "github.com/cometbft/cometbft/libs/cli" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" +// func networkWithProofObjects(t *testing.T, n int) (*network.Network, []types.Proof) { +// t.Helper() +// cfg := network.DefaultConfig() +// state := types.GenesisState{} +// for i := 0; i < n; i++ { +// proof := types.Proof{ +// Index: strconv.Itoa(i), - "pocket/testutil/network" - "pocket/testutil/nullify" - "pocket/x/supplier/client/cli" - "pocket/x/supplier/types" -) +// } +// nullify.Fill(&proof) +// state.ProofList = append(state.ProofList, proof) +// } +// buf, err := cfg.Codec.MarshalJSON(&state) +// require.NoError(t, err) +// cfg.GenesisState[types.ModuleName] = buf +// return network.New(t, cfg), state.ProofList +// } -// Prevent strconv unused error -var _ = strconv.IntSize +// func TestShowProof(t *testing.T) { +// net, objs := networkWithProofObjects(t, 2) + +// ctx := net.Validators[0].ClientCtx +// common := []string{ +// fmt.Sprintf("--%s=json", tmcli.OutputFlag), +// } +// tests := []struct { +// desc string +// idIndex string + +// args []string +// err error +// obj types.Proof +// }{ +// { +// desc: "found", +// idIndex: objs[0].Index, -func networkWithProofObjects(t *testing.T, n int) (*network.Network, []types.Proof) { - t.Helper() - cfg := network.DefaultConfig() - state := types.GenesisState{} - for i := 0; i < n; i++ { - proof := types.Proof{ - Index: strconv.Itoa(i), - - } - nullify.Fill(&proof) - state.ProofList = append(state.ProofList, proof) - } - buf, err := cfg.Codec.MarshalJSON(&state) - require.NoError(t, err) - cfg.GenesisState[types.ModuleName] = buf - return network.New(t, cfg), state.ProofList -} +// args: common, +// obj: objs[0], +// }, +// { +// desc: "not found", +// idIndex: strconv.Itoa(100000), -func TestShowProof(t *testing.T) { - net, objs := networkWithProofObjects(t, 2) +// args: common, +// err: status.Error(codes.NotFound, "not found"), +// }, +// } +// for _, tc := range tests { +// t.Run(tc.desc, func(t *testing.T) { +// args := []string{ +// tc.idIndex, - ctx := net.Validators[0].ClientCtx - common := []string{ - fmt.Sprintf("--%s=json", tmcli.OutputFlag), - } - tests := []struct { - desc string - idIndex string - - args []string - err error - obj types.Proof - }{ - { - desc: "found", - idIndex: objs[0].Index, - - args: common, - obj: objs[0], - }, - { - desc: "not found", - idIndex: strconv.Itoa(100000), - - args: common, - err: status.Error(codes.NotFound, "not found"), - }, - } - for _, tc := range tests { - t.Run(tc.desc, func(t *testing.T) { - args := []string{ - tc.idIndex, - - } - args = append(args, tc.args...) - out, err := clitestutil.ExecTestCLICmd(ctx, cli.CmdShowProof(), args) - if tc.err != nil { - stat, ok := status.FromError(tc.err) - require.True(t, ok) - require.ErrorIs(t, stat.Err(), tc.err) - } else { - require.NoError(t, err) - var resp types.QueryGetProofResponse - require.NoError(t, net.Config.Codec.UnmarshalJSON(out.Bytes(), &resp)) - require.NotNil(t, resp.Proof) - require.Equal(t, - nullify.Fill(&tc.obj), - nullify.Fill(&resp.Proof), - ) - } - }) - } -} +// } +// args = append(args, tc.args...) +// out, err := clitestutil.ExecTestCLICmd(ctx, cli.CmdShowProof(), args) +// if tc.err != nil { +// stat, ok := status.FromError(tc.err) +// require.True(t, ok) +// require.ErrorIs(t, stat.Err(), tc.err) +// } else { +// require.NoError(t, err) +// var resp types.QueryGetProofResponse +// require.NoError(t, net.Config.Codec.UnmarshalJSON(out.Bytes(), &resp)) +// require.NotNil(t, resp.Proof) +// require.Equal(t, +// nullify.Fill(&tc.obj), +// nullify.Fill(&resp.Proof), +// ) +// } +// }) +// } +// } -func TestListProof(t *testing.T) { - net, objs := networkWithProofObjects(t, 5) +// func TestListProof(t *testing.T) { +// net, objs := networkWithProofObjects(t, 5) - ctx := net.Validators[0].ClientCtx - request := func(next []byte, offset, limit uint64, total bool) []string { - args := []string{ - fmt.Sprintf("--%s=json", tmcli.OutputFlag), - } - if next == nil { - args = append(args, fmt.Sprintf("--%s=%d", flags.FlagOffset, offset)) - } else { - args = append(args, fmt.Sprintf("--%s=%s", flags.FlagPageKey, next)) - } - args = append(args, fmt.Sprintf("--%s=%d", flags.FlagLimit, limit)) - if total { - args = append(args, fmt.Sprintf("--%s", flags.FlagCountTotal)) - } - return args - } - t.Run("ByOffset", func(t *testing.T) { - step := 2 - for i := 0; i < len(objs); i += step { - args := request(nil, uint64(i), uint64(step), false) - out, err := clitestutil.ExecTestCLICmd(ctx, cli.CmdListProof(), args) - require.NoError(t, err) - var resp types.QueryAllProofResponse - require.NoError(t, net.Config.Codec.UnmarshalJSON(out.Bytes(), &resp)) - require.LessOrEqual(t, len(resp.Proof), step) - require.Subset(t, - nullify.Fill(objs), - nullify.Fill(resp.Proof), - ) - } - }) - t.Run("ByKey", func(t *testing.T) { - step := 2 - var next []byte - for i := 0; i < len(objs); i += step { - args := request(next, 0, uint64(step), false) - out, err := clitestutil.ExecTestCLICmd(ctx, cli.CmdListProof(), args) - require.NoError(t, err) - var resp types.QueryAllProofResponse - require.NoError(t, net.Config.Codec.UnmarshalJSON(out.Bytes(), &resp)) - require.LessOrEqual(t, len(resp.Proof), step) - require.Subset(t, - nullify.Fill(objs), - nullify.Fill(resp.Proof), - ) - next = resp.Pagination.NextKey - } - }) - t.Run("Total", func(t *testing.T) { - args := request(nil, 0, uint64(len(objs)), true) - out, err := clitestutil.ExecTestCLICmd(ctx, cli.CmdListProof(), args) - require.NoError(t, err) - var resp types.QueryAllProofResponse - require.NoError(t, net.Config.Codec.UnmarshalJSON(out.Bytes(), &resp)) - require.NoError(t, err) - require.Equal(t, len(objs), int(resp.Pagination.Total)) - require.ElementsMatch(t, - nullify.Fill(objs), - nullify.Fill(resp.Proof), - ) - }) -} +// ctx := net.Validators[0].ClientCtx +// request := func(next []byte, offset, limit uint64, total bool) []string { +// args := []string{ +// fmt.Sprintf("--%s=json", tmcli.OutputFlag), +// } +// if next == nil { +// args = append(args, fmt.Sprintf("--%s=%d", flags.FlagOffset, offset)) +// } else { +// args = append(args, fmt.Sprintf("--%s=%s", flags.FlagPageKey, next)) +// } +// args = append(args, fmt.Sprintf("--%s=%d", flags.FlagLimit, limit)) +// if total { +// args = append(args, fmt.Sprintf("--%s", flags.FlagCountTotal)) +// } +// return args +// } +// t.Run("ByOffset", func(t *testing.T) { +// step := 2 +// for i := 0; i < len(objs); i += step { +// args := request(nil, uint64(i), uint64(step), false) +// out, err := clitestutil.ExecTestCLICmd(ctx, cli.CmdListProof(), args) +// require.NoError(t, err) +// var resp types.QueryAllProofResponse +// require.NoError(t, net.Config.Codec.UnmarshalJSON(out.Bytes(), &resp)) +// require.LessOrEqual(t, len(resp.Proof), step) +// require.Subset(t, +// nullify.Fill(objs), +// nullify.Fill(resp.Proof), +// ) +// } +// }) +// t.Run("ByKey", func(t *testing.T) { +// step := 2 +// var next []byte +// for i := 0; i < len(objs); i += step { +// args := request(next, 0, uint64(step), false) +// out, err := clitestutil.ExecTestCLICmd(ctx, cli.CmdListProof(), args) +// require.NoError(t, err) +// var resp types.QueryAllProofResponse +// require.NoError(t, net.Config.Codec.UnmarshalJSON(out.Bytes(), &resp)) +// require.LessOrEqual(t, len(resp.Proof), step) +// require.Subset(t, +// nullify.Fill(objs), +// nullify.Fill(resp.Proof), +// ) +// next = resp.Pagination.NextKey +// } +// }) +// t.Run("Total", func(t *testing.T) { +// args := request(nil, 0, uint64(len(objs)), true) +// out, err := clitestutil.ExecTestCLICmd(ctx, cli.CmdListProof(), args) +// require.NoError(t, err) +// var resp types.QueryAllProofResponse +// require.NoError(t, net.Config.Codec.UnmarshalJSON(out.Bytes(), &resp)) +// require.NoError(t, err) +// require.Equal(t, len(objs), int(resp.Pagination.Total)) +// require.ElementsMatch(t, +// nullify.Fill(objs), +// nullify.Fill(resp.Proof), +// ) +// }) +// } diff --git a/x/supplier/genesis.go b/x/supplier/genesis.go index ceb285cb4..c9289b8f7 100644 --- a/x/supplier/genesis.go +++ b/x/supplier/genesis.go @@ -2,7 +2,6 @@ package supplier import ( sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/pokt-network/poktroll/x/supplier/keeper" "github.com/pokt-network/poktroll/x/supplier/types" ) @@ -18,11 +17,7 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, genState types.GenesisState) for _, elem := range genState.ClaimList { k.SetClaim(ctx, elem) } - // Set all the proof -for _, elem := range genState.ProofList { - k.SetProof(ctx, elem) -} -// this line is used by starport scaffolding # genesis/module/init + // this line is used by starport scaffolding # genesis/module/init k.SetParams(ctx, genState.Params) } @@ -33,8 +28,7 @@ func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { genesis.SupplierList = k.GetAllSupplier(ctx) genesis.ClaimList = k.GetAllClaims(ctx) - genesis.ProofList = k.GetAllProof(ctx) -// this line is used by starport scaffolding # genesis/module/export + // this line is used by starport scaffolding # genesis/module/export return genesis } diff --git a/x/supplier/genesis_test.go b/x/supplier/genesis_test.go index cde2322d1..c45bd1e07 100644 --- a/x/supplier/genesis_test.go +++ b/x/supplier/genesis_test.go @@ -4,14 +4,13 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/stretchr/testify/require" - keepertest "github.com/pokt-network/poktroll/testutil/keeper" "github.com/pokt-network/poktroll/testutil/nullify" "github.com/pokt-network/poktroll/testutil/sample" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" "github.com/pokt-network/poktroll/x/supplier" "github.com/pokt-network/poktroll/x/supplier/types" + "github.com/stretchr/testify/require" ) // Please see `x/supplier/types/genesis_test.go` for extensive tests related to the validity of the genesis state. @@ -64,15 +63,7 @@ func TestGenesis(t *testing.T) { Index: "1", }, }, - ProofList: []types.Proof{ - { - Index: "0", -}, - { - Index: "1", -}, - }, - // this line is used by starport scaffolding # genesis/test/state + // this line is used by starport scaffolding # genesis/test/state } k, ctx := keepertest.SupplierKeeper(t) @@ -85,6 +76,5 @@ func TestGenesis(t *testing.T) { require.ElementsMatch(t, genesisState.SupplierList, got.SupplierList) require.ElementsMatch(t, genesisState.ClaimList, got.ClaimList) - require.ElementsMatch(t, genesisState.ProofList, got.ProofList) -// this line is used by starport scaffolding # genesis/test/assert + // this line is used by starport scaffolding # genesis/test/assert } diff --git a/x/supplier/keeper/proof.go b/x/supplier/keeper/proof.go index a1ee384a5..e6074c6ea 100644 --- a/x/supplier/keeper/proof.go +++ b/x/supplier/keeper/proof.go @@ -1,34 +1,34 @@ package keeper import ( - sdk "github.com/cosmos/cosmos-sdk/types" - "pocket/x/supplier/types" "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/pokt-network/poktroll/x/supplier/types" ) // SetProof set a specific proof in the store from its index func (k Keeper) SetProof(ctx sdk.Context, proof types.Proof) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ProofKeyPrefix)) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ProofKeyPrefix)) b := k.cdc.MustMarshal(&proof) store.Set(types.ProofKey( - proof.Index, - ), b) + proof.Index, + ), b) } // GetProof returns a proof from its index func (k Keeper) GetProof( - ctx sdk.Context, - index string, - + ctx sdk.Context, + index string, + ) (val types.Proof, found bool) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ProofKeyPrefix)) b := store.Get(types.ProofKey( - index, - )) - if b == nil { - return val, false - } + index, + )) + if b == nil { + return val, false + } k.cdc.MustUnmarshal(b, &val) return val, true @@ -36,19 +36,19 @@ func (k Keeper) GetProof( // RemoveProof removes a proof from the store func (k Keeper) RemoveProof( - ctx sdk.Context, - index string, - + ctx sdk.Context, + index string, + ) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ProofKeyPrefix)) store.Delete(types.ProofKey( - index, - )) + index, + )) } // GetAllProof returns all proof func (k Keeper) GetAllProof(ctx sdk.Context) (list []types.Proof) { - store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ProofKeyPrefix)) + store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ProofKeyPrefix)) iterator := sdk.KVStorePrefixIterator(store, []byte{}) defer iterator.Close() @@ -56,8 +56,8 @@ func (k Keeper) GetAllProof(ctx sdk.Context) (list []types.Proof) { for ; iterator.Valid(); iterator.Next() { var val types.Proof k.cdc.MustUnmarshal(iterator.Value(), &val) - list = append(list, val) + list = append(list, val) } - return + return } diff --git a/x/supplier/keeper/proof_test.go b/x/supplier/keeper/proof_test.go index 27ee00272..6c9208792 100644 --- a/x/supplier/keeper/proof_test.go +++ b/x/supplier/keeper/proof_test.go @@ -4,11 +4,12 @@ import ( "strconv" "testing" - "pocket/x/supplier/keeper" - "pocket/x/supplier/types" keepertest "pocket/testutil/keeper" "pocket/testutil/nullify" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/pokt-network/poktroll/x/supplier/keeper" + "github.com/pokt-network/poktroll/x/supplier/types" "github.com/stretchr/testify/require" ) @@ -19,7 +20,7 @@ func createNProof(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.Proof { items := make([]types.Proof, n) for i := range items { items[i].Index = strconv.Itoa(i) - + keeper.SetProof(ctx, items[i]) } return items @@ -30,8 +31,7 @@ func TestProofGet(t *testing.T) { items := createNProof(keeper, ctx, 10) for _, item := range items { rst, found := keeper.GetProof(ctx, - item.Index, - + item.Index, ) require.True(t, found) require.Equal(t, @@ -45,12 +45,10 @@ func TestProofRemove(t *testing.T) { items := createNProof(keeper, ctx, 10) for _, item := range items { keeper.RemoveProof(ctx, - item.Index, - + item.Index, ) _, found := keeper.GetProof(ctx, - item.Index, - + item.Index, ) require.False(t, found) } diff --git a/x/supplier/keeper/query_proof.go b/x/supplier/keeper/query_proof.go index a029b9953..6a754c8d7 100644 --- a/x/supplier/keeper/query_proof.go +++ b/x/supplier/keeper/query_proof.go @@ -6,7 +6,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" - "pocket/x/supplier/types" + "github.com/pokt-network/poktroll/x/supplier/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -46,12 +46,12 @@ func (k Keeper) Proof(goCtx context.Context, req *types.QueryGetProofRequest) (* ctx := sdk.UnwrapSDKContext(goCtx) val, found := k.GetProof( - ctx, - req.Index, - ) + ctx, + req.Index, + ) if !found { - return nil, status.Error(codes.NotFound, "not found") + return nil, status.Error(codes.NotFound, "not found") } return &types.QueryGetProofResponse{Proof: val}, nil -} \ No newline at end of file +} diff --git a/x/supplier/keeper/query_proof_test.go b/x/supplier/keeper/query_proof_test.go index ae29f46cf..84b31416b 100644 --- a/x/supplier/keeper/query_proof_test.go +++ b/x/supplier/keeper/query_proof_test.go @@ -1,7 +1,7 @@ package keeper_test import ( - "strconv" + "strconv" "testing" sdk "github.com/cosmos/cosmos-sdk/types" @@ -10,9 +10,10 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "pocket/x/supplier/types" - "pocket/testutil/nullify" keepertest "pocket/testutil/keeper" + "pocket/testutil/nullify" + + "github.com/pokt-network/poktroll/x/supplier/types" ) // Prevent strconv unused error @@ -29,28 +30,25 @@ func TestProofQuerySingle(t *testing.T) { err error }{ { - desc: "First", - request: &types.QueryGetProofRequest{ - Index: msgs[0].Index, - + desc: "First", + request: &types.QueryGetProofRequest{ + Index: msgs[0].Index, }, response: &types.QueryGetProofResponse{Proof: msgs[0]}, }, { - desc: "Second", - request: &types.QueryGetProofRequest{ - Index: msgs[1].Index, - + desc: "Second", + request: &types.QueryGetProofRequest{ + Index: msgs[1].Index, }, response: &types.QueryGetProofResponse{Proof: msgs[1]}, }, { - desc: "KeyNotFound", + desc: "KeyNotFound", request: &types.QueryGetProofRequest{ - Index:strconv.Itoa(100000), - + Index: strconv.Itoa(100000), }, - err: status.Error(codes.NotFound, "not found"), + err: status.Error(codes.NotFound, "not found"), }, { desc: "InvalidRequest", @@ -95,9 +93,9 @@ func TestProofQueryPaginated(t *testing.T) { require.NoError(t, err) require.LessOrEqual(t, len(resp.Proof), step) require.Subset(t, - nullify.Fill(msgs), - nullify.Fill(resp.Proof), - ) + nullify.Fill(msgs), + nullify.Fill(resp.Proof), + ) } }) t.Run("ByKey", func(t *testing.T) { @@ -108,9 +106,9 @@ func TestProofQueryPaginated(t *testing.T) { require.NoError(t, err) require.LessOrEqual(t, len(resp.Proof), step) require.Subset(t, - nullify.Fill(msgs), - nullify.Fill(resp.Proof), - ) + nullify.Fill(msgs), + nullify.Fill(resp.Proof), + ) next = resp.Pagination.NextKey } }) diff --git a/x/supplier/types/genesis.go b/x/supplier/types/genesis.go index 3e685dc14..44a71f01e 100644 --- a/x/supplier/types/genesis.go +++ b/x/supplier/types/genesis.go @@ -5,7 +5,6 @@ import ( sdkerrors "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" - servicehelpers "github.com/pokt-network/poktroll/x/shared/helpers" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" ) @@ -18,8 +17,7 @@ func DefaultGenesis() *GenesisState { return &GenesisState{ SupplierList: []sharedtypes.Supplier{}, ClaimList: []Claim{}, - ProofList: []Proof{}, -// this line is used by starport scaffolding # genesis/types/default + // this line is used by starport scaffolding # genesis/types/default Params: DefaultParams(), } } @@ -74,17 +72,8 @@ func (gs GenesisState) Validate() error { } claimIndexMap[index] = struct{}{} } - // Check for duplicated index in proof -proofIndexMap := make(map[string]struct{}) -for _, elem := range gs.ProofList { - index := string(ProofKey(elem.Index)) - if _, ok := proofIndexMap[index]; ok { - return fmt.Errorf("duplicated index for proof") - } - proofIndexMap[index] = struct{}{} -} -// this line is used by starport scaffolding # genesis/types/validate + // this line is used by starport scaffolding # genesis/types/validate return gs.Params.Validate() } diff --git a/x/supplier/types/genesis_test.go b/x/supplier/types/genesis_test.go index c851c4ec9..abfebdde7 100644 --- a/x/supplier/types/genesis_test.go +++ b/x/supplier/types/genesis_test.go @@ -4,11 +4,10 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/stretchr/testify/require" - "github.com/pokt-network/poktroll/testutil/sample" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" "github.com/pokt-network/poktroll/x/supplier/types" + "github.com/stretchr/testify/require" ) func TestGenesisState_Validate(t *testing.T) { @@ -78,15 +77,7 @@ func TestGenesisState_Validate(t *testing.T) { Index: "1", }, }, - ProofList: []types.Proof{ - { - Index: "0", -}, - { - Index: "1", -}, -}, -// this line is used by starport scaffolding # types/genesis/validField + // this line is used by starport scaffolding # types/genesis/validField }, valid: true, }, @@ -329,20 +320,11 @@ func TestGenesisState_Validate(t *testing.T) { valid: false, }, { - desc: "duplicated proof", - genState: &types.GenesisState{ - ProofList: []types.Proof{ - { - Index: "0", -}, - { - Index: "0", -}, + desc: "duplicated proof", + genState: &types.GenesisState{}, + valid: false, }, - }, - valid: false, -}, -// this line is used by starport scaffolding # types/genesis/testcase + // this line is used by starport scaffolding # types/genesis/testcase } for _, tc := range tests { t.Run(tc.desc, func(t *testing.T) { diff --git a/x/supplier/types/message_create_claim.go b/x/supplier/types/message_create_claim.go index 0e702c956..902c5a978 100644 --- a/x/supplier/types/message_create_claim.go +++ b/x/supplier/types/message_create_claim.go @@ -3,7 +3,6 @@ package types import ( sdkerrors "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" - sessiontypes "github.com/pokt-network/poktroll/x/session/types" sharedhelpers "github.com/pokt-network/poktroll/x/shared/helpers" ) From 9a9ca7af85871ba7c8c1a93af455143a2fe10937 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Thu, 16 Nov 2023 18:18:24 -0800 Subject: [PATCH 04/16] Fix grammer for AllProof querying --- docs/static/openapi.yml | 10 +++++--- proto/pocket/supplier/query.proto | 31 ++++++++++++----------- testutil/keeper/session.go | 3 +-- x/pocket/types/codec.go | 3 ++- x/service/types/codec.go | 3 ++- x/session/types/codec.go | 3 ++- x/supplier/client/cli/query_proof.go | 11 ++++---- x/supplier/client/cli/query_proof_test.go | 6 ++--- x/supplier/keeper/msg_server_test.go | 6 ++--- x/supplier/keeper/proof_test.go | 5 ++-- x/supplier/keeper/query_proof.go | 4 +-- x/supplier/keeper/query_proof_test.go | 20 +++++++-------- x/supplier/types/codec.go | 3 +-- x/supplier/types/genesis_test.go | 5 ---- x/supplier/types/key_proof.go | 16 ++++++------ 15 files changed, 63 insertions(+), 66 deletions(-) diff --git a/docs/static/openapi.yml b/docs/static/openapi.yml index 7762ac8a9..1bd28d3e4 100644 --- a/docs/static/openapi.yml +++ b/docs/static/openapi.yml @@ -47648,7 +47648,7 @@ paths: - Query /pocket/supplier/proof: get: - operationId: PocketSupplierProofAll + operationId: PocketSupplierAllProofs responses: '200': description: A successful response. @@ -47780,7 +47780,11 @@ paths: - Query /pocket/supplier/proof/{index}: get: - summary: Queries a list of Proof items. + summary: >- + TODO_UPNEXT(@Olshansk): Update these endpoints after implementing proof + persistence + + Queries a list of Proof items. operationId: PocketSupplierProof responses: '200': @@ -78289,7 +78293,7 @@ definitions: repeated Bar results = 1; PageResponse page = 2; } - pocket.supplier.QueryAllProofResponse: + pocket.supplier.QueryAllProofsResponse: type: object properties: proof: diff --git a/proto/pocket/supplier/query.proto b/proto/pocket/supplier/query.proto index 1cc1d3a37..6e663607c 100644 --- a/proto/pocket/supplier/query.proto +++ b/proto/pocket/supplier/query.proto @@ -14,41 +14,42 @@ option go_package = "github.com/pokt-network/poktroll/x/supplier/types"; // Query defines the gRPC querier service. service Query { - + // Parameters queries the parameters of the module. rpc Params (QueryParamsRequest) returns (QueryParamsResponse) { option (google.api.http).get = "/pocket/supplier/params"; - + } - + // Queries a list of Supplier items. rpc Supplier (QueryGetSupplierRequest) returns (QueryGetSupplierResponse) { option (google.api.http).get = "/pocket/supplier/supplier/{address}"; - + } rpc SupplierAll (QueryAllSupplierRequest) returns (QueryAllSupplierResponse) { option (google.api.http).get = "/pocket/supplier/supplier"; - + } - + // Queries a list of Claim items. rpc Claim (QueryGetClaimRequest ) returns (QueryGetClaimResponse ) { option (google.api.http).get = "/pocket/supplier/claim/{index}"; - + } rpc AllClaims (QueryAllClaimsRequest) returns (QueryAllClaimsResponse) { option (google.api.http).get = "/pocket/supplier/claim"; - + } - + + // TODO_UPNEXT(@Olshansk): Update these endpoints after implementing proof persistence // Queries a list of Proof items. rpc Proof (QueryGetProofRequest) returns (QueryGetProofResponse) { option (google.api.http).get = "/pocket/supplier/proof/{index}"; - + } - rpc ProofAll (QueryAllProofRequest) returns (QueryAllProofResponse) { + rpc AllProofs (QueryAllProofsRequest) returns (QueryAllProofsResponse) { option (google.api.http).get = "/pocket/supplier/proof"; - + } } // QueryParamsRequest is request type for the Query/Params RPC method. @@ -56,7 +57,7 @@ message QueryParamsRequest {} // QueryParamsResponse is response type for the Query/Params RPC method. message QueryParamsResponse { - + // params holds all the parameters of this module. Params params = 1 [(gogoproto.nullable) = false]; } @@ -103,11 +104,11 @@ message QueryGetProofResponse { Proof proof = 1 [(gogoproto.nullable) = false]; } -message QueryAllProofRequest { +message QueryAllProofsRequest { cosmos.base.query.v1beta1.PageRequest pagination = 1; } -message QueryAllProofResponse { +message QueryAllProofsResponse { repeated Proof proof = 1 [(gogoproto.nullable) = false]; cosmos.base.query.v1beta1.PageResponse pagination = 2; } diff --git a/testutil/keeper/session.go b/testutil/keeper/session.go index 8b57ec0c4..2e70e666e 100644 --- a/testutil/keeper/session.go +++ b/testutil/keeper/session.go @@ -14,14 +14,13 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" typesparams "github.com/cosmos/cosmos-sdk/x/params/types" "github.com/golang/mock/gomock" - "github.com/stretchr/testify/require" - "github.com/pokt-network/poktroll/testutil/sample" "github.com/pokt-network/poktroll/testutil/session/mocks" apptypes "github.com/pokt-network/poktroll/x/application/types" "github.com/pokt-network/poktroll/x/session/keeper" "github.com/pokt-network/poktroll/x/session/types" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" + "github.com/stretchr/testify/require" ) type option[V any] func(k *keeper.Keeper) diff --git a/x/pocket/types/codec.go b/x/pocket/types/codec.go index 72399f81e..39e7482ab 100644 --- a/x/pocket/types/codec.go +++ b/x/pocket/types/codec.go @@ -1,10 +1,11 @@ package types import ( + // this line is used by starport scaffolding # 1 + "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/types/msgservice" - // this line is used by starport scaffolding # 1 ) func RegisterCodec(cdc *codec.LegacyAmino) { diff --git a/x/service/types/codec.go b/x/service/types/codec.go index 72399f81e..39e7482ab 100644 --- a/x/service/types/codec.go +++ b/x/service/types/codec.go @@ -1,10 +1,11 @@ package types import ( + // this line is used by starport scaffolding # 1 + "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/types/msgservice" - // this line is used by starport scaffolding # 1 ) func RegisterCodec(cdc *codec.LegacyAmino) { diff --git a/x/session/types/codec.go b/x/session/types/codec.go index 72399f81e..39e7482ab 100644 --- a/x/session/types/codec.go +++ b/x/session/types/codec.go @@ -1,10 +1,11 @@ package types import ( + // this line is used by starport scaffolding # 1 + "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/types/msgservice" - // this line is used by starport scaffolding # 1 ) func RegisterCodec(cdc *codec.LegacyAmino) { diff --git a/x/supplier/client/cli/query_proof.go b/x/supplier/client/cli/query_proof.go index 2c7dfea7a..bc4d34092 100644 --- a/x/supplier/client/cli/query_proof.go +++ b/x/supplier/client/cli/query_proof.go @@ -1,17 +1,16 @@ package cli import ( - "github.com/pokt-network/poktroll/x/supplier/types" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/pokt-network/poktroll/x/supplier/types" "github.com/spf13/cobra" ) func CmdListProof() *cobra.Command { cmd := &cobra.Command{ - Use: "list-proof", - Short: "list all proof", + Use: "list-proofs", + Short: "list all proofs", RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientQueryContext(cmd) if err != nil { @@ -25,11 +24,11 @@ func CmdListProof() *cobra.Command { queryClient := types.NewQueryClient(clientCtx) - params := &types.QueryAllProofRequest{ + params := &types.QueryAllProofsRequest{ Pagination: pageReq, } - res, err := queryClient.ProofAll(cmd.Context(), params) + res, err := queryClient.AllProofs(cmd.Context(), params) if err != nil { return err } diff --git a/x/supplier/client/cli/query_proof_test.go b/x/supplier/client/cli/query_proof_test.go index b87f4e24f..1301b236f 100644 --- a/x/supplier/client/cli/query_proof_test.go +++ b/x/supplier/client/cli/query_proof_test.go @@ -103,7 +103,7 @@ package cli_test // args := request(nil, uint64(i), uint64(step), false) // out, err := clitestutil.ExecTestCLICmd(ctx, cli.CmdListProof(), args) // require.NoError(t, err) -// var resp types.QueryAllProofResponse +// var resp types.QueryAllProofsResponse // require.NoError(t, net.Config.Codec.UnmarshalJSON(out.Bytes(), &resp)) // require.LessOrEqual(t, len(resp.Proof), step) // require.Subset(t, @@ -119,7 +119,7 @@ package cli_test // args := request(next, 0, uint64(step), false) // out, err := clitestutil.ExecTestCLICmd(ctx, cli.CmdListProof(), args) // require.NoError(t, err) -// var resp types.QueryAllProofResponse +// var resp types.QueryAllProofsResponse // require.NoError(t, net.Config.Codec.UnmarshalJSON(out.Bytes(), &resp)) // require.LessOrEqual(t, len(resp.Proof), step) // require.Subset(t, @@ -133,7 +133,7 @@ package cli_test // args := request(nil, 0, uint64(len(objs)), true) // out, err := clitestutil.ExecTestCLICmd(ctx, cli.CmdListProof(), args) // require.NoError(t, err) -// var resp types.QueryAllProofResponse +// var resp types.QueryAllProofsResponse // require.NoError(t, net.Config.Codec.UnmarshalJSON(out.Bytes(), &resp)) // require.NoError(t, err) // require.Equal(t, len(objs), int(resp.Pagination.Total)) diff --git a/x/supplier/keeper/msg_server_test.go b/x/supplier/keeper/msg_server_test.go index 39fc0075f..3a5927aec 100644 --- a/x/supplier/keeper/msg_server_test.go +++ b/x/supplier/keeper/msg_server_test.go @@ -5,10 +5,10 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" + keepertest "github.com/pokt-network/poktroll/testutil/keeper" + "github.com/pokt-network/poktroll/x/supplier/keeper" + "github.com/pokt-network/poktroll/x/supplier/types" "github.com/stretchr/testify/require" - "github.com/pokt-network/poktroll/x/supplier/types" - "github.com/pokt-network/poktroll/x/supplier/keeper" - keepertest "github.com/pokt-network/poktroll/testutil/keeper" ) func setupMsgServer(t testing.TB) (types.MsgServer, context.Context) { diff --git a/x/supplier/keeper/proof_test.go b/x/supplier/keeper/proof_test.go index 6c9208792..6f8c60a56 100644 --- a/x/supplier/keeper/proof_test.go +++ b/x/supplier/keeper/proof_test.go @@ -4,10 +4,9 @@ import ( "strconv" "testing" - keepertest "pocket/testutil/keeper" - "pocket/testutil/nullify" - sdk "github.com/cosmos/cosmos-sdk/types" + keepertest "github.com/pokt-network/poktroll/testutil/keeper" + "github.com/pokt-network/poktroll/testutil/nullify" "github.com/pokt-network/poktroll/x/supplier/keeper" "github.com/pokt-network/poktroll/x/supplier/types" "github.com/stretchr/testify/require" diff --git a/x/supplier/keeper/query_proof.go b/x/supplier/keeper/query_proof.go index 6a754c8d7..594eff71c 100644 --- a/x/supplier/keeper/query_proof.go +++ b/x/supplier/keeper/query_proof.go @@ -11,7 +11,7 @@ import ( "google.golang.org/grpc/status" ) -func (k Keeper) ProofAll(goCtx context.Context, req *types.QueryAllProofRequest) (*types.QueryAllProofResponse, error) { +func (k Keeper) AllProofs(goCtx context.Context, req *types.QueryAllProofsRequest) (*types.QueryAllProofsResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "invalid request") } @@ -36,7 +36,7 @@ func (k Keeper) ProofAll(goCtx context.Context, req *types.QueryAllProofRequest) return nil, status.Error(codes.Internal, err.Error()) } - return &types.QueryAllProofResponse{Proof: proofs, Pagination: pageRes}, nil + return &types.QueryAllProofsResponse{Proof: proofs, Pagination: pageRes}, nil } func (k Keeper) Proof(goCtx context.Context, req *types.QueryGetProofRequest) (*types.QueryGetProofResponse, error) { diff --git a/x/supplier/keeper/query_proof_test.go b/x/supplier/keeper/query_proof_test.go index 84b31416b..386565e78 100644 --- a/x/supplier/keeper/query_proof_test.go +++ b/x/supplier/keeper/query_proof_test.go @@ -1,19 +1,17 @@ package keeper_test import ( + keepertest "pocket/testutil/keeper" + "pocket/testutil/nullify" "strconv" "testing" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" + "github.com/pokt-network/poktroll/x/supplier/types" "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - - keepertest "pocket/testutil/keeper" - "pocket/testutil/nullify" - - "github.com/pokt-network/poktroll/x/supplier/types" ) // Prevent strconv unused error @@ -76,8 +74,8 @@ func TestProofQueryPaginated(t *testing.T) { wctx := sdk.WrapSDKContext(ctx) msgs := createNProof(keeper, ctx, 5) - request := func(next []byte, offset, limit uint64, total bool) *types.QueryAllProofRequest { - return &types.QueryAllProofRequest{ + request := func(next []byte, offset, limit uint64, total bool) *types.QueryAllProofsRequest { + return &types.QueryAllProofsRequest{ Pagination: &query.PageRequest{ Key: next, Offset: offset, @@ -89,7 +87,7 @@ func TestProofQueryPaginated(t *testing.T) { t.Run("ByOffset", func(t *testing.T) { step := 2 for i := 0; i < len(msgs); i += step { - resp, err := keeper.ProofAll(wctx, request(nil, uint64(i), uint64(step), false)) + resp, err := keeper.AllProofs(wctx, request(nil, uint64(i), uint64(step), false)) require.NoError(t, err) require.LessOrEqual(t, len(resp.Proof), step) require.Subset(t, @@ -102,7 +100,7 @@ func TestProofQueryPaginated(t *testing.T) { step := 2 var next []byte for i := 0; i < len(msgs); i += step { - resp, err := keeper.ProofAll(wctx, request(next, 0, uint64(step), false)) + resp, err := keeper.AllProofs(wctx, request(next, 0, uint64(step), false)) require.NoError(t, err) require.LessOrEqual(t, len(resp.Proof), step) require.Subset(t, @@ -113,7 +111,7 @@ func TestProofQueryPaginated(t *testing.T) { } }) t.Run("Total", func(t *testing.T) { - resp, err := keeper.ProofAll(wctx, request(nil, 0, 0, true)) + resp, err := keeper.AllProofs(wctx, request(nil, 0, 0, true)) require.NoError(t, err) require.Equal(t, len(msgs), int(resp.Pagination.Total)) require.ElementsMatch(t, @@ -122,7 +120,7 @@ func TestProofQueryPaginated(t *testing.T) { ) }) t.Run("InvalidRequest", func(t *testing.T) { - _, err := keeper.ProofAll(wctx, nil) + _, err := keeper.AllProofs(wctx, nil) require.ErrorIs(t, err, status.Error(codes.InvalidArgument, "invalid request")) }) } diff --git a/x/supplier/types/codec.go b/x/supplier/types/codec.go index 02d5e43a5..41d74aa3f 100644 --- a/x/supplier/types/codec.go +++ b/x/supplier/types/codec.go @@ -1,7 +1,6 @@ package types import ( -"github.com/cosmos/cosmos-sdk/types/msgservice" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -29,7 +28,7 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { ) // this line is used by starport scaffolding # 3 -msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) diff --git a/x/supplier/types/genesis_test.go b/x/supplier/types/genesis_test.go index abfebdde7..dd8f536fb 100644 --- a/x/supplier/types/genesis_test.go +++ b/x/supplier/types/genesis_test.go @@ -319,11 +319,6 @@ func TestGenesisState_Validate(t *testing.T) { }, valid: false, }, - { - desc: "duplicated proof", - genState: &types.GenesisState{}, - valid: false, - }, // this line is used by starport scaffolding # types/genesis/testcase } for _, tc := range tests { diff --git a/x/supplier/types/key_proof.go b/x/supplier/types/key_proof.go index 5a2f19a4c..d3d6d791e 100644 --- a/x/supplier/types/key_proof.go +++ b/x/supplier/types/key_proof.go @@ -5,19 +5,19 @@ import "encoding/binary" var _ binary.ByteOrder const ( - // ProofKeyPrefix is the prefix to retrieve all Proof + // ProofKeyPrefix is the prefix to retrieve all Proof ProofKeyPrefix = "Proof/value/" ) // ProofKey returns the store key to retrieve a Proof from the index fields func ProofKey( -index string, + index string, ) []byte { var key []byte - - indexBytes := []byte(index) - key = append(key, indexBytes...) - key = append(key, []byte("/")...) - + + indexBytes := []byte(index) + key = append(key, indexBytes...) + key = append(key, []byte("/")...) + return key -} \ No newline at end of file +} From 190fd3c13c90b09b3bb3501076220f3ecd421a42 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Fri, 17 Nov 2023 12:00:15 -0800 Subject: [PATCH 05/16] Update openapi.yml file --- docs/static/openapi.yml | 285 +++++++++++++++++++++------------------- 1 file changed, 147 insertions(+), 138 deletions(-) diff --git a/docs/static/openapi.yml b/docs/static/openapi.yml index 74242fea1..69b0fd829 100644 --- a/docs/static/openapi.yml +++ b/docs/static/openapi.yml @@ -47671,23 +47671,15 @@ paths: additionalProperties: {} tags: - Query -<<<<<<< HEAD /pocket/supplier/proof: get: operationId: PocketSupplierAllProofs -======= - /pocket/supplier/supplier/{address}: - get: - summary: Queries a list of Supplier items. - operationId: PocketSupplierSupplier ->>>>>>> main responses: '200': description: A successful response. schema: type: object properties: -<<<<<<< HEAD proof: type: array items: @@ -47734,7 +47726,148 @@ paths: repeated Bar results = 1; PageResponse page = 2; } -======= + 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: pagination.key + description: |- + key is a value returned in PageResponse.next_key to begin + querying the next page most efficiently. Only one of offset or key + should be set. + in: query + required: false + type: string + format: byte + - name: pagination.offset + description: >- + offset is a numeric offset that can be used when key is unavailable. + + It is less efficient than using key. Only one of offset or key + should + + be set. + in: query + required: false + type: string + format: uint64 + - name: pagination.limit + description: >- + limit is the total number of results to be returned in the result + page. + + If left empty it will default to a value to be set by each app. + in: query + required: false + type: string + format: uint64 + - name: pagination.count_total + description: >- + count_total is set to true to indicate that the result set should + include + + a count of the total number of items available for pagination in + UIs. + + count_total is only respected when offset is used. It is ignored + when key + + is set. + in: query + required: false + type: boolean + - name: pagination.reverse + description: >- + reverse is set to true if results are to be returned in the + descending order. + + + Since: cosmos-sdk 0.43 + in: query + required: false + type: boolean + tags: + - Query + /pocket/supplier/proof/{index}: + get: + summary: >- + TODO_UPNEXT(@Olshansk): Update these endpoints after implementing proof + persistence + + Queries a list of Proof items. + operationId: PocketSupplierProof + responses: + '200': + description: A successful response. + schema: + type: object + properties: + proof: + type: object + properties: + index: + type: string + supplier_address: + type: string + session_id: + type: string + merkle_proof: + type: string + description: >- + TODO_UPNEXT(@Olshansk): The structure below is the default + (untouched) scaffolded type. Update + + and productionize it for our use case. + 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: index + in: path + required: true + type: string + 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: @@ -47848,115 +47981,6 @@ paths: description: >- Supplier is the type defining the actor in Pocket Network that provides RPC services. ->>>>>>> main - 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: -<<<<<<< HEAD - - name: pagination.key - description: |- - key is a value returned in PageResponse.next_key to begin - querying the next page most efficiently. Only one of offset or key - should be set. - in: query - required: false - type: string - format: byte - - name: pagination.offset - description: >- - offset is a numeric offset that can be used when key is unavailable. - - It is less efficient than using key. Only one of offset or key - should - - be set. - in: query - required: false - type: string - format: uint64 - - name: pagination.limit - description: >- - limit is the total number of results to be returned in the result - page. - - If left empty it will default to a value to be set by each app. - in: query - required: false - type: string - format: uint64 - - name: pagination.count_total - description: >- - count_total is set to true to indicate that the result set should - include - - a count of the total number of items available for pagination in - UIs. - - count_total is only respected when offset is used. It is ignored - when key - - is set. - in: query - required: false - type: boolean - - name: pagination.reverse - description: >- - reverse is set to true if results are to be returned in the - descending order. - - - Since: cosmos-sdk 0.43 - in: query - required: false - type: boolean - tags: - - Query - /pocket/supplier/proof/{index}: - get: - summary: >- - TODO_UPNEXT(@Olshansk): Update these endpoints after implementing proof - persistence - - Queries a list of Proof items. - operationId: PocketSupplierProof - responses: - '200': - description: A successful response. - schema: - type: object - properties: - proof: - type: object - properties: - index: - type: string - supplier_address: - type: string - session_id: - type: string - merkle_proof: - type: string - description: >- - TODO_UPNEXT(@Olshansk): The structure below is the default - (untouched) scaffolded type. Update - - and productionize it for our use case. default: description: An unexpected error response. schema: @@ -47976,20 +48000,13 @@ paths: type: string additionalProperties: {} parameters: - - name: index -======= - name: address ->>>>>>> main in: path required: true type: string tags: - Query -<<<<<<< HEAD - /pocket/supplier/supplier: -======= /pocket/supplier/suppliers: ->>>>>>> main get: operationId: PocketSupplierSupplierAll responses: @@ -78516,12 +78533,11 @@ definitions: title: session end block height from the SessionHeader root_hash: type: string -<<<<<<< HEAD - description: >- - TODO_UPNEXT(@Olshansk): The structure below is the default (untouched) - scaffolded type. Update - - and productionize it for our use case. + format: byte + title: smt.SMST#Root() + title: >- + Claim is the serialized object stored on-chain for claims pending to + be proven pocket.supplier.QueryGetProofResponse: type: object properties: @@ -78541,13 +78557,6 @@ definitions: scaffolded type. Update and productionize it for our use case. -======= - format: byte - title: smt.SMST#Root() - title: >- - Claim is the serialized object stored on-chain for claims pending to - be proven ->>>>>>> main pocket.supplier.QueryGetSupplierResponse: type: object properties: From fef0851a18806c20f8b6757f7d405931e1e572c7 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Fri, 17 Nov 2023 12:21:59 -0800 Subject: [PATCH 06/16] Update formatting --- proto/pocket/supplier/query.proto | 3 +-- x/supplier/client/cli/query.go | 9 ++------- x/supplier/keeper/query_proof_test.go | 4 ++-- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/proto/pocket/supplier/query.proto b/proto/pocket/supplier/query.proto index 37146df39..b0d698d58 100644 --- a/proto/pocket/supplier/query.proto +++ b/proto/pocket/supplier/query.proto @@ -18,11 +18,10 @@ service Query { // Parameters queries the parameters of the module. rpc Params (QueryParamsRequest) returns (QueryParamsResponse) { option (google.api.http).get = "/pocket/supplier/params"; - } // Queries a list of Supplier items. - rpc Supplier (QueryGetSupplierRequest) returns (QueryGetSupplierResponse) { + rpc Supplier (QueryGetSupplierRequest) returns (QueryGetSupplierResponse) { option (google.api.http).get = "/pocket/supplier/supplier/{address}"; } diff --git a/x/supplier/client/cli/query.go b/x/supplier/client/cli/query.go index 753496b1e..81c41dfd3 100644 --- a/x/supplier/client/cli/query.go +++ b/x/supplier/client/cli/query.go @@ -2,15 +2,10 @@ package cli import ( "fmt" - // "strings" - - "github.com/spf13/cobra" "github.com/cosmos/cosmos-sdk/client" - // "github.com/cosmos/cosmos-sdk/client/flags" - // sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/pokt-network/poktroll/x/supplier/types" + "github.com/spf13/cobra" ) // GetQueryCmd returns the cli query commands for this module @@ -31,7 +26,7 @@ func GetQueryCmd(queryRoute string) *cobra.Command { cmd.AddCommand(CmdShowClaim()) cmd.AddCommand(CmdListProof()) cmd.AddCommand(CmdShowProof()) -// this line is used by starport scaffolding # 1 + // this line is used by starport scaffolding # 1 return cmd } diff --git a/x/supplier/keeper/query_proof_test.go b/x/supplier/keeper/query_proof_test.go index 386565e78..e1084becf 100644 --- a/x/supplier/keeper/query_proof_test.go +++ b/x/supplier/keeper/query_proof_test.go @@ -1,13 +1,13 @@ package keeper_test import ( - keepertest "pocket/testutil/keeper" - "pocket/testutil/nullify" "strconv" "testing" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" + keepertest "github.com/pokt-network/poktroll/testutil/keeper" + "github.com/pokt-network/poktroll/testutil/nullify" "github.com/pokt-network/poktroll/x/supplier/types" "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" From e3340f760b6123ab0e0b19b5206d4aef439996e6 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Mon, 20 Nov 2023 12:16:06 -0800 Subject: [PATCH 07/16] Ran make go_imports --- app/app.go | 1 + go.mod | 4 ++-- pkg/relayer/proxy/rings.go | 1 + testutil/keeper/session.go | 3 ++- x/supplier/client/cli/query.go | 3 ++- x/supplier/client/cli/query_proof.go | 3 ++- x/supplier/genesis.go | 1 + x/supplier/keeper/proof.go | 1 + x/supplier/keeper/query_proof.go | 3 ++- x/supplier/types/genesis.go | 1 + x/supplier/types/message_create_claim.go | 1 + 11 files changed, 16 insertions(+), 6 deletions(-) diff --git a/app/app.go b/app/app.go index eda44776f..b34d4db68 100644 --- a/app/app.go +++ b/app/app.go @@ -6,6 +6,7 @@ import ( "io" "os" "path/filepath" + // this line is used by starport scaffolding # stargate/app/moduleImport autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" diff --git a/go.mod b/go.mod index 35cb81d15..006bbc4ec 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,6 @@ require ( github.com/athanorlabs/go-dleq v0.1.0 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 @@ -45,7 +44,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 ) @@ -89,6 +87,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 @@ -284,6 +283,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/pkg/relayer/proxy/rings.go b/pkg/relayer/proxy/rings.go index 86651247d..82a3cae31 100644 --- a/pkg/relayer/proxy/rings.go +++ b/pkg/relayer/proxy/rings.go @@ -15,6 +15,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" accounttypes "github.com/cosmos/cosmos-sdk/x/auth/types" ring "github.com/noot/ring-go" + apptypes "github.com/pokt-network/poktroll/x/application/types" ) diff --git a/testutil/keeper/session.go b/testutil/keeper/session.go index 2e70e666e..8b57ec0c4 100644 --- a/testutil/keeper/session.go +++ b/testutil/keeper/session.go @@ -14,13 +14,14 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" typesparams "github.com/cosmos/cosmos-sdk/x/params/types" "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" + "github.com/pokt-network/poktroll/testutil/sample" "github.com/pokt-network/poktroll/testutil/session/mocks" apptypes "github.com/pokt-network/poktroll/x/application/types" "github.com/pokt-network/poktroll/x/session/keeper" "github.com/pokt-network/poktroll/x/session/types" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" - "github.com/stretchr/testify/require" ) type option[V any] func(k *keeper.Keeper) diff --git a/x/supplier/client/cli/query.go b/x/supplier/client/cli/query.go index 81c41dfd3..e87eda8ed 100644 --- a/x/supplier/client/cli/query.go +++ b/x/supplier/client/cli/query.go @@ -4,8 +4,9 @@ import ( "fmt" "github.com/cosmos/cosmos-sdk/client" - "github.com/pokt-network/poktroll/x/supplier/types" "github.com/spf13/cobra" + + "github.com/pokt-network/poktroll/x/supplier/types" ) // GetQueryCmd returns the cli query commands for this module diff --git a/x/supplier/client/cli/query_proof.go b/x/supplier/client/cli/query_proof.go index bc4d34092..f7adbb4cf 100644 --- a/x/supplier/client/cli/query_proof.go +++ b/x/supplier/client/cli/query_proof.go @@ -3,8 +3,9 @@ package cli import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/pokt-network/poktroll/x/supplier/types" "github.com/spf13/cobra" + + "github.com/pokt-network/poktroll/x/supplier/types" ) func CmdListProof() *cobra.Command { diff --git a/x/supplier/genesis.go b/x/supplier/genesis.go index 933414ac9..156d80118 100644 --- a/x/supplier/genesis.go +++ b/x/supplier/genesis.go @@ -2,6 +2,7 @@ package supplier import ( sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/pokt-network/poktroll/x/supplier/keeper" "github.com/pokt-network/poktroll/x/supplier/types" ) diff --git a/x/supplier/keeper/proof.go b/x/supplier/keeper/proof.go index e6074c6ea..25c1bd52d 100644 --- a/x/supplier/keeper/proof.go +++ b/x/supplier/keeper/proof.go @@ -3,6 +3,7 @@ package keeper import ( "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/pokt-network/poktroll/x/supplier/types" ) diff --git a/x/supplier/keeper/query_proof.go b/x/supplier/keeper/query_proof.go index 594eff71c..880d5c67b 100644 --- a/x/supplier/keeper/query_proof.go +++ b/x/supplier/keeper/query_proof.go @@ -6,9 +6,10 @@ import ( "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" - "github.com/pokt-network/poktroll/x/supplier/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + + "github.com/pokt-network/poktroll/x/supplier/types" ) func (k Keeper) AllProofs(goCtx context.Context, req *types.QueryAllProofsRequest) (*types.QueryAllProofsResponse, error) { diff --git a/x/supplier/types/genesis.go b/x/supplier/types/genesis.go index e3c3a09ee..9d06b42ff 100644 --- a/x/supplier/types/genesis.go +++ b/x/supplier/types/genesis.go @@ -5,6 +5,7 @@ import ( sdkerrors "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" + servicehelpers "github.com/pokt-network/poktroll/x/shared/helpers" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" ) diff --git a/x/supplier/types/message_create_claim.go b/x/supplier/types/message_create_claim.go index 9860c97bb..0b20c27ec 100644 --- a/x/supplier/types/message_create_claim.go +++ b/x/supplier/types/message_create_claim.go @@ -3,6 +3,7 @@ package types import ( sdkerrors "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" + sessiontypes "github.com/pokt-network/poktroll/x/session/types" sharedhelpers "github.com/pokt-network/poktroll/x/shared/helpers" ) From 3b491a5abe3c89eaa68e611826697a55f3ffcddc Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Wed, 22 Nov 2023 16:08:40 -0800 Subject: [PATCH 08/16] Update go.mod Co-authored-by: Bryan White --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 006bbc4ec..08e7ca4f9 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ // NB: Since this repostiory was scaffolded using `ignite s chain pocket` -// but the module was later rename to github.com/pokt-network/poktroll, we +// but the module was later renamed to github.com/pokt-network/poktroll, we // need to swap the two lines below only during the scaffolding operation. // NOTE that the operation is expected to error out but all the necesary // types and functions will be scaffolded correctly. From b680d9c90a66ea35e0f764a558b3669350a08ca5 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Wed, 22 Nov 2023 16:08:50 -0800 Subject: [PATCH 09/16] Update x/supplier/client/cli/query_proof.go Co-authored-by: Bryan White --- x/supplier/client/cli/query_proof.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/supplier/client/cli/query_proof.go b/x/supplier/client/cli/query_proof.go index f7adbb4cf..0e885b53c 100644 --- a/x/supplier/client/cli/query_proof.go +++ b/x/supplier/client/cli/query_proof.go @@ -46,7 +46,7 @@ func CmdListProof() *cobra.Command { func CmdShowProof() *cobra.Command { cmd := &cobra.Command{ - Use: "show-proof [index]", + Use: "show-proof ", Short: "shows a proof", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) (err error) { From 33f7fd1fdee9c4593c1fad8c1643d2ac124dc664 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Wed, 22 Nov 2023 16:12:26 -0800 Subject: [PATCH 10/16] Update x/supplier/client/cli/query_proof_test.go Co-authored-by: Bryan White --- x/supplier/client/cli/query_proof_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/supplier/client/cli/query_proof_test.go b/x/supplier/client/cli/query_proof_test.go index 1301b236f..f6f4fcefe 100644 --- a/x/supplier/client/cli/query_proof_test.go +++ b/x/supplier/client/cli/query_proof_test.go @@ -1,6 +1,6 @@ package cli_test -// TODO_UPNEXT(@Olshansk): Add these tests back in after updating how Proofs are stored on-chain. +// TODO_UPNEXT(@Olshansk): Add these tests back in after merging on-chain Proof persistence. // Prevent strconv unused error // var _ = strconv.IntSize From cede36c1a92a0c6a5850df3543d285bbf7efb86f Mon Sep 17 00:00:00 2001 From: Redouane Lakrache Date: Tue, 21 Nov 2023 00:30:15 +0100 Subject: [PATCH 11/16] [Supplier] feat: Add staking flag and config parser (#185) * feat: Add staking flag and config parser * chore: Update make file staking operation * test: Update staking tests to use a json config * test: add json staking config file * feat: Use yaml format instead of json * fix: Use yaml tags * chore: Address change requests, Add tests * fix: Add full path to supplier config * chore: address change requests --- Makefile | 10 +- .../config/supplier1_stake_config.yaml | 11 + .../config/supplier2_stake_config.yaml | 8 + .../config/supplier3_stake_config.yaml | 8 + x/supplier/client/cli/tx_stake_supplier.go | 65 ++-- .../client/cli/tx_stake_supplier_test.go | 236 +++++++++----- x/supplier/client/config/errors.go | 14 + .../client/config/supplier_configs_reader.go | 175 ++++++++++ .../config/supplier_configs_reader_test.go | 308 ++++++++++++++++++ 9 files changed, 703 insertions(+), 132 deletions(-) create mode 100644 localnet/poktrolld/config/supplier1_stake_config.yaml create mode 100644 localnet/poktrolld/config/supplier2_stake_config.yaml create mode 100644 localnet/poktrolld/config/supplier3_stake_config.yaml create mode 100644 x/supplier/client/config/errors.go create mode 100644 x/supplier/client/config/supplier_configs_reader.go create mode 100644 x/supplier/client/config/supplier_configs_reader_test.go diff --git a/Makefile b/Makefile index dc7666200..224ee5dc5 100644 --- a/Makefile +++ b/Makefile @@ -360,27 +360,27 @@ supplier_list: ## List all the staked supplier # TODO(@Olshansk, @okdas): Add more services (in addition to anvil) for apps and suppliers to stake for. # TODO_TECHDEBT: svc1, svc2 and svc3 below are only in place to make GetSession testable .PHONY: supplier_stake -supplier_stake: ## Stake tokens for the supplier specified (must specify the APP env var) - poktrolld --home=$(POKTROLLD_HOME) tx supplier stake-supplier 1000upokt "$(SERVICES)" --keyring-backend test --from $(SUPPLIER) --node $(POCKET_NODE) +supplier_stake: ## Stake tokens for the supplier specified (must specify the SUPPLIER and SUPPLIER_CONFIG env vars) + poktrolld --home=$(POKTROLLD_HOME) tx supplier stake-supplier 1000upokt --config $(POKTROLLD_HOME)/config/$(SERVICES) --keyring-backend test --from $(SUPPLIER) --node $(POCKET_NODE) # TODO_IMPROVE(#180): Make sure genesis-staked actors are available via AccountKeeper .PHONY: supplier1_stake supplier1_stake: ## Stake supplier1 (also staked in genesis) # TODO_UPNEXT(@okdas): once `relayminer` service is added to tilt, this hostname should point to that service. # I.e.: replace `localhost` with `relayminer` (or whatever the service's hostname is). - SUPPLIER=supplier1 SERVICES="anvil;http://localhost:8545,svc1;http://localhost:8081" make supplier_stake + SUPPLIER=supplier1 SERVICES=supplier1_stake_config.yaml make supplier_stake .PHONY: supplier2_stake supplier2_stake: ## Stake supplier2 # TODO_UPNEXT(@okdas): once `relayminer` service is added to tilt, this hostname should point to that service. # I.e.: replace `localhost` with `relayminer` (or whatever the service's hostname is). - SUPPLIER=supplier2 SERVICES="anvil;http://localhost:8545,svc2;http://localhost:8082" make supplier_stake + SUPPLIER=supplier2 SERVICES=supplier2_stake_config.yaml make supplier_stake .PHONY: supplier3_stake supplier3_stake: ## Stake supplier3 # TODO_UPNEXT(@okdas): once `relayminer` service is added to tilt, this hostname should point to that service. # I.e.: replace `localhost` with `relayminer` (or whatever the service's hostname is). - SUPPLIER=supplier3 SERVICES="anvil;http://localhost:8545,svc3;http://localhost:8083" make supplier_stake + SUPPLIER=supplier3 SERVICES=supplier3_stake_config.yaml make supplier_stake .PHONY: supplier_unstake supplier_unstake: ## Unstake an supplier (must specify the SUPPLIER env var) diff --git a/localnet/poktrolld/config/supplier1_stake_config.yaml b/localnet/poktrolld/config/supplier1_stake_config.yaml new file mode 100644 index 000000000..c65514ac1 --- /dev/null +++ b/localnet/poktrolld/config/supplier1_stake_config.yaml @@ -0,0 +1,11 @@ +# TODO(@Olshansk, @okdas): Add more services (in addition to anvil) for apps and suppliers to stake for. +# TODO_TECHDEBT: svc1, svc2 and svc3 below are only in place to make GetSession testable +# TODO_IMPROVE(#180): Make sure genesis-staked actors are available via AccountKeeper +- service_id: anvil + endpoints: + - url: http://anvil:8547 + rpc_type: json_rpc +- service_id: svc1 + endpoints: + - url: http://lovalhost:8081 + rpc_type: json_rpc \ No newline at end of file diff --git a/localnet/poktrolld/config/supplier2_stake_config.yaml b/localnet/poktrolld/config/supplier2_stake_config.yaml new file mode 100644 index 000000000..5bdfca2a8 --- /dev/null +++ b/localnet/poktrolld/config/supplier2_stake_config.yaml @@ -0,0 +1,8 @@ +- service_id: anvil + endpoints: + - url: http://anvil:8547 + rpc_type: json_rpc +- service_id: svc1 + endpoints: + - url: http://lovalhost:8082 + rpc_type: json_rpc diff --git a/localnet/poktrolld/config/supplier3_stake_config.yaml b/localnet/poktrolld/config/supplier3_stake_config.yaml new file mode 100644 index 000000000..69b631468 --- /dev/null +++ b/localnet/poktrolld/config/supplier3_stake_config.yaml @@ -0,0 +1,8 @@ +- service_id: anvil + endpoints: + - url: http://anvil:8547 + rpc_type: json_rpc +- service_id: svc1 + endpoints: + - url: http://lovalhost:8083 + rpc_type: json_rpc diff --git a/x/supplier/client/cli/tx_stake_supplier.go b/x/supplier/client/cli/tx_stake_supplier.go index 83a1413e2..ca940cc8a 100644 --- a/x/supplier/client/cli/tx_stake_supplier.go +++ b/x/supplier/client/cli/tx_stake_supplier.go @@ -1,9 +1,8 @@ package cli import ( - "fmt" + "os" "strconv" - "strings" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" @@ -11,34 +10,30 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/spf13/cobra" - sharedtypes "github.com/pokt-network/poktroll/x/shared/types" + "github.com/pokt-network/poktroll/x/supplier/client/config" "github.com/pokt-network/poktroll/x/supplier/types" ) -var _ = strconv.Itoa(0) +var ( + flagStakeConfig string + _ = strconv.Itoa(0) // Part of the default ignite imports +) func CmdStakeSupplier() *cobra.Command { // fromAddress & signature is retrieved via `flags.FlagFrom` in the `clientCtx` cmd := &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 ", + Use: "stake-supplier [--config config_file]", 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. -TODO_HACK: Until proper service configuration files are supported, suppliers must specify the services as a single string -of comma separated values of the form 'service;url' where 'service' is the service ID and 'url' is the service URL. -For example, an application that stakes for 'anvil' could be matched with a supplier staking for 'anvil;http://anvil:8547'. Example: -$ poktrolld --home=$(POKTROLLD_HOME) tx supplier stake-supplier 1000upokt anvil;http://anvil:8547 --keyring-backend test --from $(APP) --node $(POCKET_NODE)`, - Args: cobra.ExactArgs(2), +$ poktrolld --home=$(POKTROLLD_HOME) tx supplier stake-supplier 1000upokt --config stake_config.yaml --keyring-backend test --from $(APP) --node $(POCKET_NODE)`, + + Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) (err error) { stakeString := args[0] - servicesArg := args[1] - - clientCtx, err := client.GetClientTxContext(cmd) + configContent, err := os.ReadFile(flagStakeConfig) if err != nil { return err } @@ -48,7 +43,12 @@ $ poktrolld --home=$(POKTROLLD_HOME) tx supplier stake-supplier 1000upokt anvil; return err } - services, err := hackStringToServices(servicesArg) + supplierStakeConfigs, err := config.ParseSupplierConfigs(configContent) + if err != nil { + return err + } + + clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err } @@ -56,7 +56,7 @@ $ poktrolld --home=$(POKTROLLD_HOME) tx supplier stake-supplier 1000upokt anvil; msg := types.NewMsgStakeSupplier( clientCtx.GetFromAddress().String(), stake, - services, + supplierStakeConfigs, ) if err := msg.ValidateBasic(); err != nil { @@ -67,35 +67,8 @@ $ poktrolld --home=$(POKTROLLD_HOME) tx supplier stake-supplier 1000upokt anvil; }, } + cmd.Flags().StringVar(&flagStakeConfig, "config", "", "Path to the stake config file") flags.AddTxFlagsToCmd(cmd) return cmd } - -// TODO_BLOCKER, TODO_HACK: The supplier stake command should take an argument -// or flag that points to a file containing all the services configurations & specifications. -// As a quick workaround, we just need the service & url to get things working for now. -func hackStringToServices(servicesArg string) ([]*sharedtypes.SupplierServiceConfig, error) { - supplierServiceConfig := make([]*sharedtypes.SupplierServiceConfig, 0) - serviceStrings := strings.Split(servicesArg, ",") - for _, serviceString := range serviceStrings { - serviceParts := strings.Split(serviceString, ";") - if len(serviceParts) != 2 { - return nil, fmt.Errorf("invalid service string: %s. Expected it to be of the form 'service;url'", serviceString) - } - service := &sharedtypes.SupplierServiceConfig{ - Service: &sharedtypes.Service{ - Id: serviceParts[0], - }, - Endpoints: []*sharedtypes.SupplierEndpoint{ - { - Url: serviceParts[1], - RpcType: sharedtypes.RPCType_JSON_RPC, - Configs: make([]*sharedtypes.ConfigOption, 0), - }, - }, - } - supplierServiceConfig = append(supplierServiceConfig, service) - } - return supplierServiceConfig, nil -} diff --git a/x/supplier/client/cli/tx_stake_supplier_test.go b/x/supplier/client/cli/tx_stake_supplier_test.go index f61d41fc9..b9059da2a 100644 --- a/x/supplier/client/cli/tx_stake_supplier_test.go +++ b/x/supplier/client/cli/tx_stake_supplier_test.go @@ -15,6 +15,7 @@ import ( "github.com/pokt-network/poktroll/testutil/network" "github.com/pokt-network/poktroll/x/supplier/client/cli" + "github.com/pokt-network/poktroll/x/supplier/client/config" "github.com/pokt-network/poktroll/x/supplier/types" ) @@ -38,135 +39,205 @@ func TestCLI_StakeSupplier(t *testing.T) { fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(net.Config.BondDenom, sdkmath.NewInt(10))).String()), } + defaultConfig := ` + - service_id: svc1 + endpoints: + - url: http://pokt.network:8081 + rpc_type: json_rpc + ` + tests := []struct { - desc string - address string - stakeString string - servicesString string - err *sdkerrors.Error + desc string + address string + stakeString string + config string + err *sdkerrors.Error }{ // Happy Paths { - desc: "stake supplier: valid", - address: supplierAccount.Address.String(), - stakeString: "1000upokt", - servicesString: "svc1;http://pokt.network:8081", + desc: "stake supplier: valid", + address: supplierAccount.Address.String(), + stakeString: "1000upokt", + config: defaultConfig, }, // Error Paths - Address Related { desc: "stake supplier: missing address", // address: "explicitly missing", - stakeString: "1000upokt", - servicesString: "svc1;http://pokt.network:8081", - err: types.ErrSupplierInvalidAddress, + err: types.ErrSupplierInvalidAddress, + stakeString: "1000upokt", + config: defaultConfig, }, { - desc: "stake supplier: invalid address", - address: "invalid", - stakeString: "1000upokt", - servicesString: "svc1;http://pokt.network:8081", - err: types.ErrSupplierInvalidAddress, + desc: "stake supplier: invalid address", + address: "invalid", + stakeString: "1000upokt", + err: types.ErrSupplierInvalidAddress, + config: defaultConfig, }, // Error Paths - Stake Related { desc: "stake supplier: missing stake", address: supplierAccount.Address.String(), - // stakeString: "explicitly missing", - servicesString: "svc1;http://pokt.network:8081", - err: types.ErrSupplierInvalidStake, + err: types.ErrSupplierInvalidStake, + // stakeString: "explicitly missing", + config: ` + - service_id: svc1 + endpoints: + - url: http://pokt.network:8081 + rpc_type: json_rpc + `, }, { - desc: "stake supplier: invalid stake denom", - address: supplierAccount.Address.String(), - stakeString: "1000invalid", - servicesString: "svc1;http://pokt.network:8081", - err: types.ErrSupplierInvalidStake, + desc: "stake supplier: invalid stake denom", + address: supplierAccount.Address.String(), + err: types.ErrSupplierInvalidStake, + stakeString: "1000invalid", + config: ` + - service_id: svc1 + endpoints: + - url: http://pokt.network:8081 + rpc_type: json_rpc + `, }, { - desc: "stake supplier: invalid stake amount (zero)", - address: supplierAccount.Address.String(), - stakeString: "0upokt", - servicesString: "svc1;http://pokt.network:8081", - err: types.ErrSupplierInvalidStake, + desc: "stake supplier: invalid stake amount (zero)", + address: supplierAccount.Address.String(), + err: types.ErrSupplierInvalidStake, + stakeString: "0upokt", + config: ` + - service_id: svc1 + endpoints: + - url: http://pokt.network:8081 + rpc_type: json_rpc + `, }, { - desc: "stake supplier: invalid stake amount (negative)", - address: supplierAccount.Address.String(), - stakeString: "-1000upokt", - servicesString: "svc1;http://pokt.network:8081", - err: types.ErrSupplierInvalidStake, + desc: "stake supplier: invalid stake amount (negative)", + address: supplierAccount.Address.String(), + err: types.ErrSupplierInvalidStake, + stakeString: "-1000upokt", + config: ` + - service_id: svc1 + endpoints: + - url: http://pokt.network:8081 + rpc_type: json_rpc + `, }, // Happy Paths - Service Related { - desc: "services_test: valid multiple services", - address: supplierAccount.Address.String(), - stakeString: "1000upokt", - servicesString: "svc1;http://pokt.network:8081,svc2;http://pokt.network:8082", + desc: "services_test: valid multiple services", + address: supplierAccount.Address.String(), + stakeString: "1000upokt", + config: ` + - service_id: svc1 + endpoints: + - url: http://pokt.network:8081 + rpc_type: json_rpc + - service_id: svc2 + endpoints: + - url: http://pokt.network:8082 + rpc_type: json_rpc + `, }, { - desc: "services_test: valid localhost", - address: supplierAccount.Address.String(), - stakeString: "1000upokt", - servicesString: "scv1;http://127.0.0.1:8082", + desc: "services_test: valid localhost", + address: supplierAccount.Address.String(), + stakeString: "1000upokt", + config: ` + - service_id: svc1 + endpoints: + - url: http://127.0.0.1:8082 + rpc_type: json_rpc + `, }, { - desc: "services_test: valid loopback", - address: supplierAccount.Address.String(), - stakeString: "1000upokt", - servicesString: "scv1;http://localhost:8082", + desc: "services_test: valid loopback", + address: supplierAccount.Address.String(), + stakeString: "1000upokt", + config: ` + - service_id: svc1 + endpoints: + - url: http://localhost:8082 + rpc_type: json_rpc + `, }, { - desc: "services_test: valid without a pork", - address: supplierAccount.Address.String(), - stakeString: "1000upokt", - servicesString: "scv1;http://pokt.network", + desc: "services_test: valid without a pork", + address: supplierAccount.Address.String(), + stakeString: "1000upokt", + config: ` + - service_id: svc1 + endpoints: + - url: http://pokt.network + rpc_type: json_rpc + `, }, // Error Paths - Service Related { - desc: "services_test: invalid services (missing argument)", - address: supplierAccount.Address.String(), - stakeString: "1000upokt", + desc: "services_test: invalid services (missing argument)", + address: supplierAccount.Address.String(), + err: types.ErrSupplierInvalidServiceConfig, // servicesString: "explicitly omitted", - err: types.ErrSupplierInvalidServiceConfig, + stakeString: "1000upokt", }, { - desc: "services_test: invalid services (empty string)", - address: supplierAccount.Address.String(), - stakeString: "1000upokt", - servicesString: "", - err: types.ErrSupplierInvalidServiceConfig, + desc: "services_test: invalid services (empty string)", + address: supplierAccount.Address.String(), + err: types.ErrSupplierInvalidServiceConfig, + stakeString: "1000upokt", + config: ``, }, { - desc: "services_test: invalid because contains a space", - address: supplierAccount.Address.String(), - stakeString: "1000upokt", - servicesString: "scv1 http://127.0.0.1:8082", - err: types.ErrSupplierInvalidServiceConfig, + desc: "services_test: invalid URL", + address: supplierAccount.Address.String(), + err: types.ErrSupplierInvalidServiceConfig, + stakeString: "1000upokt", + config: ` + - service_id: svc1 + endpoints: + - url: bad_url + rpc_type: json_rpc + `, }, { - desc: "services_test: invalid URL", - address: supplierAccount.Address.String(), - stakeString: "1000upokt", - servicesString: "svc1;bad_url", - err: types.ErrSupplierInvalidServiceConfig, + desc: "services_test: missing URLs", + address: supplierAccount.Address.String(), + err: types.ErrSupplierInvalidServiceConfig, + stakeString: "1000upokt", + config: ` + - service_id: svc1 + - service_id: svc2 + `, }, { - desc: "services_test: missing URLs", - address: supplierAccount.Address.String(), - stakeString: "1000upokt", - servicesString: "svc1,svc2;", - err: types.ErrSupplierInvalidServiceConfig, + desc: "services_test: missing service IDs", + address: supplierAccount.Address.String(), + err: types.ErrSupplierInvalidServiceConfig, + stakeString: "1000upokt", + config: ` + - endpoints: + - url: localhost:8081 + rpc_type: json_rpc + - endpoints: + - url: localhost:8082 + rpc_type: json_rpc + `, }, { - desc: "services_test: missing service IDs", - address: supplierAccount.Address.String(), - stakeString: "1000upokt", - servicesString: "localhost:8081,;localhost:8082", - err: types.ErrSupplierInvalidServiceConfig, + desc: "services_test: missing rpc type", + address: supplierAccount.Address.String(), + err: types.ErrSupplierInvalidServiceConfig, + stakeString: "1000upokt", + config: ` + - service_id: svc1 + endpoints: + - url: localhost:8082 + `, }, } @@ -179,10 +250,13 @@ func TestCLI_StakeSupplier(t *testing.T) { // Wait for a new block to be committed require.NoError(t, net.WaitForNextBlock()) + // write the stake config to a file + configPath := testutil.WriteToNewTempFile(t, config.NormalizeYAMLIndentation(tt.config)).Name() + // Prepare the arguments for the CLI command args := []string{ tt.stakeString, - tt.servicesString, + fmt.Sprintf("--config=%s", configPath), fmt.Sprintf("--%s=%s", flags.FlagFrom, tt.address), } args = append(args, commonArgs...) diff --git a/x/supplier/client/config/errors.go b/x/supplier/client/config/errors.go new file mode 100644 index 000000000..0739daf93 --- /dev/null +++ b/x/supplier/client/config/errors.go @@ -0,0 +1,14 @@ +package config + +import sdkerrors "cosmossdk.io/errors" + +var ( + codespace = "supplierconfig" + ErrSupplierConfigUnmarshalYAML = sdkerrors.Register(codespace, 1, "config reader cannot unmarshal yaml content") + ErrSupplierConfigInvalidServiceId = sdkerrors.Register(codespace, 2, "invalid serviceId in supplier config") + ErrSupplierConfigNoEndpoints = sdkerrors.Register(codespace, 3, "no endpoints defined for serviceId in supplier config") + ErrSupplierConfigInvalidEndpointConfig = sdkerrors.Register(codespace, 4, "invalid endpoint config in supplier config") + ErrSupplierConfigInvalidRPCType = sdkerrors.Register(codespace, 5, "invalid rpc type in supplier config") + ErrSupplierConfigInvalidURL = sdkerrors.Register(codespace, 6, "invalid endpoint url in supplier config") + ErrSupplierConfigEmptyContent = sdkerrors.Register(codespace, 7, "empty supplier config content") +) diff --git a/x/supplier/client/config/supplier_configs_reader.go b/x/supplier/client/config/supplier_configs_reader.go new file mode 100644 index 000000000..538338318 --- /dev/null +++ b/x/supplier/client/config/supplier_configs_reader.go @@ -0,0 +1,175 @@ +package config + +import ( + "net/url" + "strings" + + "gopkg.in/yaml.v2" + + sharedhelpers "github.com/pokt-network/poktroll/x/shared/helpers" + sharedtypes "github.com/pokt-network/poktroll/x/shared/types" +) + +// YAMLStakeService is the structure describing a single service stake entry in the stake config file +type YAMLStakeService struct { + ServiceId string `yaml:"service_id"` + Endpoints []YAMLServiceEndpoint `yaml:"endpoints"` +} + +// YAMLServiceEndpoint is the structure describing a single service endpoint in the stake config file +type YAMLServiceEndpoint struct { + Url string `yaml:"url"` + RPCType string `yaml:"rpc_type"` + Config map[string]string `yaml:"config"` +} + +// ParseSupplierServiceConfig parses the stake config file into a SupplierServiceConfig +func ParseSupplierConfigs(configContent []byte) ([]*sharedtypes.SupplierServiceConfig, error) { + var stakeConfig []*YAMLStakeService + + // Unmarshal the stake config file into a stakeConfig + if err := yaml.Unmarshal(configContent, &stakeConfig); err != nil { + return nil, ErrSupplierConfigUnmarshalYAML.Wrapf("%s", err) + } + + if len(stakeConfig) == 0 { + return nil, ErrSupplierConfigEmptyContent + } + + // Prepare the supplierServiceConfig + supplierServiceConfig := []*sharedtypes.SupplierServiceConfig{} + + // Populate the services slice + for _, svc := range stakeConfig { + // Validate the serviceId + if !sharedhelpers.IsValidServiceId(svc.ServiceId) { + return nil, ErrSupplierConfigInvalidServiceId.Wrapf("%s", svc.ServiceId) + } + + if len(svc.Endpoints) == 0 { + return nil, ErrSupplierConfigNoEndpoints.Wrapf("%s", svc.ServiceId) + } + + // Create a supplied service config with the serviceId + service := &sharedtypes.SupplierServiceConfig{ + Service: &sharedtypes.Service{Id: svc.ServiceId}, + Endpoints: []*sharedtypes.SupplierEndpoint{}, + } + + // Iterate over the service endpoints and add their parsed representation to the supplied service config + for _, endpoint := range svc.Endpoints { + parsedEndpointEntry, err := parseEndpointEntry(endpoint) + if err != nil { + return nil, err + } + service.Endpoints = append(service.Endpoints, parsedEndpointEntry) + } + supplierServiceConfig = append(supplierServiceConfig, service) + } + + return supplierServiceConfig, nil +} + +func parseEndpointEntry(endpoint YAMLServiceEndpoint) (*sharedtypes.SupplierEndpoint, error) { + endpointEntry := &sharedtypes.SupplierEndpoint{} + var err error + + // Endpoint URL + if endpointEntry.Url, err = validateEndpointURL(endpoint); err != nil { + return nil, err + } + + // Endpoint config + if endpointEntry.Configs, err = parseEndpointConfigs(endpoint); err != nil { + return nil, err + } + + // Endpoint RPC type + if endpointEntry.RpcType, err = parseEndpointRPCType(endpoint); err != nil { + return nil, err + } + + return endpointEntry, nil +} + +// validateEndpointURL validates the endpoint URL, making sure that the string provided is a valid URL +func validateEndpointURL(endpoint YAMLServiceEndpoint) (string, error) { + // Validate the endpoint URL + if _, err := url.Parse(endpoint.Url); err != nil { + return "", ErrSupplierConfigInvalidURL.Wrapf("%s", err) + } + + return endpoint.Url, nil +} + +// parseEndpointConfigs parses the endpoint config entries into a slice of ConfigOption +// compatible with the SupplierEndpointConfig. +// It accepts a nil config entry or a map of valid config keys. +func parseEndpointConfigs(endpoint YAMLServiceEndpoint) ([]*sharedtypes.ConfigOption, error) { + // Prepare the endpoint configs slice + endpointConfigs := []*sharedtypes.ConfigOption{} + + // If we have an endpoint config entry, parse it into a slice of ConfigOption + if endpoint.Config == nil { + return endpointConfigs, nil + } + + // Iterate over the endpoint config entries and add them to the slice of ConfigOption + for key, value := range endpoint.Config { + var configKey sharedtypes.ConfigOptions + + // Make sure the config key is valid + switch key { + case "timeout": + configKey = sharedtypes.ConfigOptions_TIMEOUT + default: + return nil, ErrSupplierConfigInvalidEndpointConfig.Wrapf("%s", key) + } + + config := &sharedtypes.ConfigOption{ + Key: configKey, + Value: value, + } + endpointConfigs = append(endpointConfigs, config) + } + + return endpointConfigs, nil +} + +// parseEndpointRPCType parses the endpoint RPC type into a sharedtypes.RPCType +func parseEndpointRPCType(endpoint YAMLServiceEndpoint) (sharedtypes.RPCType, error) { + switch endpoint.RPCType { + case "json_rpc": + return sharedtypes.RPCType_JSON_RPC, nil + default: + return sharedtypes.RPCType_UNKNOWN_RPC, ErrSupplierConfigInvalidRPCType.Wrapf("%s", endpoint.RPCType) + } +} + +// YAML is indentation sensitive, so we need to remove the extra indentation from the test cases and make sure +// it is space-indented instead of tab-indented, otherwise the YAML parser will fail +func NormalizeYAMLIndentation(rawContent string) string { + var processedContent = rawContent + // Remove extra newlines + processedContent = strings.TrimPrefix(processedContent, "\n") + + // Replace tab indentation with 2 spaces as our code is tab-indented but YAML is expecting double spaces + processedContent = strings.ReplaceAll(processedContent, "\t", " ") + + // Get the extra indentation from the first line that will serve as the basis for the rest of the lines + extraIndentationCount := len(processedContent) - len(strings.TrimLeft(processedContent, " ")) + + // Create a prefix to trim from the beginning of each line + extraIndentation := strings.Repeat(" ", extraIndentationCount) + + // Split the content into lines, trim the extra indentation from each line, and rejoin the lines + lines := strings.Split(processedContent, "\n") + for i := range lines { + lines[i] = strings.TrimPrefix(lines[i], extraIndentation) + } + + // Recover the processed content + processedContent = strings.Trim(strings.Join(lines, "\n"), "\n") + + return processedContent +} diff --git a/x/supplier/client/config/supplier_configs_reader_test.go b/x/supplier/client/config/supplier_configs_reader_test.go new file mode 100644 index 000000000..b3ab06c44 --- /dev/null +++ b/x/supplier/client/config/supplier_configs_reader_test.go @@ -0,0 +1,308 @@ +package config_test + +import ( + "testing" + + sdkerrors "cosmossdk.io/errors" + "github.com/gogo/status" + "github.com/stretchr/testify/require" + + "github.com/pokt-network/poktroll/x/shared/types" + "github.com/pokt-network/poktroll/x/supplier/client/config" +) + +func Test_ParseSupplierConfigs(t *testing.T) { + tests := []struct { + desc string + err *sdkerrors.Error + expected []*types.SupplierServiceConfig + config string + }{ + // Valid Configs + { + desc: "services_test: valid full service config", + err: nil, + expected: []*types.SupplierServiceConfig{ + { + Service: &types.Service{Id: "svc"}, + Endpoints: []*types.SupplierEndpoint{ + { + Url: "http://pokt.network:8081", + RpcType: types.RPCType_JSON_RPC, + Configs: []*types.ConfigOption{ + { + Key: types.ConfigOptions_TIMEOUT, + Value: "10", + }, + }, + }, + }, + }, + }, + config: ` + - service_id: svc + endpoints: + - url: http://pokt.network:8081 + rpc_type: json_rpc + config: + timeout: 10 + `, + }, + { + desc: "services_test: valid service config without endpoint config", + err: nil, + expected: []*types.SupplierServiceConfig{ + { + Service: &types.Service{Id: "svc"}, + Endpoints: []*types.SupplierEndpoint{ + { + Url: "http://pokt.network:8081", + RpcType: types.RPCType_JSON_RPC, + }, + }, + }, + }, + config: ` + - service_id: svc + endpoints: + - url: http://pokt.network:8081 + rpc_type: json_rpc + `, + }, + { + desc: "services_test: valid service config with empty endpoint config", + err: nil, + expected: []*types.SupplierServiceConfig{ + { + Service: &types.Service{Id: "svc"}, + Endpoints: []*types.SupplierEndpoint{ + { + Url: "http://pokt.network:8081", + RpcType: types.RPCType_JSON_RPC, + Configs: []*types.ConfigOption{}, + }, + }, + }, + }, + config: ` + - service_id: svc + endpoints: + - url: http://pokt.network:8081 + rpc_type: json_rpc + config: + `, + }, + { + desc: "services_test: valid service config with multiple endpoints", + err: nil, + expected: []*types.SupplierServiceConfig{ + { + Service: &types.Service{Id: "svc"}, + Endpoints: []*types.SupplierEndpoint{ + { + Url: "http://pokt.network:8081", + RpcType: types.RPCType_JSON_RPC, + Configs: []*types.ConfigOption{ + { + Key: types.ConfigOptions_TIMEOUT, + Value: "10", + }, + }, + }, + { + Url: "http://pokt.network:8082", + RpcType: types.RPCType_JSON_RPC, + Configs: []*types.ConfigOption{ + { + Key: types.ConfigOptions_TIMEOUT, + Value: "11", + }, + }, + }, + }, + }, + }, + config: ` + - service_id: svc + endpoints: + - url: http://pokt.network:8081 + rpc_type: json_rpc + config: + timeout: 10 + - url: http://pokt.network:8082 + rpc_type: json_rpc + config: + timeout: 11 + `, + }, + { + desc: "services_test: valid service config with multiple services", + err: nil, + expected: []*types.SupplierServiceConfig{ + { + Service: &types.Service{Id: "svc1"}, + Endpoints: []*types.SupplierEndpoint{ + { + Url: "http://pokt.network:8081", + RpcType: types.RPCType_JSON_RPC, + Configs: []*types.ConfigOption{ + { + Key: types.ConfigOptions_TIMEOUT, + Value: "10", + }, + }, + }, + }, + }, + { + Service: &types.Service{Id: "svc2"}, + Endpoints: []*types.SupplierEndpoint{ + { + Url: "http://pokt.network:8081", + RpcType: types.RPCType_JSON_RPC, + Configs: []*types.ConfigOption{ + { + Key: types.ConfigOptions_TIMEOUT, + Value: "10", + }, + }, + }, + }, + }, + }, + config: ` + - service_id: svc1 + endpoints: + - url: http://pokt.network:8081 + rpc_type: json_rpc + config: + timeout: 10 + - service_id: svc2 + endpoints: + - url: http://pokt.network:8081 + rpc_type: json_rpc + config: + timeout: 10 + `, + }, + // Invalid Configs + { + desc: "services_test: invalid service config without service ID", + err: config.ErrSupplierConfigUnmarshalYAML, + config: ` + endpoints: + - url: http://pokt.network:8081 + rpc_type: json_rpc + config: + timeout: 10 + `, + }, + { + desc: "services_test: invalid service config with empty service ID", + err: config.ErrSupplierConfigInvalidServiceId, + config: ` + - service_id: + endpoints: + - url: http://pokt.network:8081 + rpc_type: json_rpc + config: + timeout: 10 + `, + }, + { + desc: "services_test: invalid service config without endpoints", + err: config.ErrSupplierConfigNoEndpoints, + config: ` + - service_id: svc + `, + }, + { + desc: "services_test: invalid service config with empty endpoints", + err: config.ErrSupplierConfigNoEndpoints, + config: ` + - service_id: svc + endpoints: + `, + }, + { + desc: "services_test: invalid service config with unknown endpoint config key", + err: config.ErrSupplierConfigInvalidEndpointConfig, + config: ` + - service_id: svc + endpoints: + - url: http://pokt.network:8081 + rpc_type: json_rpc + config: + somekey: 10 + `, + }, + { + desc: "services_test: invalid service config with unknown endpoint rpc type", + err: config.ErrSupplierConfigInvalidRPCType, + config: ` + - service_id: svc + endpoints: + - url: http://pokt.network:8081 + rpc_type: somerpc + config: + timeout: 10 + `, + }, + { + desc: "services_test: invalid service config with invalid endpoint url", + err: config.ErrSupplierConfigInvalidURL, + config: ` + - service_id: svc + endpoints: + - url: ::invalid_url + rpc_type: json_rpc + config: + timeout: 10 + `, + }, + { + desc: "services_test: invalid service config with empty content", + err: config.ErrSupplierConfigInvalidURL, + config: ``, + }, + } + + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + normalizedConfig := config.NormalizeYAMLIndentation(tt.config) + supplierServiceConfig, err := config.ParseSupplierConfigs([]byte(normalizedConfig)) + + if tt.err != nil { + require.Error(t, err) + require.Nil(t, supplierServiceConfig) + stat, ok := status.FromError(tt.err) + require.True(t, ok) + require.Contains(t, stat.Message(), tt.err.Error()) + require.Nil(t, supplierServiceConfig) + return + } + + require.NoError(t, err) + + require.Equal(t, len(tt.expected), len(supplierServiceConfig)) + for i, expected := range tt.expected { + + require.Equal(t, expected.Service.Id, supplierServiceConfig[i].Service.Id) + + require.Equal(t, len(expected.Endpoints), len(supplierServiceConfig[i].Endpoints)) + for j, expectedEndpoint := range expected.Endpoints { + + require.Equal(t, expectedEndpoint.Url, supplierServiceConfig[i].Endpoints[j].Url) + require.Equal(t, expectedEndpoint.RpcType, supplierServiceConfig[i].Endpoints[j].RpcType) + + require.Equal(t, len(expectedEndpoint.Configs), len(supplierServiceConfig[i].Endpoints[j].Configs)) + for k, expectedConfig := range expectedEndpoint.Configs { + + require.Equal(t, expectedConfig.Key, supplierServiceConfig[i].Endpoints[j].Configs[k].Key) + require.Equal(t, expectedConfig.Value, supplierServiceConfig[i].Endpoints[j].Configs[k].Value) + } + } + } + }) + } +} From df6ee286344784ad342fe1a003ffde62160d0d6c Mon Sep 17 00:00:00 2001 From: Bryan White Date: Wed, 22 Nov 2023 21:56:07 +0100 Subject: [PATCH 12/16] [Miner] test: add `#MinedRelays()` coverage (#191) * test: improve curl usage in e2e suite * chore: add `WithDifficulty()` miner option * test: add `miner#MinedRelays` coverage * chore: review feedback improvements Co-authored-by: Daniel Olshansky * refactor: `TestFixtureGeneration_MineMockRelays()` add `--gen-mined-relays` flag to conditionally skip * refactor: set fixture generation precedent * chore: improve naming & comments * chore: improve comments & cleanup * chore: remove commented code * refactor: `HashBytes` to shared testutil * refactor & fix: difficulty * [RelayMiner, Testing] test: add coverage to `relayerSessionsManager` (#194) * test: `relayerSessionsManager` claim/proof life-cycle * chore: review feedback improvements Co-authored-by: Daniel Olshansky --------- Co-authored-by: Daniel Olshansky * chore: fix comment * chore: review feedback improvements * chore: review feedback improvements * chore: review feedback improvements * revert: `RelayRequest` pointer receivers * chore: add TODO comment * chore: add "DO NOT EDIT..." comment to fixture output * chore: chore: review feedback improvements --------- Co-authored-by: Daniel Olshansky --- Makefile | 4 + pkg/client/interface.go | 1 + pkg/observable/channel/collect.go | 32 +++ pkg/relayer/miner/gen/gen_fixtures.go | 304 +++++++++++++++++++++ pkg/relayer/miner/gen/template.go | 37 +++ pkg/relayer/miner/miner.go | 22 +- pkg/relayer/miner/miner_test.go | 141 +++++++++- pkg/relayer/miner/options.go | 11 + pkg/relayer/miner/relay_fixtures_test.go | 33 +++ pkg/relayer/session/session.go | 2 + pkg/relayer/session/session_test.go | 113 +++++++- testutil/testclient/testblock/client.go | 26 ++ testutil/testclient/testsupplier/client.go | 34 +++ testutil/testrelayer/hash.go | 16 ++ testutil/testrelayer/options.go | 23 ++ x/service/types/relay.go | 8 + 16 files changed, 797 insertions(+), 10 deletions(-) create mode 100644 pkg/observable/channel/collect.go create mode 100644 pkg/relayer/miner/gen/gen_fixtures.go create mode 100644 pkg/relayer/miner/gen/template.go create mode 100644 pkg/relayer/miner/options.go create mode 100644 pkg/relayer/miner/relay_fixtures_test.go create mode 100644 testutil/testrelayer/hash.go create mode 100644 testutil/testrelayer/options.go diff --git a/Makefile b/Makefile index 224ee5dc5..ba73809da 100644 --- a/Makefile +++ b/Makefile @@ -166,6 +166,10 @@ go_mockgen: ## Use `mockgen` to generate mocks used for testing purposes of all go generate ./x/session/types/ go generate ./pkg/... +.PHONY: go_fixturegen +go_fixturegen: ## Generate fixture data for unit tests + go generate ./pkg/relayer/miner/miner_test.go + .PHONY: go_develop go_develop: proto_regen go_mockgen ## Generate protos and mocks diff --git a/pkg/client/interface.go b/pkg/client/interface.go index 1a9bcb500..67627bc9d 100644 --- a/pkg/client/interface.go +++ b/pkg/client/interface.go @@ -1,6 +1,7 @@ //go:generate mockgen -destination=../../testutil/mockclient/events_query_client_mock.go -package=mockclient . Dialer,Connection,EventsQueryClient //go:generate mockgen -destination=../../testutil/mockclient/block_client_mock.go -package=mockclient . Block,BlockClient //go:generate mockgen -destination=../../testutil/mockclient/tx_client_mock.go -package=mockclient . TxContext,TxClient +//go:generate mockgen -destination=../../testutil/mockclient/supplier_client_mock.go -package=mockclient . SupplierClient //go:generate mockgen -destination=../../testutil/mockclient/cosmos_tx_builder_mock.go -package=mockclient github.com/cosmos/cosmos-sdk/client TxBuilder //go:generate mockgen -destination=../../testutil/mockclient/cosmos_keyring_mock.go -package=mockclient github.com/cosmos/cosmos-sdk/crypto/keyring Keyring //go:generate mockgen -destination=../../testutil/mockclient/cosmos_client_mock.go -package=mockclient github.com/cosmos/cosmos-sdk/client AccountRetriever diff --git a/pkg/observable/channel/collect.go b/pkg/observable/channel/collect.go new file mode 100644 index 000000000..4a8e1e22f --- /dev/null +++ b/pkg/observable/channel/collect.go @@ -0,0 +1,32 @@ +package channel + +import ( + "context" + "sync" + + "github.com/pokt-network/poktroll/pkg/observable" +) + +// Collect collects all notifications received from the observable and returns +// them as a slice. ctx MUST be canceled, after some finite duration as it blocks +// until either srcObservable is closed OR ctx is canceled. Collect is a terminal +// observable operator. +func Collect[V any]( + ctx context.Context, + srcObservable observable.Observable[V], +) (dstCollection []V) { + var dstCollectionMu sync.Mutex + defer dstCollectionMu.Unlock() + + ForEach(ctx, srcObservable, func(ctx context.Context, src V) { + dstCollectionMu.Lock() + dstCollection = append(dstCollection, src) + dstCollectionMu.Unlock() + }) + + // Wait for context to be done before returning. + <-ctx.Done() + + dstCollectionMu.Lock() + return dstCollection +} diff --git a/pkg/relayer/miner/gen/gen_fixtures.go b/pkg/relayer/miner/gen/gen_fixtures.go new file mode 100644 index 000000000..87e27bb01 --- /dev/null +++ b/pkg/relayer/miner/gen/gen_fixtures.go @@ -0,0 +1,304 @@ +// NB: ensure this code is never included in any normal builds. +//go:build ignore + +// NB: package MUST be `main` so that it can be run as a binary. +package main + +import ( + "bytes" + "context" + "crypto/rand" + "flag" + "fmt" + "hash" + "log" + "os" + "strings" + "sync" + "time" + + "github.com/pokt-network/poktroll/pkg/observable" + "github.com/pokt-network/poktroll/pkg/observable/channel" + "github.com/pokt-network/poktroll/pkg/relayer" + "github.com/pokt-network/poktroll/pkg/relayer/miner" + "github.com/pokt-network/poktroll/pkg/relayer/protocol" + servicetypes "github.com/pokt-network/poktroll/x/service/types" +) + +const ( + defaultDifficultyBits = 16 + defaultFixtureLimitPerGroup = 5 + defaultRandLength = 16 + defaultOutPath = "relay_fixtures_test.go" +) + +var ( + // flagDifficultyBitsThreshold is the number of leading zero bits that a + // randomized, serialized relay must have to be included in the + // `marshaledMinableRelaysHex` slice which is generated. It is also used as + // the maximum difficulty allowed for relays to be included in the + // `marshaledUnminableRelaysHex` slice. + flagDifficultyBitsThreshold int + + // flagFixtureLimitPerGroup is the number of randomized, serialized relays that will be + // generated for each of `marshaledMinableRelaysHex` and + // `marshaledUnminableRelaysHex`. + flagFixtureLimitPerGroup int + + // flagOut is the path to the generated file. + flagOut string +) + +// TODO_TECHDEBT: remove once marshaling using canonical codec. +type marshalable interface { + Marshal() ([]byte, error) +} + +func init() { + flag.IntVar(&flagDifficultyBitsThreshold, "difficulty-bits-threshold", defaultDifficultyBits, "the number of leading zero bits that a randomized, serialized relay must have to be included in the `marshaledMinableRelaysHex` slice which is generated. It is also used as the maximum difficulty allowed for relays to be included in the `marshaledUnminableRelaysHex` slice.") + flag.IntVar(&flagFixtureLimitPerGroup, "fixture-limit-per-group", defaultFixtureLimitPerGroup, "the number of randomized, serialized relays that will be generated for each of `marshaledMinableRelaysHex` and `marshaledUnminableRelaysHex`.") + flag.StringVar(&flagOut, "out", defaultOutPath, "the path to the generated file.") +} + +// This is utility for generating relay fixtures for testing. It is not intended +// to be used **in/by** any tests but rather is persisted to aid in re-generation +// of relay fixtures should the test requirements change. It generates two slices +// of minedRelays, `marshaledMinableRelaysHex` and `marshaledUnminableRelaysHex`, +// which contain hex encoded strings of serialized relays. The relays in +// `marshaledMinableRelaysHex` have been pre-mined to difficulty 16 by populating +// the signature with random bytes. The relays in `marshaledUnminableRelaysHex` +// have been pre-mined to **exclude** relays with difficulty 16 (or greater). Like +// `marshaledMinableRelaysHex`, this is done by populating the signature with +// random bytes. +// Output file is truncated and overwritten if it already exists. +// +// To regenerate all fixtures, use `make go_fixturegen`; to regenerate only this +// test's fixtures run `go generate ./pkg/relayer/miner/miner_test.go`. +func main() { + flag.Parse() + + ctx, cancelCtx := context.WithCancel(context.Background()) + defer cancelCtx() + + randRelaysObs, errCh := genRandomizedMinedRelayFixtures( + ctx, + defaultRandLength, + miner.DefaultRelayHasher, + ) + exitOnError(errCh) + + outputBuffer := new(bytes.Buffer) + + // Collect the minable relay fixtures into a single string (one relay per line). + marshaledMinableRelaysHex := getMarshaledRelayFmtLines(ctx, randRelaysObs, difficultyGTE) + + // Collect the unminable relay fixtures into a single string (one relay per line). + marshaledUnminableRelaysHex := getMarshaledRelayFmtLines(ctx, randRelaysObs, difficultyLT) + + // Interpolate the collected relay fixtures into the relay fixtures template. + if err := relayFixturesTemplate.Execute( + outputBuffer, + map[string]any{ + "difficultyBitsThreshold": flagDifficultyBitsThreshold, + "MarshaledMinableRelaysHex": marshaledMinableRelaysHex, + "MarshaledUnminableRelaysHex": marshaledUnminableRelaysHex, + }, + ); err != nil { + log.Fatal(err) + } + + // Write the output buffer to the file at flagOut path. + if err := os.WriteFile(flagOut, outputBuffer.Bytes(), 0644); err != nil { + log.Fatal(err) + } +} + +// genRandomizedMinedRelayFixtures returns an observable of mined relays which +// are generated by randomizing the signature of a relay. It generates these mined +// relay fixtures continuously until the context is canceled. It also returns an +// error channel which will receive any error it encounters while generating. +func genRandomizedMinedRelayFixtures( + ctx context.Context, + randLength int, + newHasher func() hash.Hash, +) (observable.Observable[*relayer.MinedRelay], <-chan error) { + var ( + errCh = make(chan error, 1) + randBzObs, randBzPublishCh = channel.NewObservable[*relayer.MinedRelay]() + ) + + go func() { + for { + select { + case <-ctx.Done(): + return + default: + } + + randBz := make([]byte, randLength) + if _, err := rand.Read(randBz); err != nil { + errCh <- err + return + } + + // Populate a relay with the minimally sufficient randomized data. + relay := servicetypes.Relay{ + Req: &servicetypes.RelayRequest{ + Meta: &servicetypes.RelayRequestMetadata{ + Signature: randBz, + }, + Payload: nil, + }, + Res: nil, + } + + // TODO_BLOCKER: use canonical codec. + relayBz, err := relay.Marshal() + if err != nil { + errCh <- err + return + } + + // Hash relay bytes + relayHash, err := hashBytes(newHasher, relayBz) + if err != nil { + errCh <- err + return + } + + randBzPublishCh <- &relayer.MinedRelay{ + Relay: relay, + Bytes: relayBz, + Hash: relayHash, + } + } + }() + + return randBzObs, errCh +} + +// hashBytes hashes the given bytes using the given hasher. +func hashBytes(newHasher func() hash.Hash, relayBz []byte) ([]byte, error) { + hasher := newHasher() + if _, err := hasher.Write(relayBz); err != nil { + return nil, err + } + + return hasher.Sum(nil), nil +} + +// exitOnError exits the program if an error is received on the given error +// channel. +func exitOnError(errCh <-chan error) { + go func() { + for err := range errCh { + log.Fatalf("ERROR: %s", err) + } + }() +} + +// difficultyGTE returns true if the given hash has a difficulty greater than or +// equal to flagDifficultyBitsThreshold. +func difficultyGTE(hash []byte) bool { + return protocol.MustCountDifficultyBits(hash) >= flagDifficultyBitsThreshold +} + +// difficultyLT returns true if the given hash has a difficulty less than +// flagDifficultyBitsThreshold. +func difficultyLT(hash []byte) bool { + return protocol.MustCountDifficultyBits(hash) < flagDifficultyBitsThreshold +} + +// getMarshaledRelayFmtLines performs two map operations followed by a collect. +// The first map filters mined relays from the given observable, skipping when +// shouldAccept is false. This map, and as a result, all downstream observables +// are closed when flagFixtureLimitPerGroup number of relays have been accepted. +// The second map then marshals, hex-encodes, and formats the filtered mined relay. +// Finally, the collect operation collects the formatted mined relays into a slice +// to return. +func getMarshaledRelayFmtLines( + ctx context.Context, + randRelaysObs observable.Observable[*relayer.MinedRelay], + shouldAccept func(hash []byte) bool, +) string { + ctx, cancelFilterMapCollect := context.WithCancel(ctx) + filteredRelaysObs := filterLimitRelays( + ctx, + cancelFilterMapCollect, + flagFixtureLimitPerGroup, + randRelaysObs, + shouldAccept, + ) + + marshaledFilteredRelayLinesObs := channel.Map( + ctx, filteredRelaysObs, + newMapRelayMarshalLineFmt[*relayer.MinedRelay](relayFixtureLineFmt), + ) + + // Collect the filtered relays and return them (as a slice). + marshaledFilteredRelayLines := channel.Collect(ctx, marshaledFilteredRelayLinesObs) + return strings.Join(marshaledFilteredRelayLines, "\n") +} + +// filterLimitRelays maps over the given observable of mined relays, skipping when +// the given shouldAppend function returns false. Once flagFixtureLimitPerGroup +// number of relay fixtures have been mapped, it calls the given cancel function. +func filterLimitRelays( + ctx context.Context, + cancel context.CancelFunc, + limit int, + randRelaysObs observable.Observable[*relayer.MinedRelay], + shouldCollect func(hash []byte) bool, +) observable.Observable[*relayer.MinedRelay] { + var ( + counterMu sync.Mutex + minedRelayAcceptCounter = 0 + minedRelayRejectCounter = 0 + ) + + return channel.Map(ctx, randRelaysObs, + func( + _ context.Context, + minedRelay *relayer.MinedRelay, + ) (_ *relayer.MinedRelay, skip bool) { + counterMu.Lock() + defer counterMu.Unlock() + + // At the start of each iteration, check if the relayCounter has reached + // the limit. If so, cancel the ctx to stop the map operation. + if minedRelayAcceptCounter >= limit { + // Wait a tick for the map to complete as the observable drains + // asynchronously. + time.Sleep(time.Millisecond) + cancel() + return nil, true + } + + // Skip if shouldCollect returns false. + if !shouldCollect(minedRelay.Hash) { + minedRelayRejectCounter++ + return nil, true + } + + minedRelayAcceptCounter++ + return minedRelay, false + }, + ) +} + +// newMapRelayMarshalLineFmt returns a MapFn which formats the given marshalable +// as a hex-encoded string with the given line format string. +func newMapRelayMarshalLineFmt[T marshalable](lineFmt string) channel.MapFn[T, string] { + return func( + _ context.Context, + marsh T, + ) (_ string, skip bool) { + // TODO_BLOCKER: marshal using canonical codec. + minedRelayBz, err := marsh.Marshal() + if err != nil { + log.Fatal(err) + } + + return fmt.Sprintf(lineFmt, minedRelayBz), false + } +} diff --git a/pkg/relayer/miner/gen/template.go b/pkg/relayer/miner/gen/template.go new file mode 100644 index 000000000..5d6ef2802 --- /dev/null +++ b/pkg/relayer/miner/gen/template.go @@ -0,0 +1,37 @@ +package main + +import "text/template" + +var ( + relayFixtureLineFmt = "\t\t\"%x\"," + relayFixturesTemplate = template.Must( + template.New("relay_fixtures_test.go").Parse( + `// DO NOT EDIT: this file was generated by gen/gen_fixtures.go, +// changes made will be overwritten upon regeneration. +// +// To regenerate all fixtures, use make go_fixturegen; to regenerate only this +// test's fixtures run go generate ./pkg/relayer/miner/miner_test.go. +package miner_test + +var ( + // marshaledMinableRelaysHex are the hex encoded strings of serialized + // relayer.MinedRelays which have been pre-mined to difficulty {{.difficultyBitsThreshold}} by + // populating the signature with random bytes. It is intended for use + // in tests. + marshaledMinableRelaysHex = []string{ +{{.MarshaledMinableRelaysHex}} + } + + // marshaledUnminableRelaysHex are the hex encoded strings of serialized + // relayer.MinedRelays which have been pre-mined to **exclude** relays with + // difficulty 2 (or greater). Like marshaledMinableRelaysHex, this is done + // by populating the signature with random bytes. It is intended for use in + // tests. + marshaledUnminableRelaysHex = []string{ +{{.MarshaledUnminableRelaysHex}} + } +) +`, + ), + ) +) diff --git a/pkg/relayer/miner/miner.go b/pkg/relayer/miner/miner.go index 21d706f2f..c3b062a04 100644 --- a/pkg/relayer/miner/miner.go +++ b/pkg/relayer/miner/miner.go @@ -16,8 +16,9 @@ import ( ) var ( - _ relayer.Miner = (*miner)(nil) - defaultRelayHasher = sha256.New + _ relayer.Miner = (*miner)(nil) + // TODO_TECHDEBT(@h5law): Retrieve the relay hasher mechanism from the `smt` repo. + DefaultRelayHasher = sha256.New // TODO_BLOCKER: query on-chain governance params once available. // Setting this to 0 to effectively disables mining for now. // I.e., all relays are added to the tree. @@ -28,14 +29,18 @@ var ( // difficulty of each, finally publishing those with sufficient difficulty to // minedRelayObs as they are applicable for relay volume. // +// Available options: +// - WithDifficulty +// // TODO_BLOCKER: The relay hashing and relay difficulty mechanisms & values must come +// from on-chain. type miner struct { // relayHasher is a function which returns a hash.Hash interfact type. It is // used to hash serialized relays to measure their mining difficulty. relayHasher func() hash.Hash - // relayDifficulty is the minimum difficulty that a relay must have to be + // relayDifficultyBits is the minimum difficulty that a relay must have to be // volume / reward applicable. - relayDifficulty int + relayDifficultyBits int } // NewMiner creates a new miner from the given dependencies and options. It @@ -81,7 +86,11 @@ func (mnr *miner) MinedRelays( // the default hasherConstructor if not. func (mnr *miner) setDefaults() { if mnr.relayHasher == nil { - mnr.relayHasher = defaultRelayHasher + mnr.relayHasher = DefaultRelayHasher + } + + if mnr.relayDifficultyBits == 0 { + mnr.relayDifficultyBits = defaultRelayDifficultyBits } } @@ -94,6 +103,7 @@ func (mnr *miner) mapMineRelay( _ context.Context, relay *servicetypes.Relay, ) (_ either.Either[*relayer.MinedRelay], skip bool) { + // TODO_BLOCKER: marshal using canonical codec. relayBz, err := relay.Marshal() if err != nil { return either.Error[*relayer.MinedRelay](err), false @@ -107,7 +117,7 @@ func (mnr *miner) mapMineRelay( relayHash := mnr.hash(relayBz) // The relay IS NOT volume / reward applicable - if protocol.MustCountDifficultyBits(relayHash) < defaultRelayDifficultyBits { + if protocol.MustCountDifficultyBits(relayHash) < mnr.relayDifficultyBits { return either.Success[*relayer.MinedRelay](nil), true } diff --git a/pkg/relayer/miner/miner_test.go b/pkg/relayer/miner/miner_test.go index c362005bd..c6958616d 100644 --- a/pkg/relayer/miner/miner_test.go +++ b/pkg/relayer/miner/miner_test.go @@ -1,10 +1,145 @@ +//go:generate go run gen/gen_fixtures.go gen/template.go +// (see: https://pkg.go.dev/cmd/go/internal/generate) +// (see: https://go.googlesource.com/proposal/+/refs/heads/master/design/go-generate.md) + package miner_test import ( + "context" + "encoding/hex" + "hash" + "sync" "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/pokt-network/poktroll/pkg/observable/channel" + "github.com/pokt-network/poktroll/pkg/relayer" + "github.com/pokt-network/poktroll/pkg/relayer/miner" + "github.com/pokt-network/poktroll/testutil/testrelayer" + servicetypes "github.com/pokt-network/poktroll/x/service/types" ) -// TODO_TECHDEBT(@bryanchriswhite): add all the test coverage... -func TestNewMiner(t *testing.T) { - t.Skip("TODO_TECHDEBT(@bryanchriswhite): add all the test coverage...") +const testDifficulty = 16 + +// TestMiner_MinedRelays constructs an observable of mined relays, through which +// it pipes pre-mined relay fixtures. It asserts that the observable only emits +// mined relays with difficulty equal to or greater than testDifficulty. +// +// To regenerate all fixtures, use `make go_fixturegen`; to regenerate only this +// test's fixtures run `go generate ./pkg/relayer/miner/miner_test.go`. +func TestMiner_MinedRelays(t *testing.T) { + var ( + minedRelayCounter = 0 + ctx = context.Background() + actualMinedRelaysMu sync.Mutex + actualMinedRelays []*relayer.MinedRelay + mockRelaysObs, relaysFixturePublishCh = channel.NewObservable[*servicetypes.Relay]() + expectedMinedRelays = unmarshalHexMinedRelays( + t, marshaledMinableRelaysHex, + miner.DefaultRelayHasher, + ) + ) + + mnr, err := miner.NewMiner(miner.WithDifficulty(testDifficulty)) + require.NoError(t, err) + + minedRelays := mnr.MinedRelays(ctx, mockRelaysObs) + minedRelaysObserver := minedRelays.Subscribe(ctx) + + // Subscribe to the mined relays observable and append them to the + // actualMinedRelays slice asynchronously. + go func() { + for minedRelay := range minedRelaysObserver.Ch() { + actualMinedRelaysMu.Lock() + actualMinedRelays = append(actualMinedRelays, minedRelay) + minedRelayCounter++ + actualMinedRelaysMu.Unlock() + } + }() + + // Publish unminable relay fixtures to the mock relays observable. + publishRelayFixtures(t, marshaledUnminableRelaysHex, relaysFixturePublishCh) + time.Sleep(time.Millisecond) + + // Assert that no unminable relay fixtures were published to minedRelays. + actualMinedRelaysMu.Lock() + require.Empty(t, actualMinedRelays) + actualMinedRelaysMu.Unlock() + + // Publish minable relay fixtures to the relay fixtures observable. + publishRelayFixtures(t, marshaledMinableRelaysHex, relaysFixturePublishCh) + time.Sleep(time.Millisecond) + + // Assert that all minable relay fixtures were published to minedRelays. + actualMinedRelaysMu.Lock() + require.EqualValues(t, expectedMinedRelays, actualMinedRelays) + actualMinedRelaysMu.Unlock() +} + +func publishRelayFixtures( + t *testing.T, + marshalledRelaysHex []string, + mockRelaysPublishCh chan<- *servicetypes.Relay, +) { + t.Helper() + + for _, marshalledRelayHex := range marshalledRelaysHex { + relay := unmarshalHexRelay(t, marshalledRelayHex) + + mockRelaysPublishCh <- relay + } +} + +func unmarshalHexRelay( + t *testing.T, + marshalledHexRelay string, +) *servicetypes.Relay { + t.Helper() + + relayBz, err := hex.DecodeString(marshalledHexRelay) + require.NoError(t, err) + + var relay servicetypes.Relay + err = relay.Unmarshal(relayBz) + require.NoError(t, err) + + return &relay +} + +func unmarshalHexMinedRelays( + t *testing.T, + marshalledHexMinedRelays []string, + newHasher func() hash.Hash, +) (relays []*relayer.MinedRelay) { + t.Helper() + + for _, marshalledRelayHex := range marshalledHexMinedRelays { + relays = append(relays, unmarshalHexMinedRelay(t, marshalledRelayHex, newHasher)) + } + return relays +} + +func unmarshalHexMinedRelay( + t *testing.T, + marshalledHexMinedRelay string, + newHasher func() hash.Hash, +) *relayer.MinedRelay { + t.Helper() + + relayBz, err := hex.DecodeString(marshalledHexMinedRelay) + require.NoError(t, err) + + var relay servicetypes.Relay + err = relay.Unmarshal(relayBz) + require.NoError(t, err) + + relayHashBz := testrelayer.HashBytes(t, newHasher, relayBz) + + return &relayer.MinedRelay{ + Relay: relay, + Bytes: relayBz, + Hash: relayHashBz, + } } diff --git a/pkg/relayer/miner/options.go b/pkg/relayer/miner/options.go new file mode 100644 index 000000000..fae783d85 --- /dev/null +++ b/pkg/relayer/miner/options.go @@ -0,0 +1,11 @@ +package miner + +import "github.com/pokt-network/poktroll/pkg/relayer" + +// WithDifficulty sets the difficulty of the miner, where difficultyBytes is the +// minimum number of leading zero bytes. +func WithDifficulty(difficultyBits int) relayer.MinerOption { + return func(mnr relayer.Miner) { + mnr.(*miner).relayDifficultyBits = difficultyBits + } +} diff --git a/pkg/relayer/miner/relay_fixtures_test.go b/pkg/relayer/miner/relay_fixtures_test.go new file mode 100644 index 000000000..f3163e255 --- /dev/null +++ b/pkg/relayer/miner/relay_fixtures_test.go @@ -0,0 +1,33 @@ +// DO NOT EDIT: this file was generated by gen/gen_fixtures.go, +// changes made will be overwritten upon regeneration. +// +// To regenerate all fixtures, use make go_fixturegen; to regenerate only this +// test's fixtures run go generate ./pkg/relayer/miner/miner_test.go. +package miner_test + +var ( + // marshaledMinableRelaysHex are the hex encoded strings of serialized + // relayer.MinedRelays which have been pre-mined to difficulty 16 by + // populating the signature with random bytes. It is intended for use + // in tests. + marshaledMinableRelaysHex = []string{ + "0a140a121210bffa0b5c3f03c71f93d7611af54ba80b", + "0a140a1212106655cb3dccaada7837b094962d65426d", + "0a140a121210b19bcf19e96cb58bb37bae3a1769fc08", + "0a140a121210146014db743850694ce211403e91c451", + "0a140a12121016da74aea084a4d40aebf61d876809d4", + } + + // marshaledUnminableRelaysHex are the hex encoded strings of serialized + // relayer.MinedRelays which have been pre-mined to **exclude** relays with + // difficulty 2 (or greater). Like marshaledMinableRelaysHex, this is done + // by populating the signature with random bytes. It is intended for use in + // tests. + marshaledUnminableRelaysHex = []string{ + "0a140a12121070b059e32e4149bcded39d8eb0186fce", + "0a140a121210f5bb373e3d6cabe04675083ac4ffc36e", + "0a140a1212104ae2b0539ecd82ec56bf23b276d543c1", + "0a140a121210d4238199f9e52347b46d060c477b464e", + "0a140a1212103118a0689c4eb883e384d12378bc61e2", + } +) diff --git a/pkg/relayer/session/session.go b/pkg/relayer/session/session.go index 3316d28c9..8367552c4 100644 --- a/pkg/relayer/session/session.go +++ b/pkg/relayer/session/session.go @@ -237,6 +237,8 @@ func (rs *relayerSessionsManager) mapAddMinedRelayToSessionTree( rs.sessionsTreesMu.Lock() defer rs.sessionsTreesMu.Unlock() // ensure the session tree exists for this relay + // TODO_CONSIDERATION: if we get the session header from the response, there + // is no possibility that we forgot to hydrate it (i.e. blindly trust the client). sessionHeader := relay.GetReq().GetMeta().GetSessionHeader() smst, err := rs.ensureSessionTree(sessionHeader) if err != nil { diff --git a/pkg/relayer/session/session_test.go b/pkg/relayer/session/session_test.go index 9efb49710..67e3a1214 100644 --- a/pkg/relayer/session/session_test.go +++ b/pkg/relayer/session/session_test.go @@ -1,3 +1,114 @@ package session_test -// TODO: Add tests to the relayerSessionsManager logic +import ( + "context" + "testing" + "time" + + "cosmossdk.io/depinject" + "github.com/stretchr/testify/require" + + "github.com/pokt-network/poktroll/pkg/client" + "github.com/pokt-network/poktroll/pkg/observable/channel" + "github.com/pokt-network/poktroll/pkg/relayer" + "github.com/pokt-network/poktroll/pkg/relayer/miner" + "github.com/pokt-network/poktroll/pkg/relayer/session" + "github.com/pokt-network/poktroll/testutil/testclient/testblock" + "github.com/pokt-network/poktroll/testutil/testclient/testsupplier" + "github.com/pokt-network/poktroll/testutil/testrelayer" + servicetypes "github.com/pokt-network/poktroll/x/service/types" + sessiontypes "github.com/pokt-network/poktroll/x/session/types" +) + +func TestRelayerSessionsManager_Start(t *testing.T) { + const ( + sessionStartHeight = 1 + sessionEndHeight = 2 + ) + var ( + zeroByteSlice = []byte{0} + ctx = context.Background() + ) + + // Set up dependencies. + blocksObs, blockPublishCh := channel.NewReplayObservable[client.Block](ctx, 1) + blockClient := testblock.NewAnyTimesCommittedBlocksSequenceBlockClient(t, blocksObs) + supplierClient := testsupplier.NewOneTimeClaimProofSupplierClient(ctx, t) + + deps := depinject.Supply(blockClient, supplierClient) + storesDirectoryOpt := testrelayer.WithTempStoresDirectory(t) + + // Create a new relayer sessions manager. + relayerSessionsManager, err := session.NewRelayerSessions(ctx, deps, storesDirectoryOpt) + require.NoError(t, err) + require.NotNil(t, relayerSessionsManager) + + // Pass a mined relays observable via InsertRelays. + mrObs, minedRelaysPublishCh := channel.NewObservable[*relayer.MinedRelay]() + minedRelaysObs := relayer.MinedRelaysObservable(mrObs) + relayerSessionsManager.InsertRelays(minedRelaysObs) + + // Start the relayer sessions manager. + relayerSessionsManager.Start(ctx) + + // Publish a mined relay to the minedRelaysPublishCh to insert into the session tree. + minedRelay := newMinedRelay(t, sessionStartHeight, sessionEndHeight) + minedRelaysPublishCh <- minedRelay + + // Wait a tick to allow the relayer sessions manager to process asynchronously. + // It should have created a session tree for the relay. + time.Sleep(10 * time.Millisecond) + + // Publish a block to the blockPublishCh to simulate non-actionable blocks. + noopBlock := testblock.NewAnyTimesBlock(t, zeroByteSlice, sessionStartHeight) + blockPublishCh <- noopBlock + + // Publish a block to the blockPublishCh to trigger claim creation for the session. + // TODO_TECHDEBT: assumes claiming at sessionEndHeight is valid. This will + // likely change in future work. + triggerClaimBlock := testblock.NewAnyTimesBlock(t, zeroByteSlice, sessionEndHeight) + blockPublishCh <- triggerClaimBlock + + // TODO_IMPROVE: ensure correctness of persisted session trees here. + + // Publish a block to the blockPublishCh to trigger proof submission for the session. + // TODO_TECHDEBT: assumes proving at sessionEndHeight is valid. This will + // likely change in future work. + triggerProofBlock := testblock.NewAnyTimesBlock(t, zeroByteSlice, sessionEndHeight+1) + blockPublishCh <- triggerProofBlock + + // Wait a tick to allow the relayer sessions manager to process asynchronously. + time.Sleep(250 * time.Millisecond) +} + +// newMinedRelay returns a new mined relay with the given session start and end +// heights on the session header, and the bytes and hash fields populated. +func newMinedRelay( + t *testing.T, + sessionStartHeight int64, + sessionEndHeight int64, +) *relayer.MinedRelay { + relay := servicetypes.Relay{ + Req: &servicetypes.RelayRequest{ + Meta: &servicetypes.RelayRequestMetadata{ + SessionHeader: &sessiontypes.SessionHeader{ + SessionStartBlockHeight: sessionStartHeight, + SessionEndBlockHeight: sessionEndHeight, + }, + }, + }, + Res: &servicetypes.RelayResponse{}, + } + + // TODO_BLOCKER: use canonical codec to serialize the relay + relayBz, err := relay.Marshal() + require.NoError(t, err) + + relayHash := testrelayer.HashBytes(t, miner.DefaultRelayHasher, relayBz) + + return &relayer.MinedRelay{ + Relay: relay, + Bytes: relayBz, + Hash: relayHash, + } +} diff --git a/testutil/testclient/testblock/client.go b/testutil/testclient/testblock/client.go index 7fc1a0341..dbeed8427 100644 --- a/testutil/testclient/testblock/client.go +++ b/testutil/testclient/testblock/client.go @@ -8,6 +8,7 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" + "github.com/pokt-network/poktroll/pkg/observable" "github.com/pokt-network/poktroll/testutil/mockclient" "github.com/pokt-network/poktroll/pkg/client" @@ -32,6 +33,31 @@ func NewLocalnetClient(ctx context.Context, t *testing.T) client.BlockClient { return bClient } +// NewAnyTimesCommittedBlocksSequenceBlockClient creates a new mock BlockClient. +// This mock BlockClient will expect any number of calls to CommittedBlocksSequence, +// and when that call is made, it returns the given BlocksObservable. +func NewAnyTimesCommittedBlocksSequenceBlockClient( + t *testing.T, + blocksObs observable.Observable[client.Block], +) *mockclient.MockBlockClient { + t.Helper() + + // Create a mock for the block client which expects the LatestBlock method to be called any number of times. + blockClientMock := NewAnyTimeLatestBlockBlockClient(t, nil, 0) + + // Set up the mock expectation for the CommittedBlocksSequence method. When + // the method is called, it returns a new replay observable that publishes + // blocks sent on the given blocksPublishCh. + blockClientMock.EXPECT(). + CommittedBlocksSequence( + gomock.AssignableToTypeOf(context.Background()), + ). + Return(blocksObs). + AnyTimes() + + return blockClientMock +} + // NewOneTimeCommittedBlocksSequenceBlockClient creates a new mock BlockClient. // This mock BlockClient will expect a call to CommittedBlocksSequence, and // when that call is made, it returns a new BlocksObservable that is notified of diff --git a/testutil/testclient/testsupplier/client.go b/testutil/testclient/testsupplier/client.go index f5ee73969..841cfc024 100644 --- a/testutil/testclient/testsupplier/client.go +++ b/testutil/testclient/testsupplier/client.go @@ -1,15 +1,20 @@ package testsupplier import ( + "context" "testing" "cosmossdk.io/depinject" + "github.com/golang/mock/gomock" + "github.com/pokt-network/smt" "github.com/stretchr/testify/require" "github.com/pokt-network/poktroll/pkg/client" "github.com/pokt-network/poktroll/pkg/client/supplier" "github.com/pokt-network/poktroll/pkg/client/tx" + "github.com/pokt-network/poktroll/testutil/mockclient" "github.com/pokt-network/poktroll/testutil/testclient/testtx" + sessiontypes "github.com/pokt-network/poktroll/x/session/types" ) // NewLocalnetClient creates and returns a new supplier client that connects to @@ -35,3 +40,32 @@ func NewLocalnetClient( require.NoError(t, err) return supplierClient } + +func NewOneTimeClaimProofSupplierClient( + ctx context.Context, + t *testing.T, +) *mockclient.MockSupplierClient { + t.Helper() + + ctrl := gomock.NewController(t) + supplierClientMock := mockclient.NewMockSupplierClient(ctrl) + supplierClientMock.EXPECT(). + CreateClaim( + gomock.Eq(ctx), + gomock.AssignableToTypeOf(sessiontypes.SessionHeader{}), + gomock.AssignableToTypeOf([]byte{}), + ). + Return(nil). + Times(1) + + supplierClientMock.EXPECT(). + SubmitProof( + gomock.Eq(ctx), + gomock.AssignableToTypeOf(sessiontypes.SessionHeader{}), + gomock.AssignableToTypeOf((*smt.SparseMerkleClosestProof)(nil)), + ). + Return(nil). + Times(1) + + return supplierClientMock +} diff --git a/testutil/testrelayer/hash.go b/testutil/testrelayer/hash.go new file mode 100644 index 000000000..d8c78e64e --- /dev/null +++ b/testutil/testrelayer/hash.go @@ -0,0 +1,16 @@ +package testrelayer + +import ( + "hash" + "testing" + + "github.com/stretchr/testify/require" +) + +// TODO_TECHDEBT(@h5law): Retrieve the relay hasher mechanism from the `smt` repo. +func HashBytes(t *testing.T, newHasher func() hash.Hash, relayBz []byte) []byte { + hasher := newHasher() + _, err := hasher.Write(relayBz) + require.NoError(t, err) + return hasher.Sum(nil) +} diff --git a/testutil/testrelayer/options.go b/testutil/testrelayer/options.go new file mode 100644 index 000000000..a63518293 --- /dev/null +++ b/testutil/testrelayer/options.go @@ -0,0 +1,23 @@ +package testrelayer + +import ( + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/pokt-network/poktroll/pkg/relayer" + "github.com/pokt-network/poktroll/pkg/relayer/session" +) + +func WithTempStoresDirectory(t *testing.T) relayer.RelayerSessionsManagerOption { + tmpDirPattern := fmt.Sprintf("%s_smt_kvstore", t.Name()) + tmpStoresDir, err := os.MkdirTemp("", tmpDirPattern) + require.NoError(t, err) + + // Delete all temporary files and directories created by the test on completion. + t.Cleanup(func() { _ = os.RemoveAll(tmpStoresDir) }) + + return session.WithStoresDirectory(tmpStoresDir) +} diff --git a/x/service/types/relay.go b/x/service/types/relay.go index c7b2a1894..211e644e9 100644 --- a/x/service/types/relay.go +++ b/x/service/types/relay.go @@ -21,3 +21,11 @@ func (res RelayResponse) GetSignableBytes() ([]byte, error) { // return the marshaled message return res.Marshal() } + +func (res *RelayResponse) ValidateBasic() error { + // TODO_FUTURE: if a client gets a response with an invalid/incomplete + // SessionHeader, consider sending an on-chain challenge, lowering their + // QoS, or other future work. + + return nil +} From 6a2139284b03805a089083b23d9b07f5dd1ca638 Mon Sep 17 00:00:00 2001 From: Bryan White Date: Wed, 22 Nov 2023 23:01:20 +0100 Subject: [PATCH 13/16] chore: omitted improvments to #191 (#214) --- pkg/observable/channel/collect.go | 2 ++ pkg/relayer/miner/gen/template.go | 2 +- pkg/relayer/miner/relay_fixtures_test.go | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/observable/channel/collect.go b/pkg/observable/channel/collect.go index 4a8e1e22f..edbc545cb 100644 --- a/pkg/observable/channel/collect.go +++ b/pkg/observable/channel/collect.go @@ -16,6 +16,7 @@ func Collect[V any]( srcObservable observable.Observable[V], ) (dstCollection []V) { var dstCollectionMu sync.Mutex + // Defer unlocking as lock is acquired immediately before returning. defer dstCollectionMu.Unlock() ForEach(ctx, srcObservable, func(ctx context.Context, src V) { @@ -27,6 +28,7 @@ func Collect[V any]( // Wait for context to be done before returning. <-ctx.Done() + // Lock to read from dstCollection in return. dstCollectionMu.Lock() return dstCollection } diff --git a/pkg/relayer/miner/gen/template.go b/pkg/relayer/miner/gen/template.go index 5d6ef2802..8eb32c53b 100644 --- a/pkg/relayer/miner/gen/template.go +++ b/pkg/relayer/miner/gen/template.go @@ -24,7 +24,7 @@ var ( // marshaledUnminableRelaysHex are the hex encoded strings of serialized // relayer.MinedRelays which have been pre-mined to **exclude** relays with - // difficulty 2 (or greater). Like marshaledMinableRelaysHex, this is done + // difficulty {{.difficultyBitsThreshold}} (or greater). Like marshaledMinableRelaysHex, this is done // by populating the signature with random bytes. It is intended for use in // tests. marshaledUnminableRelaysHex = []string{ diff --git a/pkg/relayer/miner/relay_fixtures_test.go b/pkg/relayer/miner/relay_fixtures_test.go index f3163e255..7a8042fde 100644 --- a/pkg/relayer/miner/relay_fixtures_test.go +++ b/pkg/relayer/miner/relay_fixtures_test.go @@ -20,7 +20,7 @@ var ( // marshaledUnminableRelaysHex are the hex encoded strings of serialized // relayer.MinedRelays which have been pre-mined to **exclude** relays with - // difficulty 2 (or greater). Like marshaledMinableRelaysHex, this is done + // difficulty 16 (or greater). Like marshaledMinableRelaysHex, this is done // by populating the signature with random bytes. It is intended for use in // tests. marshaledUnminableRelaysHex = []string{ From ef7afb55627dcf7bdd72c086d04e3666b0034604 Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Wed, 22 Nov 2023 16:13:33 -0800 Subject: [PATCH 14/16] Follow up on review comments --- pkg/relayer/miner/relay_fixtures_test.go | 20 ++++++++++---------- proto/pocket/supplier/genesis.proto | 2 -- x/supplier/client/cli/query_proof.go | 1 + x/supplier/keeper/proof.go | 4 ++-- x/supplier/keeper/proof_test.go | 10 +++++----- x/supplier/keeper/query_proof_test.go | 4 ++-- x/supplier/types/key_proof.go | 1 + 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/pkg/relayer/miner/relay_fixtures_test.go b/pkg/relayer/miner/relay_fixtures_test.go index 7a8042fde..d054334e6 100644 --- a/pkg/relayer/miner/relay_fixtures_test.go +++ b/pkg/relayer/miner/relay_fixtures_test.go @@ -11,11 +11,11 @@ var ( // populating the signature with random bytes. It is intended for use // in tests. marshaledMinableRelaysHex = []string{ - "0a140a121210bffa0b5c3f03c71f93d7611af54ba80b", - "0a140a1212106655cb3dccaada7837b094962d65426d", - "0a140a121210b19bcf19e96cb58bb37bae3a1769fc08", - "0a140a121210146014db743850694ce211403e91c451", - "0a140a12121016da74aea084a4d40aebf61d876809d4", + "0a140a121210e64c3c38db4c40caf4a8854b8d664e25", + "0a140a121210455ce459696f697015ce99820b335e9f", + "0a140a1212107c3e2e511fd8534e52ed48d728160b46", + "0a140a12121064af21da207ce228de794858c9780ca7", + "0a140a121210d8a3ec11ccb4c0181fa416a6f0222416", } // marshaledUnminableRelaysHex are the hex encoded strings of serialized @@ -24,10 +24,10 @@ var ( // by populating the signature with random bytes. It is intended for use in // tests. marshaledUnminableRelaysHex = []string{ - "0a140a12121070b059e32e4149bcded39d8eb0186fce", - "0a140a121210f5bb373e3d6cabe04675083ac4ffc36e", - "0a140a1212104ae2b0539ecd82ec56bf23b276d543c1", - "0a140a121210d4238199f9e52347b46d060c477b464e", - "0a140a1212103118a0689c4eb883e384d12378bc61e2", + "0a140a12121037591bc113241a798fd9f1a736119b14", + "0a140a121210f7cda9e92e0736b388359008246496e7", + "0a140a1212101f67c148fb1a4c9c754f97685ba8645d", + "0a140a121210192c9dc85976add860245e33a51660eb", + "0a140a12121017d9cb1ca9ca7be354dbe8f8a6951bcd", } ) diff --git a/proto/pocket/supplier/genesis.proto b/proto/pocket/supplier/genesis.proto index ae8dfde4b..5bba7baea 100644 --- a/proto/pocket/supplier/genesis.proto +++ b/proto/pocket/supplier/genesis.proto @@ -5,8 +5,6 @@ package pocket.supplier; import "gogoproto/gogo.proto"; import "pocket/supplier/params.proto"; import "pocket/shared/supplier.proto"; -import "pocket/supplier/claim.proto"; -import "pocket/supplier/proof.proto"; option go_package = "github.com/pokt-network/poktroll/x/supplier/types"; diff --git a/x/supplier/client/cli/query_proof.go b/x/supplier/client/cli/query_proof.go index 0e885b53c..e36d0f13f 100644 --- a/x/supplier/client/cli/query_proof.go +++ b/x/supplier/client/cli/query_proof.go @@ -44,6 +44,7 @@ func CmdListProof() *cobra.Command { return cmd } +// TODO_UPNEXT(@Olshansk): Remove the dependency on index which was part of the default scaffolding behaviour func CmdShowProof() *cobra.Command { cmd := &cobra.Command{ Use: "show-proof ", diff --git a/x/supplier/keeper/proof.go b/x/supplier/keeper/proof.go index 25c1bd52d..bb9188a98 100644 --- a/x/supplier/keeper/proof.go +++ b/x/supplier/keeper/proof.go @@ -47,8 +47,8 @@ func (k Keeper) RemoveProof( )) } -// GetAllProof returns all proof -func (k Keeper) GetAllProof(ctx sdk.Context) (list []types.Proof) { +// GetAllProofs returns all proof +func (k Keeper) GetAllProofs(ctx sdk.Context) (list []types.Proof) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefix(types.ProofKeyPrefix)) iterator := sdk.KVStorePrefixIterator(store, []byte{}) diff --git a/x/supplier/keeper/proof_test.go b/x/supplier/keeper/proof_test.go index 6f8c60a56..c3fb4e753 100644 --- a/x/supplier/keeper/proof_test.go +++ b/x/supplier/keeper/proof_test.go @@ -15,7 +15,7 @@ import ( // Prevent strconv unused error var _ = strconv.IntSize -func createNProof(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.Proof { +func createNProofs(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.Proof { items := make([]types.Proof, n) for i := range items { items[i].Index = strconv.Itoa(i) @@ -27,7 +27,7 @@ func createNProof(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.Proof { func TestProofGet(t *testing.T) { keeper, ctx := keepertest.SupplierKeeper(t) - items := createNProof(keeper, ctx, 10) + items := createNProofs(keeper, ctx, 10) for _, item := range items { rst, found := keeper.GetProof(ctx, item.Index, @@ -41,7 +41,7 @@ func TestProofGet(t *testing.T) { } func TestProofRemove(t *testing.T) { keeper, ctx := keepertest.SupplierKeeper(t) - items := createNProof(keeper, ctx, 10) + items := createNProofs(keeper, ctx, 10) for _, item := range items { keeper.RemoveProof(ctx, item.Index, @@ -55,9 +55,9 @@ func TestProofRemove(t *testing.T) { func TestProofGetAll(t *testing.T) { keeper, ctx := keepertest.SupplierKeeper(t) - items := createNProof(keeper, ctx, 10) + items := createNProofs(keeper, ctx, 10) require.ElementsMatch(t, nullify.Fill(items), - nullify.Fill(keeper.GetAllProof(ctx)), + nullify.Fill(keeper.GetAllProofs(ctx)), ) } diff --git a/x/supplier/keeper/query_proof_test.go b/x/supplier/keeper/query_proof_test.go index e1084becf..d932b43cb 100644 --- a/x/supplier/keeper/query_proof_test.go +++ b/x/supplier/keeper/query_proof_test.go @@ -20,7 +20,7 @@ var _ = strconv.IntSize func TestProofQuerySingle(t *testing.T) { keeper, ctx := keepertest.SupplierKeeper(t) wctx := sdk.WrapSDKContext(ctx) - msgs := createNProof(keeper, ctx, 2) + msgs := createNProofs(keeper, ctx, 2) tests := []struct { desc string request *types.QueryGetProofRequest @@ -72,7 +72,7 @@ func TestProofQuerySingle(t *testing.T) { func TestProofQueryPaginated(t *testing.T) { keeper, ctx := keepertest.SupplierKeeper(t) wctx := sdk.WrapSDKContext(ctx) - msgs := createNProof(keeper, ctx, 5) + msgs := createNProofs(keeper, ctx, 5) request := func(next []byte, offset, limit uint64, total bool) *types.QueryAllProofsRequest { return &types.QueryAllProofsRequest{ diff --git a/x/supplier/types/key_proof.go b/x/supplier/types/key_proof.go index d3d6d791e..6307f4ccb 100644 --- a/x/supplier/types/key_proof.go +++ b/x/supplier/types/key_proof.go @@ -10,6 +10,7 @@ const ( ) // ProofKey returns the store key to retrieve a Proof from the index fields +// TODO_UPNEXT(@Olshansk): Implement a similar indexing strategy for Proofs as we do for Claims func ProofKey( index string, ) []byte { From 7dfd86ccf48f1d2a58a38bbf92e644d3e17018cb Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Wed, 22 Nov 2023 16:47:54 -0800 Subject: [PATCH 15/16] A couple more nites --- pkg/relayer/miner/relay_fixtures_test.go | 20 ++++++++++---------- x/supplier/types/codec.go | 5 ----- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/pkg/relayer/miner/relay_fixtures_test.go b/pkg/relayer/miner/relay_fixtures_test.go index d054334e6..79e6be371 100644 --- a/pkg/relayer/miner/relay_fixtures_test.go +++ b/pkg/relayer/miner/relay_fixtures_test.go @@ -11,11 +11,11 @@ var ( // populating the signature with random bytes. It is intended for use // in tests. marshaledMinableRelaysHex = []string{ - "0a140a121210e64c3c38db4c40caf4a8854b8d664e25", - "0a140a121210455ce459696f697015ce99820b335e9f", - "0a140a1212107c3e2e511fd8534e52ed48d728160b46", - "0a140a12121064af21da207ce228de794858c9780ca7", - "0a140a121210d8a3ec11ccb4c0181fa416a6f0222416", + "0a140a121210225096c97ef68ee5f66863002c0fc124", + "0a140a1212103b4d48629c66cc151dcb2d30e97a91d1", + "0a140a121210f44ddc930e988c4f811c770c141c721c", + "0a140a121210aeed5b008ca198752f3d7bab8b8f2472", + "0a140a121210ff0fc27ebe20263b16c8289e7b57583e", } // marshaledUnminableRelaysHex are the hex encoded strings of serialized @@ -24,10 +24,10 @@ var ( // by populating the signature with random bytes. It is intended for use in // tests. marshaledUnminableRelaysHex = []string{ - "0a140a12121037591bc113241a798fd9f1a736119b14", - "0a140a121210f7cda9e92e0736b388359008246496e7", - "0a140a1212101f67c148fb1a4c9c754f97685ba8645d", - "0a140a121210192c9dc85976add860245e33a51660eb", - "0a140a12121017d9cb1ca9ca7be354dbe8f8a6951bcd", + "0a140a12121070248ca76729ed1ab6c9b1e574d4e37b", + "0a140a1212100da5b8d0fac76164d65ac2831df8a3bf", + "0a140a1212104d5ae8dfc930ba7b19421e975c6e9dff", + "0a140a1212105d3b3aaee4e8c472b442300f54326027", + "0a140a1212109464ef6aa8164f74138d8b03671052af", } ) diff --git a/x/supplier/types/codec.go b/x/supplier/types/codec.go index 41d74aa3f..5dc59bf31 100644 --- a/x/supplier/types/codec.go +++ b/x/supplier/types/codec.go @@ -27,11 +27,6 @@ func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { &MsgSubmitProof{}, ) // this line is used by starport scaffolding # 3 - - msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) - - msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) - msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) } From bdf0ee9c7e5e64ae36398791a1f56770e1e308ef Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Wed, 22 Nov 2023 16:49:22 -0800 Subject: [PATCH 16/16] Manually ran goimports -w -local github.com/pokt-network/poktroll on a couple of files --- go.mod | 4 ++-- x/supplier/genesis_test.go | 3 ++- x/supplier/keeper/msg_server_test.go | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 08e7ca4f9..4784e5ee9 100644 --- a/go.mod +++ b/go.mod @@ -24,6 +24,7 @@ require ( github.com/athanorlabs/go-dleq v0.1.0 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 @@ -44,6 +45,7 @@ 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 ) @@ -87,7 +89,6 @@ 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 @@ -283,7 +284,6 @@ 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/x/supplier/genesis_test.go b/x/supplier/genesis_test.go index 927c7a704..ba9b521f8 100644 --- a/x/supplier/genesis_test.go +++ b/x/supplier/genesis_test.go @@ -4,13 +4,14 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + keepertest "github.com/pokt-network/poktroll/testutil/keeper" "github.com/pokt-network/poktroll/testutil/nullify" "github.com/pokt-network/poktroll/testutil/sample" sharedtypes "github.com/pokt-network/poktroll/x/shared/types" "github.com/pokt-network/poktroll/x/supplier" "github.com/pokt-network/poktroll/x/supplier/types" - "github.com/stretchr/testify/require" ) // Please see `x/supplier/types/genesis_test.go` for extensive tests related to the validity of the genesis state. diff --git a/x/supplier/keeper/msg_server_test.go b/x/supplier/keeper/msg_server_test.go index 3a5927aec..7e4d01f27 100644 --- a/x/supplier/keeper/msg_server_test.go +++ b/x/supplier/keeper/msg_server_test.go @@ -5,10 +5,11 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + keepertest "github.com/pokt-network/poktroll/testutil/keeper" "github.com/pokt-network/poktroll/x/supplier/keeper" "github.com/pokt-network/poktroll/x/supplier/types" - "github.com/stretchr/testify/require" ) func setupMsgServer(t testing.TB) (types.MsgServer, context.Context) {