diff --git a/proto/canine_chain/storage/query.proto b/proto/canine_chain/storage/query.proto index 45aac8ced..b32afeae8 100644 --- a/proto/canine_chain/storage/query.proto +++ b/proto/canine_chain/storage/query.proto @@ -58,6 +58,13 @@ service Query { "/jackal/canine-chain/storage/files/merkle/{merkle}"; } + // Queries a list of File items owned by a specific address. + rpc AllFilesByOwner(QueryAllFilesByOwner) + returns (QueryAllFilesByOwnerResponse) { + option (google.api.http).get = + "/jackal/canine-chain/storage/files/owner/{owner}"; + } + // Queries a Proof by provider_address, merkle, owner, and start. rpc Proof(QueryProof) returns (QueryProofResponse) { diff --git a/x/storage/keeper/grpc_query_active_deals.go b/x/storage/keeper/grpc_query_active_deals.go index 07181afbb..54f7f9c30 100644 --- a/x/storage/keeper/grpc_query_active_deals.go +++ b/x/storage/keeper/grpc_query_active_deals.go @@ -12,6 +12,58 @@ import ( "google.golang.org/grpc/status" ) +// paginationParams holds extracted pagination parameters +type paginationParams struct { + reverse bool + limit uint64 + offset uint64 +} + +// extractPaginationParams extracts pagination parameters with defaults +func extractPaginationParams(pagination *query.PageRequest) paginationParams { + p := paginationParams{ + reverse: false, + limit: 100, + offset: 0, + } + if pagination != nil { + p.reverse = pagination.Reverse + if pagination.Limit > 0 { + p.limit = pagination.Limit + } + p.offset = pagination.Offset + } + return p +} + +// filterFilesWithPagination iterates over files and returns those matching the filter with pagination +func (k Keeper) filterFilesWithPagination(ctx sdk.Context, params paginationParams, filter func(*types.UnifiedFile) bool) ([]types.UnifiedFile, *query.PageResponse) { + var files []types.UnifiedFile + var skipped, collected, total uint64 + + k.IterateFilesByMerkle(ctx, params.reverse, func(_ []byte, val []byte) bool { + var file types.UnifiedFile + if err := k.cdc.Unmarshal(val, &file); err != nil { + return false + } + + if filter(&file) { + total++ + if skipped < params.offset { + skipped++ + return false + } + if collected < params.limit { + files = append(files, file) + collected++ + } + } + return false + }) + + return files, &query.PageResponse{Total: total} +} + func (k Keeper) AllFiles(c context.Context, req *types.QueryAllFiles) (*types.QueryAllFilesResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "invalid request") @@ -110,110 +162,60 @@ func (k Keeper) AllFilesByMerkle(c context.Context, req *types.QueryAllFilesByMe return &types.QueryAllFilesByMerkleResponse{Files: files, Pagination: pageRes}, nil } -// OpenFiles returns a paginated list of files with space that providers have yet to fill -// -// TODO: Create unit-test cases for this -func (k Keeper) OpenFiles(c context.Context, req *types.QueryOpenFiles) (*types.QueryAllFilesResponse, error) { +// AllFilesByOwner returns a paginated list of files owned by a specific address +func (k Keeper) AllFilesByOwner(c context.Context, req *types.QueryAllFilesByOwner) (*types.QueryAllFilesByOwnerResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "invalid request") } - var files []types.UnifiedFile - ctx := sdk.UnwrapSDKContext(c) + if req.Owner == "" { + return nil, status.Error(codes.InvalidArgument, "owner address is required") + } - reverse := false - var limit uint64 = 100 - if req.Pagination != nil { // HERE IS THE FIX - reverse = req.Pagination.Reverse - limit = req.Pagination.Limit + if _, err := sdk.AccAddressFromBech32(req.Owner); err != nil { + return nil, status.Error(codes.InvalidArgument, "invalid owner address format") } - var i uint64 - var total uint64 - k.IterateFilesByMerkle(ctx, reverse, func(_ []byte, val []byte) bool { - var file types.UnifiedFile - if err := k.cdc.Unmarshal(val, &file); err != nil { - return false - } + ctx := sdk.UnwrapSDKContext(c) + params := extractPaginationParams(req.Pagination) - if file.ContainsProver(req.ProviderAddress) { - return false - } + files, pageRes := k.filterFilesWithPagination(ctx, params, func(file *types.UnifiedFile) bool { + return file.Owner == req.Owner + }) - if len(file.Proofs) < int(file.MaxProofs) { - total++ - if i >= limit { - return false - } - files = append(files, file) - } else { - return false - } + return &types.QueryAllFilesByOwnerResponse{Files: files, Pagination: pageRes}, nil +} - i++ +// OpenFiles returns a paginated list of files with space that providers have yet to fill +func (k Keeper) OpenFiles(c context.Context, req *types.QueryOpenFiles) (*types.QueryAllFilesResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } - return false - }) + ctx := sdk.UnwrapSDKContext(c) + params := extractPaginationParams(req.Pagination) - qpr := query.PageResponse{ - NextKey: nil, - Total: total, - } + files, pageRes := k.filterFilesWithPagination(ctx, params, func(file *types.UnifiedFile) bool { + return !file.ContainsProver(req.ProviderAddress) && len(file.Proofs) < int(file.MaxProofs) + }) - return &types.QueryAllFilesResponse{Files: files, Pagination: &qpr}, nil + return &types.QueryAllFilesResponse{Files: files, Pagination: pageRes}, nil } // EndangeredFiles returns a paginated list of files with only 1x redundancy -// -// TODO: Create unit-test cases for this func (k Keeper) EndangeredFiles(c context.Context, req *types.QueryOpenFiles) (*types.QueryAllFilesResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "invalid request") } - var files []types.UnifiedFile ctx := sdk.UnwrapSDKContext(c) + params := extractPaginationParams(req.Pagination) - reverse := false - var limit uint64 = 100 - if req.Pagination != nil { // HERE IS THE FIX - reverse = req.Pagination.Reverse - limit = req.Pagination.Limit - } - - var i uint64 - var total uint64 - k.IterateFilesByMerkle(ctx, reverse, func(_ []byte, val []byte) bool { - var file types.UnifiedFile - if err := k.cdc.Unmarshal(val, &file); err != nil { - return false - } - - if file.ContainsProver(req.ProviderAddress) { - return false - } - - if len(file.Proofs) == 1 { - total++ - if i >= limit { - return false - } - files = append(files, file) - } else { - return false - } - - i++ - - return false + files, pageRes := k.filterFilesWithPagination(ctx, params, func(file *types.UnifiedFile) bool { + return !file.ContainsProver(req.ProviderAddress) && len(file.Proofs) == 1 }) - qpr := query.PageResponse{ - NextKey: nil, - Total: total, - } - - return &types.QueryAllFilesResponse{Files: files, Pagination: &qpr}, nil + return &types.QueryAllFilesResponse{Files: files, Pagination: pageRes}, nil } func (k Keeper) File(c context.Context, req *types.QueryFile) (*types.QueryFileResponse, error) { diff --git a/x/storage/keeper/grpc_query_active_deals_test.go b/x/storage/keeper/grpc_query_active_deals_test.go index 40be39cec..451973fcc 100644 --- a/x/storage/keeper/grpc_query_active_deals_test.go +++ b/x/storage/keeper/grpc_query_active_deals_test.go @@ -144,6 +144,159 @@ func (suite *KeeperTestSuite) TestAllFiles() { suite.reset() } +func (suite *KeeperTestSuite) TestAllFilesByOwner() { + suite.SetupSuite() + + testAddresses, err := testutil.CreateTestAddresses("cosmos", 3) + suite.Require().NoError(err) + + owner1 := testAddresses[0] + owner2 := testAddresses[1] + depoAccount := testAddresses[2] + + coins := sdk.NewCoins(sdk.NewCoin("ujkl", sdk.NewInt(100000000000))) + testAcc, _ := sdk.AccAddressFromBech32(owner1) + err = suite.bankKeeper.SendCoinsFromModuleToAccount(suite.ctx, types.ModuleName, testAcc, coins) + suite.Require().NoError(err) + + suite.storageKeeper.SetParams(suite.ctx, types.Params{ + DepositAccount: depoAccount, + ProofWindow: 50, + ChunkSize: 1024, + PriceFeed: "jklprice", + MissesToBurn: 3, + MaxContractAgeInBlocks: 100, + PricePerTbPerMonth: 8, + CollateralPrice: 2, + CheckWindow: 11, + ReferralCommission: 25, + PolRatio: 40, + }) + + // Create 5 files for owner1 + for i := 0; i < 5; i++ { + merkle := []byte(fmt.Sprintf("merkle_owner1_%d", i)) + suite.storageKeeper.SetFile(suite.ctx, types.UnifiedFile{ + Merkle: merkle, + Owner: owner1, + Start: int64(i), + Expires: 0, + FileSize: 1024, + ProofInterval: 400, + ProofType: 0, + Proofs: make([]string, 0), + MaxProofs: 3, + Note: "{}", + }) + } + + // Create 3 files for owner2 + for i := 0; i < 3; i++ { + merkle := []byte(fmt.Sprintf("merkle_owner2_%d", i)) + suite.storageKeeper.SetFile(suite.ctx, types.UnifiedFile{ + Merkle: merkle, + Owner: owner2, + Start: int64(i), + Expires: 0, + FileSize: 2048, + ProofInterval: 400, + ProofType: 0, + Proofs: make([]string, 0), + MaxProofs: 3, + Note: "{}", + }) + } + + // Test: Query files for owner1 - should return 5 files + pg := query.PageRequest{ + Offset: 0, + Reverse: false, + Limit: 100, + } + + res, err := suite.queryClient.AllFilesByOwner(context.Background(), &types.QueryAllFilesByOwner{ + Pagination: &pg, + Owner: owner1, + }) + suite.Require().NoError(err) + suite.Require().Equal(5, len(res.Files)) + suite.Require().Equal(uint64(5), res.Pagination.Total) + + // Verify all returned files belong to owner1 + for _, file := range res.Files { + suite.Require().Equal(owner1, file.Owner) + } + + // Test: Query files for owner2 - should return 3 files + res, err = suite.queryClient.AllFilesByOwner(context.Background(), &types.QueryAllFilesByOwner{ + Pagination: &pg, + Owner: owner2, + }) + suite.Require().NoError(err) + suite.Require().Equal(3, len(res.Files)) + suite.Require().Equal(uint64(3), res.Pagination.Total) + + // Verify all returned files belong to owner2 + for _, file := range res.Files { + suite.Require().Equal(owner2, file.Owner) + } + + // Test: Pagination with limit + pgLimit := query.PageRequest{ + Offset: 0, + Limit: 2, + } + res, err = suite.queryClient.AllFilesByOwner(context.Background(), &types.QueryAllFilesByOwner{ + Pagination: &pgLimit, + Owner: owner1, + }) + suite.Require().NoError(err) + suite.Require().Equal(2, len(res.Files)) + suite.Require().Equal(uint64(5), res.Pagination.Total) // Total should still be 5 + + // Test: Pagination with offset + pgOffset := query.PageRequest{ + Offset: 3, + Limit: 100, + } + res, err = suite.queryClient.AllFilesByOwner(context.Background(), &types.QueryAllFilesByOwner{ + Pagination: &pgOffset, + Owner: owner1, + }) + suite.Require().NoError(err) + suite.Require().Equal(2, len(res.Files)) // 5 total - 3 offset = 2 remaining + suite.Require().Equal(uint64(5), res.Pagination.Total) + + // Test: Empty owner should return error + _, err = suite.queryClient.AllFilesByOwner(context.Background(), &types.QueryAllFilesByOwner{ + Pagination: &pg, + Owner: "", + }) + suite.Require().Error(err) + suite.Require().Contains(err.Error(), "owner address is required") + + // Test: Invalid owner address format should return error + _, err = suite.queryClient.AllFilesByOwner(context.Background(), &types.QueryAllFilesByOwner{ + Pagination: &pg, + Owner: "invalid-address", + }) + suite.Require().Error(err) + suite.Require().Contains(err.Error(), "invalid owner address format") + + // Test: Non-existent owner should return empty list + // Use a known valid bech32 address that won't match any files we created + nonExistentOwner := "cosmos1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqnrql8a" + res, err = suite.queryClient.AllFilesByOwner(context.Background(), &types.QueryAllFilesByOwner{ + Pagination: &pg, + Owner: nonExistentOwner, + }) + suite.Require().NoError(err) + suite.Require().Equal(0, len(res.Files)) + suite.Require().Equal(uint64(0), res.Pagination.Total) + + suite.reset() +} + func (suite *KeeperTestSuite) TestOpenFiles() { suite.SetupSuite() diff --git a/x/storage/types/query.pb.go b/x/storage/types/query.pb.go index 7bf3c301f..8c965afcc 100644 --- a/x/storage/types/query.pb.go +++ b/x/storage/types/query.pb.go @@ -3117,6 +3117,8 @@ type QueryClient interface { EndangeredFiles(ctx context.Context, in *QueryOpenFiles, opts ...grpc.CallOption) (*QueryAllFilesResponse, error) // Queries a list of File items matching the merkle. AllFilesByMerkle(ctx context.Context, in *QueryAllFilesByMerkle, opts ...grpc.CallOption) (*QueryAllFilesByMerkleResponse, error) + // Queries a list of File items owned by a specific address. + AllFilesByOwner(ctx context.Context, in *QueryAllFilesByOwner, opts ...grpc.CallOption) (*QueryAllFilesByOwnerResponse, error) // Queries a Proof by provider_address, merkle, owner, and start. Proof(ctx context.Context, in *QueryProof, opts ...grpc.CallOption) (*QueryProofResponse, error) // Queries a list of Proof items. @@ -3236,6 +3238,15 @@ func (c *queryClient) AllFilesByMerkle(ctx context.Context, in *QueryAllFilesByM return out, nil } +func (c *queryClient) AllFilesByOwner(ctx context.Context, in *QueryAllFilesByOwner, opts ...grpc.CallOption) (*QueryAllFilesByOwnerResponse, error) { + out := new(QueryAllFilesByOwnerResponse) + err := c.cc.Invoke(ctx, "/canine_chain.storage.Query/AllFilesByOwner", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *queryClient) Proof(ctx context.Context, in *QueryProof, opts ...grpc.CallOption) (*QueryProofResponse, error) { out := new(QueryProofResponse) err := c.cc.Invoke(ctx, "/canine_chain.storage.Query/Proof", in, out, opts...) @@ -3458,6 +3469,8 @@ type QueryServer interface { EndangeredFiles(context.Context, *QueryOpenFiles) (*QueryAllFilesResponse, error) // Queries a list of File items matching the merkle. AllFilesByMerkle(context.Context, *QueryAllFilesByMerkle) (*QueryAllFilesByMerkleResponse, error) + // Queries a list of File items owned by a specific address. + AllFilesByOwner(context.Context, *QueryAllFilesByOwner) (*QueryAllFilesByOwnerResponse, error) // Queries a Proof by provider_address, merkle, owner, and start. Proof(context.Context, *QueryProof) (*QueryProofResponse, error) // Queries a list of Proof items. @@ -3531,6 +3544,9 @@ func (*UnimplementedQueryServer) EndangeredFiles(ctx context.Context, req *Query func (*UnimplementedQueryServer) AllFilesByMerkle(ctx context.Context, req *QueryAllFilesByMerkle) (*QueryAllFilesByMerkleResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method AllFilesByMerkle not implemented") } +func (*UnimplementedQueryServer) AllFilesByOwner(ctx context.Context, req *QueryAllFilesByOwner) (*QueryAllFilesByOwnerResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AllFilesByOwner not implemented") +} func (*UnimplementedQueryServer) Proof(ctx context.Context, req *QueryProof) (*QueryProofResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Proof not implemented") } @@ -3731,6 +3747,24 @@ func _Query_AllFilesByMerkle_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } +func _Query_AllFilesByOwner_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryAllFilesByOwner) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).AllFilesByOwner(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/canine_chain.storage.Query/AllFilesByOwner", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).AllFilesByOwner(ctx, req.(*QueryAllFilesByOwner)) + } + return interceptor(ctx, in, info, handler) +} + func _Query_Proof_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(QueryProof) if err := dec(in); err != nil { @@ -4177,6 +4211,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "AllFilesByMerkle", Handler: _Query_AllFilesByMerkle_Handler, }, + { + MethodName: "AllFilesByOwner", + Handler: _Query_AllFilesByOwner_Handler, + }, { MethodName: "Proof", Handler: _Query_Proof_Handler, diff --git a/x/storage/types/query.pb.gw.go b/x/storage/types/query.pb.gw.go index e8b42afab..210aedd48 100644 --- a/x/storage/types/query.pb.gw.go +++ b/x/storage/types/query.pb.gw.go @@ -495,6 +495,78 @@ func local_request_Query_AllFilesByMerkle_0(ctx context.Context, marshaler runti } +var ( + filter_Query_AllFilesByOwner_0 = &utilities.DoubleArray{Encoding: map[string]int{"owner": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_AllFilesByOwner_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAllFilesByOwner + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["owner"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "owner") + } + + protoReq.Owner, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "owner", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_AllFilesByOwner_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.AllFilesByOwner(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_AllFilesByOwner_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryAllFilesByOwner + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["owner"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "owner") + } + + protoReq.Owner, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "owner", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_AllFilesByOwner_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.AllFilesByOwner(ctx, &protoReq) + return msg, metadata, err + +} + func request_Query_Proof_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryProof var metadata runtime.ServerMetadata @@ -1872,6 +1944,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_AllFilesByOwner_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_AllFilesByOwner_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AllFilesByOwner_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_Proof_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -2582,6 +2677,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_AllFilesByOwner_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_AllFilesByOwner_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_AllFilesByOwner_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_Query_Proof_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -3060,6 +3175,8 @@ var ( pattern_Query_AllFilesByMerkle_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 4}, []string{"jackal", "canine-chain", "storage", "files", "merkle"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_AllFilesByOwner_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 4}, []string{"jackal", "canine-chain", "storage", "files", "owner"}, "", runtime.AssumeColonVerbOpt(false))) + pattern_Query_Proof_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5, 1, 0, 4, 1, 5, 6, 1, 0, 4, 1, 5, 7}, []string{"jackal", "canine-chain", "storage", "proofs", "provider_address", "merkle", "owner", "start"}, "", runtime.AssumeColonVerbOpt(false))) pattern_Query_AllProofs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"jackal", "canine-chain", "storage", "proofs"}, "", runtime.AssumeColonVerbOpt(false))) @@ -3122,6 +3239,8 @@ var ( forward_Query_AllFilesByMerkle_0 = runtime.ForwardResponseMessage + forward_Query_AllFilesByOwner_0 = runtime.ForwardResponseMessage + forward_Query_Proof_0 = runtime.ForwardResponseMessage forward_Query_AllProofs_0 = runtime.ForwardResponseMessage