Skip to content

Commit

Permalink
Add dhash http client
Browse files Browse the repository at this point in the history
  • Loading branch information
ischasny committed Jan 13, 2023
1 parent 1060735 commit 0f2948d
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 5 deletions.
2 changes: 2 additions & 0 deletions api/v0/finder/client/http/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ func (c *Client) ListProviders(ctx context.Context, withExtMetadata bool) ([]*mo
defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
defer resp.Body.Close()

if err != nil {
return nil, err
}
Expand Down
161 changes: 161 additions & 0 deletions api/v0/finder/client/http/dhash_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package finderhttpclient

import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"

"github.com/ipni/go-indexer-core/store/dhash"
"github.com/ipni/storetheindex/api/v0/finder/model"
"github.com/ipni/storetheindex/api/v0/httpclient"
"github.com/libp2p/go-libp2p/core/peer"
b58 "github.com/mr-tron/base58/base58"
"github.com/multiformats/go-multihash"
)

const (
metadataPath = "/metadata"
)

type DHashClient struct {
Client

metadataUrl string
}

func NewDHashClient(baseURL string, options ...httpclient.Option) (*DHashClient, error) {
c, err := New(baseURL, options...)
if err != nil {
return nil, err
}

return &DHashClient{
Client: *c,
metadataUrl: baseURL + metadataPath,
}, nil
}

func (c *DHashClient) Find(ctx context.Context, mh multihash.Multihash) (*model.FindResponse, error) {
// query value keys from indexer
smh, err := dhash.SecondMultihash(mh)
if err != nil {
return nil, err
}
u := fmt.Sprint(c.finderURL, "/", smh.B58String())
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
if err != nil {
return nil, err
}
req.Header.Add("Accept", "application/json")

resp, err := c.c.Do(req)
if err != nil {
return nil, err
}

body, err := io.ReadAll(resp.Body)
defer resp.Body.Close()

if err != nil {
return nil, err
}

if resp.StatusCode != http.StatusOK {
return nil, httpclient.ReadError(resp.StatusCode, body)
}

findResponse := &model.FindResponse{}
err = json.Unmarshal(body, findResponse)
if err != nil {
return nil, err
}

c.decryptFindResponse(ctx, findResponse, map[string]multihash.Multihash{smh.B58String(): mh})

return findResponse, nil
}

// decryptFindResponse decrypts EncMultihashResults and appends the decrypted values to
// MultihashResults. It also fetches provider info and metadata for each value key.
func (c *DHashClient) decryptFindResponse(ctx context.Context, resp *model.FindResponse, unhasher map[string]multihash.Multihash) error {
pinfoCache := make(map[peer.ID]*model.ProviderInfo)

// decrypt each value key using the original multihash
// then for each decrypted value key fetch provider's addr info
for _, encRes := range resp.EncMultihashResults {
mh, found := unhasher[encRes.Multihash.B58String()]
if !found {
continue
}

mhr := model.MultihashResult{
Multihash: mh,
}
for _, evk := range encRes.ValueKeys {
vk, err := dhash.DecryptValueKey(evk, mh)
if err != nil {
return err
}

pid, ctxId, err := dhash.SplitValueKey(vk)
if err != nil {
return err
}

// fetch provider info to populate peer.AddrInfo
pinfo := pinfoCache[pid]
if pinfo == nil {
pinfo, err = c.GetProvider(ctx, pid)
if err != nil {
continue
}
pinfoCache[pid] = pinfo
}

// fetch metadata
metadata, err := c.fetchMetadata(ctx, vk)
if err != nil {
continue
}

mhr.ProviderResults = append(mhr.ProviderResults, model.ProviderResult{
ContextID: ctxId,
Metadata: metadata,
Provider: pinfo.AddrInfo,
})
}
if len(mhr.ProviderResults) > 0 {
resp.MultihashResults = append(resp.MultihashResults, mhr)
}
}
return nil
}

func (c *DHashClient) fetchMetadata(ctx context.Context, vk []byte) ([]byte, error) {
u := fmt.Sprint(c.metadataUrl, "/", b58.Encode(dhash.SHA256(vk, nil)))
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
if err != nil {
return nil, err
}
req.Header.Add("Accept", "application/json")

resp, err := c.c.Do(req)
if err != nil {
return nil, err
}

body, err := io.ReadAll(resp.Body)
defer resp.Body.Close()

if err != nil {
return nil, err
}

if resp.StatusCode != http.StatusOK {
return nil, httpclient.ReadError(resp.StatusCode, body)
}

return dhash.DecryptMetadata(body, vk)
}
9 changes: 8 additions & 1 deletion api/v0/finder/model/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,18 @@ type MultihashResult struct {

// FindResponse used to answer client queries/requests
type FindResponse struct {
MultihashResults []MultihashResult
MultihashResults []MultihashResult
EncMultihashResults []EncMultihashResult
// NOTE: This feature is not enabled yet.
// Signature []byte // Providers signature.
}

// EncMultihashResult aggregates all encrypted value keys for a single multihash
type EncMultihashResult struct {
Multihash multihash.Multihash
ValueKeys [][]byte
}

// Equal compares ProviderResult values to determine if they are equal. The
// provider addresses are omitted from the comparison.
func (pr ProviderResult) Equal(other ProviderResult) bool {
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ require (
github.com/ipld/go-ipld-adl-hamt v0.0.0-20220616142416-9004dbd839e0
github.com/ipld/go-ipld-prime v0.19.0
github.com/ipld/go-storethehash v0.3.13
github.com/ipni/go-indexer-core v0.6.20-0.20221203120225-301a542115f8
github.com/ipni/go-indexer-core v0.6.20-0.20230112154735-7b53be959fe6
github.com/libp2p/go-libp2p v0.23.4
github.com/libp2p/go-libp2p-gostream v0.5.0
github.com/libp2p/go-libp2p-pubsub v0.8.1
github.com/libp2p/go-msgio v0.2.0
github.com/mitchellh/go-homedir v1.1.0
github.com/mr-tron/base58 v1.2.0
github.com/multiformats/go-multiaddr v0.7.0
github.com/multiformats/go-multicodec v0.7.0
github.com/multiformats/go-multihash v0.2.1
Expand Down Expand Up @@ -154,7 +155,6 @@ require (
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
github.com/minio/sha256-simd v1.0.0 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect
github.com/multiformats/go-base36 v0.1.0 // indirect
github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -665,8 +665,8 @@ github.com/ipld/go-ipld-prime v0.19.0/go.mod h1:Q9j3BaVXwaA3o5JUDNvptDDr/x8+F7FG
github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20211210234204-ce2a1c70cd73/go.mod h1:2PJ0JgxyB08t0b2WKrcuqI3di0V+5n6RS/LTUJhkoxY=
github.com/ipld/go-storethehash v0.3.13 h1:1T6kX5K57lAgxbsGitZEaZMAR3RdWch2kO8okK/BgN8=
github.com/ipld/go-storethehash v0.3.13/go.mod h1:KCYpzmamubnSwm7fvWcCkm0aIwQh4WRNtzrKK4pVhAQ=
github.com/ipni/go-indexer-core v0.6.20-0.20221203120225-301a542115f8 h1:yVqgbaS/EwnJggQYpxf6mYJ//72NbPyM9MAGjDeD+8g=
github.com/ipni/go-indexer-core v0.6.20-0.20221203120225-301a542115f8/go.mod h1:EBHAKGJXuQUbdDYWCCmVCNrTO7vkapCeaDUG6my66J0=
github.com/ipni/go-indexer-core v0.6.20-0.20230112154735-7b53be959fe6 h1:sn06bRrS1aAlH5WdeLsHxeHPArKlS46bvwjSIapBf1M=
github.com/ipni/go-indexer-core v0.6.20-0.20230112154735-7b53be959fe6/go.mod h1:EBHAKGJXuQUbdDYWCCmVCNrTO7vkapCeaDUG6my66J0=
github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c=
github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4=
github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI=
Expand Down

0 comments on commit 0f2948d

Please sign in to comment.