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

Migrate delegated routing #3

Merged
merged 54 commits into from
Nov 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
e7295ac
Initial commit
aschmahmann Oct 13, 2021
355426e
WIP initial draft (#1)
aschmahmann Oct 26, 2021
30ed35a
fix context leak (#3)
petar Oct 28, 2021
89ff75d
add server logging
petar Nov 16, 2021
298c2a5
add more server logging
petar Nov 16, 2021
8bfe782
add more client logging
petar Nov 16, 2021
3f7013e
sync: update CI config files (#12)
web3-bot Apr 14, 2022
2dee21d
Implementation of delegated routing based on the Edelweiss compiler a…
petar May 4, 2022
8211c33
Add ValueStore Client implementation.
ajnavarro May 19, 2022
4c4b42f
Merge pull request ipfs/go-delegated-routing#17 from ajnavarro/featur…
ajnavarro May 20, 2022
d06bc84
Handle context cancellation.
ajnavarro May 19, 2022
5bc20f3
Requested changes.
ajnavarro May 20, 2022
4f5d67e
Recreate edelweiss code with fixes.
ajnavarro May 23, 2022
e67b775
Requested changes.
ajnavarro May 24, 2022
6b1d126
Update edelweiss
ajnavarro May 24, 2022
ee3210e
Merge pull request ipfs/go-delegated-routing#16 from ajnavarro/fix/ca…
ajnavarro May 24, 2022
55d18ae
Fix context handling on server.
ajnavarro May 26, 2022
da708fd
Merge pull request ipfs/go-delegated-routing#19 from ajnavarro/fix/se…
ajnavarro May 27, 2022
a621003
update dep on edelweiss (#20)
petar May 27, 2022
46ebd49
bump to latest edelweiss; query moved to http body (#23)
petar Jun 7, 2022
e2d8829
support multiple responses (#26)
petar Jun 18, 2022
b4689e9
fix: context cancelation tests
guseggert Jul 1, 2022
d64dd01
Merge pull request ipfs/go-delegated-routing#28 from ipfs/fix/context…
ajnavarro Jul 7, 2022
5543bd2
Fix: Handle correctly keys on Get/Put Value and Get/Put IPNS.
ajnavarro Jul 7, 2022
4da16f4
upgrade to go-log/v2 (#34)
petar Jul 27, 2022
1ba943f
Add Provide RPC (#37)
willscott Aug 10, 2022
8bbb160
ci: add check to ensure generated files are up-to-date (#41)
guseggert Aug 31, 2022
0ee4442
fix: upgrade edelweiss and rerun 'go generate' (#42)
guseggert Aug 31, 2022
b0ccc76
Update provide to take an array of keys, per spec (#45)
willscott Sep 5, 2022
be5d6db
feat: use GET for FindProviders (#46)
guseggert Sep 13, 2022
cbcf08b
Fixed serialisation issue with multiadds (#49)
ischasny Sep 15, 2022
4837bd4
Fixed a bug when provider with more than one multiaddresses failed si…
ischasny Sep 21, 2022
f4dc284
Merge pull request ipfs/go-delegated-routing#52 from ischasny/main
ajnavarro Sep 21, 2022
669d88f
added link to reframe blog post (#54)
reidlw Oct 13, 2022
a43cbef
content routing poc
guseggert Oct 20, 2022
c096b3e
remove ipns
guseggert Oct 20, 2022
07e55c7
finish server poc
guseggert Oct 20, 2022
177be2d
add basic client tests (except provide)
guseggert Oct 21, 2022
384af08
finish client tests
guseggert Oct 22, 2022
f688028
add contentrouter tests
guseggert Oct 22, 2022
73c38c0
Change schema according to spec changes
guseggert Nov 18, 2022
a93ec16
Implement basic tests
guseggert Nov 22, 2022
2aea9d7
Add test for signature verification failure
guseggert Nov 22, 2022
fa74a3e
Fix tests (still WIP)
guseggert Nov 22, 2022
d7e4e8f
Fix tests and remove unnecesary code.
ajnavarro Nov 22, 2022
75cae59
Fix go vet
ajnavarro Nov 22, 2022
009d080
Fix staticcheck
ajnavarro Nov 22, 2022
5906d11
Rebased
ajnavarro Nov 22, 2022
62447ef
Add windows compatibility on tests
ajnavarro Nov 22, 2022
f61bf6b
Remove unused test file
ajnavarro Nov 28, 2022
a9206e9
Merge pull request ipfs/go-delegated-routing#65 from ipfs/ajnavarro/f…
ajnavarro Nov 28, 2022
f352679
Merge commits from ipfs/go-delegated-routing/guseggert/content-routin…
ajnavarro Nov 29, 2022
6a529bd
Migrate go-delegated-routing
ajnavarro Nov 29, 2022
102042c
Add README
ajnavarro Nov 29, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,50 @@ module github.com/ipfs/go-libipfs

go 1.19

require github.com/stretchr/testify v1.8.1
require (
github.com/benbjohnson/clock v1.3.0
github.com/gorilla/mux v1.8.0
github.com/ipfs/go-cid v0.3.2
github.com/ipfs/go-ipns v0.3.0
github.com/ipfs/go-log/v2 v2.5.1
github.com/libp2p/go-libp2p v0.23.4
github.com/libp2p/go-libp2p-record v0.2.0
github.com/multiformats/go-multiaddr v0.8.0
github.com/multiformats/go-multibase v0.1.1
github.com/multiformats/go-multihash v0.2.1
github.com/samber/lo v1.36.0
github.com/stretchr/testify v1.8.1
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/ipfs/go-ipfs-util v0.0.2 // indirect
github.com/ipld/go-ipld-prime v0.9.0 // indirect
github.com/klauspost/cpuid/v2 v2.1.1 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/libp2p/go-openssl v0.1.0 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/mattn/go-pointer v0.0.1 // 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-multicodec v0.6.0 // indirect
github.com/multiformats/go-varint v0.0.6 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/polydawn/refmt v0.0.0-20190807091052-3d65705ee9f1 // indirect
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.23.0 // indirect
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
golang.org/x/exp v0.0.0-20220916125017-b168a2c6b86b // indirect
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.1.7 // indirect
)
174 changes: 173 additions & 1 deletion go.sum

Large diffs are not rendered by default.

24 changes: 24 additions & 0 deletions routing/http/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
go-delegated-routing
=======================

> Delegated routing Client and Server over Reframe RPC

This package provides delegated routing implementation in Go:
- Client (for IPFS nodes like [Kubo](https://github.com/ipfs/kubo/blob/master/docs/config.md#routingrouters-parameters)),
- Server (for public indexers such as https://cid.contact)

## Documentation

- Go docs: https://pkg.go.dev/github.com/ipfs/go-libipfs/routing/http/

## Lead Maintainer

🦗🎶

## Contributing

Contributions are welcome! This repository is part of the IPFS project and therefore governed by our [contributing guidelines](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md).

## License

[SPDX-License-Identifier: Apache-2.0 OR MIT](LICENSE.md)
187 changes: 187 additions & 0 deletions routing/http/client/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
package client

import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"time"

"github.com/benbjohnson/clock"
"github.com/ipfs/go-cid"
ipns "github.com/ipfs/go-ipns"
delegatedrouting "github.com/ipfs/go-libipfs/routing/http"
logging "github.com/ipfs/go-log/v2"
record "github.com/libp2p/go-libp2p-record"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/multiformats/go-multiaddr"
)

var logger = logging.Logger("service/delegatedrouting")

type client struct {
baseURL string
httpClient httpClient
validator record.Validator
clock clock.Clock

peerID peer.ID
addrs []delegatedrouting.Multiaddr
identity crypto.PrivKey

// called immeidately after signing a provide req
// used for testing, e.g. testing the server with a mangled signature
afterSignCallback func(req *delegatedrouting.BitswapWriteProviderRequest)
}

type httpClient interface {
Do(req *http.Request) (*http.Response, error)
}

type option func(*client)

func WithIdentity(identity crypto.PrivKey) option {
return func(c *client) {
c.identity = identity
}
}

func WithHTTPClient(h httpClient) option {
return func(c *client) {
c.httpClient = h
}
}

func WithProviderInfo(peerID peer.ID, addrs []multiaddr.Multiaddr) option {
return func(c *client) {
c.peerID = peerID
for _, a := range addrs {
c.addrs = append(c.addrs, delegatedrouting.Multiaddr{Multiaddr: a})
}
}
}

// New creates a content routing API client.
// The Provider and identity parameters are option. If they are nil, the `Provide` method will not function.
func New(baseURL string, opts ...option) (*client, error) {
client := &client{
baseURL: baseURL,
httpClient: http.DefaultClient,
validator: ipns.Validator{},
clock: clock.New(),
}

for _, opt := range opts {
opt(client)
}

if client.identity != nil && client.peerID.Size() != 0 && !client.peerID.MatchesPublicKey(client.identity.GetPublic()) {
return nil, errors.New("identity does not match provider")
}

return client, nil
}

func (c *client) FindProviders(ctx context.Context, key cid.Cid) ([]delegatedrouting.Provider, error) {
url := c.baseURL + "/v1/providers/" + key.String()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, err
}

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

if resp.StatusCode != http.StatusOK {
return nil, httpError(resp.StatusCode, resp.Body)
}

parsedResp := &delegatedrouting.FindProvidersResponse{}
err = json.NewDecoder(resp.Body).Decode(parsedResp)
return parsedResp.Providers, err
}

func (c *client) ProvideBitswap(ctx context.Context, keys []cid.Cid, ttl time.Duration) (time.Duration, error) {
if c.identity == nil {
return 0, errors.New("cannot provide Bitswap records without an identity")
}
if c.peerID.Size() == 0 {
return 0, errors.New("cannot provide Bitswap records without a peer ID")
}

ks := make([]delegatedrouting.CID, len(keys))
for i, c := range keys {
ks[i] = delegatedrouting.CID{Cid: c}
}

now := c.clock.Now()

req := delegatedrouting.BitswapWriteProviderRequest{
Protocol: "bitswap",
Payload: delegatedrouting.BitswapWriteProviderRequestPayload{
Keys: ks,
AdvisoryTTL: &delegatedrouting.Duration{Duration: ttl},
Timestamp: &delegatedrouting.Time{Time: now},
ID: &c.peerID,
Addrs: c.addrs,
},
}
err := req.Sign(c.peerID, c.identity)
if err != nil {
return 0, err
}

if c.afterSignCallback != nil {
c.afterSignCallback(&req)
}

advisoryTTL, err := c.provideSignedBitswapRecord(ctx, &req)
if err != nil {
return 0, err
}

return advisoryTTL, err
}

// ProvideAsync makes a provide request to a delegated router
func (c *client) provideSignedBitswapRecord(ctx context.Context, bswp *delegatedrouting.BitswapWriteProviderRequest) (time.Duration, error) {
req := delegatedrouting.WriteProvidersRequest{Providers: []delegatedrouting.Provider{bswp}}

url := c.baseURL + "/v1/providers"

b, err := json.Marshal(req)
if err != nil {
return 0, err
}

httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewBuffer(b))
if err != nil {
return 0, err
}

resp, err := c.httpClient.Do(httpReq)
if err != nil {
return 0, fmt.Errorf("making HTTP req to provide a signed record: %w", err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return 0, httpError(resp.StatusCode, resp.Body)
}
provideResult := delegatedrouting.WriteProvidersResponse{Protocols: []string{"bitswap"}}
err = json.NewDecoder(resp.Body).Decode(&provideResult)
if err != nil {
return 0, err
}
if len(provideResult.ProvideResults) != 1 {
return 0, fmt.Errorf("expected 1 result but got %d", len(provideResult.ProvideResults))
}

return provideResult.ProvideResults[0].(*delegatedrouting.BitswapWriteProviderResponse).AdvisoryTTL, nil
}
Loading