Skip to content

Commit

Permalink
Merge branch 'main' into chore/migrate-peering
Browse files Browse the repository at this point in the history
  • Loading branch information
gammazero authored Oct 18, 2023
2 parents 6896038 + a50f784 commit b635397
Show file tree
Hide file tree
Showing 53 changed files with 1,930 additions and 1,929 deletions.
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ The following emojis are used to highlight certain changes:

* `boxo/gateway`:
* A new `WithResolver(...)` option can be used with `NewBlocksBackend(...)` allowing the user to pass their custom `Resolver` implementation.
* The gateway now sets a `Cache-Control` header for requests under the `/ipns/` namespace if the TTL for the corresponding IPNS Records or DNSLink entities is known.
* `boxo/bitswap/client`:
* A new `WithoutDuplicatedBlockStats()` option can be used with `bitswap.New` and `bsclient.New`. This disable accounting for duplicated blocks, which requires a `blockstore.Has()` lookup for every received block and thus, can impact performance.
* ✨ Migrated repositories into Boxo
Expand All @@ -42,9 +43,27 @@ The following emojis are used to highlight certain changes:
- Eliminate `..` elements that begin a rooted path: that is, replace "`/..`" by "`/`" at the beginning of a path.
* 🛠 The signature of `CoreAPI.ResolvePath` in `coreiface` has changed to now return
the remainder segments as a second return value, matching the signature of `resolver.ResolveToLastNode`.
* 🛠 `routing/http/client.FindPeers` now returns `iter.ResultIter[types.PeerRecord]` instead of `iter.ResultIter[types.Record]`. The specification indicates that records for this method will always be Peer Records.
* 🛠 The `namesys` package has been refactored. The following are the largest modifications:
* The options in `coreiface/options/namesys` have been moved to `namesys` and their names
have been made more consistent.
* Many of the exported structs and functions have been renamed in order to be consistent with
the remaining packages.
* `namesys.Resolver.Resolve` now returns a TTL, in addition to the resolved path. If the
TTL is unknown, 0 is returned. `IPNSResolver` is able to resolve a TTL, while `DNSResolver`
is not.
* `namesys/resolver.ResolveIPNS` has been moved to `namesys.ResolveIPNS` and now returns a TTL
in addition to the resolved path.
*`boxo/ipns` record defaults follow recommendations from [IPNS Record Specification](https://specs.ipfs.tech/ipns/ipns-record/#ipns-record):
* `DefaultRecordTTL` is now set to `1h`
* `DefaultRecordLifetime` follows the increased expiration window of Amino DHT ([go-libp2p-kad-dht#793](https://github.com/libp2p/go-libp2p-kad-dht/pull/793)) and is set to `48h`
* 🛠 The `gateway`'s `IPFSBackend.ResolveMutable` is now expected to return a TTL in addition to
the resolved path. If the TTL is unknown, 0 should be returned.

### Removed

* 🛠 `util.MultiErr` has been removed. Please use Go's native support for wrapping errors, or `errors.Join` instead.

### Fixed

### Security
Expand Down
6 changes: 3 additions & 3 deletions coreiface/options/name.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package options
import (
"time"

ropts "github.com/ipfs/boxo/coreiface/options/namesys"
"github.com/ipfs/boxo/namesys"
)

const (
Expand All @@ -21,7 +21,7 @@ type NamePublishSettings struct {
type NameResolveSettings struct {
Cache bool

ResolveOpts []ropts.ResolveOpt
ResolveOpts []namesys.ResolveOption
}

type (
Expand Down Expand Up @@ -123,7 +123,7 @@ func (nameOpts) Cache(cache bool) NameResolveOption {
}
}

func (nameOpts) ResolveOption(opt ropts.ResolveOpt) NameResolveOption {
func (nameOpts) ResolveOption(opt namesys.ResolveOption) NameResolveOption {
return func(settings *NameResolveSettings) error {
settings.ResolveOpts = append(settings.ResolveOpts, opt)
return nil
Expand Down
131 changes: 0 additions & 131 deletions coreiface/options/namesys/opts.go

This file was deleted.

54 changes: 38 additions & 16 deletions examples/routing/delegated-routing-client/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,22 +69,6 @@ func findProviders(w io.Writer, ctx context.Context, client *client.Client, cidS
return printIter(w, recordsIter)
}

func findPeers(w io.Writer, ctx context.Context, client *client.Client, pidStr string) error {
// Parses the given Peer ID to lookup the information for.
pid, err := peer.Decode(pidStr)
if err != nil {
return err
}

// Ask for information about the peer with the given peer ID.
recordsIter, err := client.FindPeers(ctx, pid)
if err != nil {
return err
}
defer recordsIter.Close()
return printIter(w, recordsIter)
}

func printIter(w io.Writer, iter iter.ResultIter[types.Record]) error {
// The response is streamed. Alternatively, you could use [iter.ReadAll]
// to fetch all the results all at once, instead of iterating as they are
Expand Down Expand Up @@ -118,6 +102,44 @@ func printIter(w io.Writer, iter iter.ResultIter[types.Record]) error {
return nil
}

func findPeers(w io.Writer, ctx context.Context, client *client.Client, pidStr string) error {
// Parses the given Peer ID to lookup the information for.
pid, err := peer.Decode(pidStr)
if err != nil {
return err
}

// Ask for information about the peer with the given peer ID.
recordsIter, err := client.FindPeers(ctx, pid)
if err != nil {
return err
}
defer recordsIter.Close()

// The response is streamed. Alternatively, you could use [iter.ReadAll]
// to fetch all the results all at once, instead of iterating as they are
// streamed.
for recordsIter.Next() {
res := recordsIter.Val()

// Check for error, but do not complain if we exceeded the timeout. We are
// expecting that to happen: we explicitly defined a timeout.
if res.Err != nil {
if !errors.Is(res.Err, context.DeadlineExceeded) {
return res.Err
}

return nil
}

fmt.Fprintln(w, res.Val.ID)
fmt.Fprintln(w, "\tProtocols:", res.Val.Protocols)
fmt.Fprintln(w, "\tAddresses:", res.Val.Addrs)
}

return nil
}

func findIPNS(w io.Writer, ctx context.Context, client *client.Client, nameStr string) error {
// Parses the given name string to get a record for.
name, err := ipns.NameFromString(nameStr)
Expand Down
46 changes: 24 additions & 22 deletions gateway/blocks_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ import (
"io"
"net/http"
"strings"
"time"

"github.com/ipfs/boxo/blockservice"
blockstore "github.com/ipfs/boxo/blockstore"
nsopts "github.com/ipfs/boxo/coreiface/options/namesys"
"github.com/ipfs/boxo/fetcher"
bsfetcher "github.com/ipfs/boxo/fetcher/impl/blockservice"
"github.com/ipfs/boxo/files"
"github.com/ipfs/boxo/ipld/merkledag"
ufile "github.com/ipfs/boxo/ipld/unixfs/file"
uio "github.com/ipfs/boxo/ipld/unixfs/io"
"github.com/ipfs/boxo/ipns"
"github.com/ipfs/boxo/namesys"
"github.com/ipfs/boxo/namesys/resolve"
"github.com/ipfs/boxo/path"
"github.com/ipfs/boxo/path/resolver"
blocks "github.com/ipfs/go-block-format"
Expand All @@ -39,7 +39,6 @@ import (
"github.com/ipld/go-ipld-prime/traversal/selector"
selectorparse "github.com/ipld/go-ipld-prime/traversal/selector/parse"
routinghelpers "github.com/libp2p/go-libp2p-routing-helpers"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/routing"
mc "github.com/multiformats/go-multicodec"

Expand Down Expand Up @@ -623,18 +622,23 @@ func (bb *BlocksBackend) getPathRoots(ctx context.Context, contentPath path.Immu
return pathRoots, lastPath, remainder, nil
}

func (bb *BlocksBackend) ResolveMutable(ctx context.Context, p path.Path) (path.ImmutablePath, error) {
func (bb *BlocksBackend) ResolveMutable(ctx context.Context, p path.Path) (path.ImmutablePath, time.Duration, time.Time, error) {
switch p.Namespace() {
case path.IPNSNamespace:
p, err := resolve.ResolveIPNS(ctx, bb.namesys, p)
res, err := namesys.Resolve(ctx, bb.namesys, p)
if err != nil {
return path.ImmutablePath{}, err
return path.ImmutablePath{}, 0, time.Time{}, err
}
return path.NewImmutablePath(p)
ip, err := path.NewImmutablePath(res.Path)
if err != nil {
return path.ImmutablePath{}, 0, time.Time{}, err
}
return ip, res.TTL, res.LastMod, nil
case path.IPFSNamespace:
return path.NewImmutablePath(p)
ip, err := path.NewImmutablePath(p)
return ip, 0, time.Time{}, err
default:
return path.ImmutablePath{}, NewErrorStatusCode(fmt.Errorf("unsupported path namespace: %s", p.Namespace()), http.StatusNotImplemented)
return path.ImmutablePath{}, 0, time.Time{}, NewErrorStatusCode(fmt.Errorf("unsupported path namespace: %s", p.Namespace()), http.StatusNotImplemented)
}
}

Expand All @@ -643,28 +647,25 @@ func (bb *BlocksBackend) GetIPNSRecord(ctx context.Context, c cid.Cid) ([]byte,
return nil, NewErrorStatusCode(errors.New("IPNS Record responses are not supported by this gateway"), http.StatusNotImplemented)
}

// Fails fast if the CID is not an encoded Libp2p Key, avoids wasteful
// round trips to the remote routing provider.
if mc.Code(c.Type()) != mc.Libp2pKey {
return nil, NewErrorStatusCode(errors.New("cid codec must be libp2p-key"), http.StatusBadRequest)
}

// The value store expects the key itself to be encoded as a multihash.
id, err := peer.FromCid(c)
name, err := ipns.NameFromCid(c)
if err != nil {
return nil, err
return nil, NewErrorStatusCode(err, http.StatusBadRequest)
}

return bb.routing.GetValue(ctx, "/ipns/"+string(id))
return bb.routing.GetValue(ctx, string(name.RoutingKey()))
}

func (bb *BlocksBackend) GetDNSLinkRecord(ctx context.Context, hostname string) (path.Path, error) {
if bb.namesys != nil {
p, err := bb.namesys.Resolve(ctx, "/ipns/"+hostname, nsopts.Depth(1))
p, err := path.NewPath("/ipns/" + hostname)
if err != nil {
return nil, err
}
res, err := bb.namesys.Resolve(ctx, p, namesys.ResolveWithDepth(1))
if err == namesys.ErrResolveRecursion {
err = nil
}
return p, err
return res.Path, err
}

return nil, NewErrorStatusCode(errors.New("not implemented"), http.StatusNotImplemented)
Expand Down Expand Up @@ -696,10 +697,11 @@ func (bb *BlocksBackend) ResolvePath(ctx context.Context, path path.ImmutablePat
func (bb *BlocksBackend) resolvePath(ctx context.Context, p path.Path) (path.ImmutablePath, []string, error) {
var err error
if p.Namespace() == path.IPNSNamespace {
p, err = resolve.ResolveIPNS(ctx, bb.namesys, p)
res, err := namesys.Resolve(ctx, bb.namesys, p)
if err != nil {
return path.ImmutablePath{}, nil, err
}
p = res.Path
}

if p.Namespace() != path.IPFSNamespace {
Expand Down
5 changes: 3 additions & 2 deletions gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"sort"
"strconv"
"strings"
"time"

"github.com/ipfs/boxo/files"
"github.com/ipfs/boxo/gateway/assets"
Expand Down Expand Up @@ -369,11 +370,11 @@ type IPFSBackend interface {
GetIPNSRecord(context.Context, cid.Cid) ([]byte, error)

// ResolveMutable takes a mutable path and resolves it into an immutable one. This means recursively resolving any
// DNSLink or IPNS records.
// DNSLink or IPNS records. It should also return a TTL. If the TTL is unknown, 0 should be returned.
//
// For example, given a mapping from `/ipns/dnslink.tld -> /ipns/ipns-id/mydirectory` and `/ipns/ipns-id` to
// `/ipfs/some-cid`, the result of passing `/ipns/dnslink.tld/myfile` would be `/ipfs/some-cid/mydirectory/myfile`.
ResolveMutable(context.Context, path.Path) (path.ImmutablePath, error)
ResolveMutable(context.Context, path.Path) (path.ImmutablePath, time.Duration, time.Time, error)

// GetDNSLinkRecord returns the DNSLink TXT record for the provided FQDN.
// Unlike ResolvePath, it does not perform recursive resolution. It only
Expand Down
Loading

0 comments on commit b635397

Please sign in to comment.