Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(x/data): query iri by hash cli and rest endpoint #1107

Merged
merged 9 commits into from
May 23, 2022
2,769 changes: 2,503 additions & 266 deletions api/regen/data/v1/query.pulsar.go

Large diffs are not rendered by default.

76 changes: 76 additions & 0 deletions api/regen/data/v1/query_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

66 changes: 61 additions & 5 deletions proto/regen/data/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@ service Query {
// HTTP REST API not supported with ContentHash
}

// IRIByRawHash queries IRI based on ContentHash_Raw properties.
rpc IRIByRawHash(QueryIRIByRawHashRequest)
returns (QueryIRIByRawHashResponse) {
option (google.api.http).get = "/regen/data/v1/iri-by-raw";
}

// IRIByGraphHash queries IRI based on ContentHash_Graph properties.
rpc IRIByGraphHash(QueryIRIByGraphHashRequest)
returns (QueryIRIByGraphHashResponse) {
option (google.api.http).get = "/regen/data/v1/iri-by-graph";
}

// HashByIRI queries ContentHash based on IRI.
rpc HashByIRI(QueryHashByIRIRequest) returns (QueryHashByIRIResponse) {
option (google.api.http).get = "/regen/data/v1/hash/{iri}";
Expand Down Expand Up @@ -59,11 +71,11 @@ service Query {
// HTTP REST API not supported with ContentHash
}

// ResolverInfo queries information about a resolved based on url.
// ResolverInfo queries information about a resolved based on URL.
rpc ResolverInfo(QueryResolverInfoRequest)
returns (QueryResolverInfoResponse) {
option (google.api.http).get =
"/regen/data/v1/resolver"; // url must be passed as a parameter
"/regen/data/v1/resolver"; // URL must be passed as a parameter
}
}

Expand Down Expand Up @@ -117,19 +129,63 @@ message QueryIRIByHashRequest {

// QueryIRIByHashResponse is the Query/IRIByHash response type.
message QueryIRIByHashResponse {
// iri is the IRI for the anchored data.
// iri is the IRI for the content hash.
string iri = 1;
}

// QueryIRIByRawHashRequest is the Query/IRIByRawHash request type.
message QueryIRIByRawHashRequest {
// hash represents the hash of the data based on the digest_algorithm and must
// be encoded as a base64 string. When hash is provided as a URL parameter,
// all instances of "+" should also be replaced with "%2b".
string hash = 1;

// digest_algorithm represents the hash digest algorithm.
DigestAlgorithm digest_algorithm = 2;

// media_type represents the media type for raw data.
RawMediaType media_type = 3;
}

// QueryIRIByRawHashResponse is the Query/IRIByRawHash response type.
message QueryIRIByRawHashResponse {
// iri is the IRI for the content hash.
string iri = 1;
}

// QueryIRIByGraphHashRequest is the Query/IRIByGraphHash request type.
message QueryIRIByGraphHashRequest {
// hash represents the hash of the data based on the digest_algorithm and must
// be encoded as a base64 string. When hash is provided as a URL parameter,
// all instances of "+" should also be replaced with "%2b".
string hash = 1;

// digest_algorithm represents the hash digest algorithm.
DigestAlgorithm digest_algorithm = 2;

// graph_canonicalization_algorithm represents the RDF graph
// canonicalization algorithm.
GraphCanonicalizationAlgorithm canonicalization_algorithm = 3;

// merkle_tree is the merkle tree type used for the graph hash, if any.
GraphMerkleTree merkle_tree = 4;
}

// QueryIRIByGraphHashResponse is the Query/IRIByGraphHash response type.
message QueryIRIByGraphHashResponse {
// iri is the IRI for the content hash.
string iri = 1;
}

// QueryHashByIRIRequest is the Query/HashByIRI request type.
message QueryHashByIRIRequest {
// iri is the IRI for the anchored data.
// iri is the IRI for the content hash.
string iri = 1;
}

// QueryHashByIRIResponse is the Query/HashByIRI response type.
message QueryHashByIRIResponse {
// content_hash is the ContentHash for the anchored data.
// content_hash is the ContentHash for the IRI.
ContentHash content_hash = 1;
}

Expand Down
69 changes: 68 additions & 1 deletion x/data/client/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package client

import (
"fmt"
"io/ioutil"
"strings"

"github.com/spf13/cobra"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/spf13/cobra"

"github.com/regen-network/regen-ledger/x/data"
)
Expand Down Expand Up @@ -45,6 +47,7 @@ $ regen query data by-iri regen:113gdjFKcVCt13Za6vN7TtbgMM6LMSjRnu89BMCxeuHdkJ1h
queryByIRICmd,
QueryByAttestorCmd(),
QueryHashByIRICmd(),
QueryIRIByHashCmd(),
QueryAttestorsCmd(),
QueryResolverInfoCmd(),
QueryResolversCmd(),
Expand Down Expand Up @@ -136,6 +139,51 @@ func QueryHashByIRICmd() *cobra.Command {
return cmd
}

// QueryIRIByHashCmd creates a CLI command for Query/IRIByHash.
func QueryIRIByHashCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "iri [content-hash-json]",
Short: "Query for IRI based on content hash",
Long: `Query for IRI based on content hash provided in json format.

Parameters:
content-hash-json: contains the content hash formatted as json`,
Example: `regen q data iri content.json

where content.json contains:
{
"graph": {
"hash": "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=",
"digest_algorithm": "DIGEST_ALGORITHM_BLAKE2B_256",
"canonicalization_algorithm": "GRAPH_CANONICALIZATION_ALGORITHM_URDNA2015",
"merkle_tree": "GRAPH_MERKLE_TREE_NONE_UNSPECIFIED"
}
}`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
c, ctx, err := mkQueryClient(cmd)
if err != nil {
return err
}

contentHash, err := parseContentHash(ctx, args[0])
if err != nil {
return err
}

res, err := c.IRIByHash(cmd.Context(), &data.QueryIRIByHashRequest{
ContentHash: contentHash,
})

return print(ctx, res, err)
},
}

flags.AddQueryFlagsToCmd(cmd)

return cmd
}

// QueryAttestorsCmd creates a CLI command for Query/Attestors.
func QueryAttestorsCmd() *cobra.Command {
cmd := &cobra.Command{
Expand Down Expand Up @@ -223,3 +271,22 @@ func QueryResolversCmd() *cobra.Command {

return cmd
}

func parseContentHash(clientCtx client.Context, filePath string) (*data.ContentHash, error) {
contentHash := data.ContentHash{}

if filePath == "" {
return nil, fmt.Errorf("file path is empty")
}

bz, err := ioutil.ReadFile(filePath)
if err != nil {
return nil, err
}

if err := clientCtx.Codec.UnmarshalJSON(bz, &contentHash); err != nil {
return nil, err
}

return &contentHash, nil
}
Loading