Merge pull request #10190 from ipfs/release-v0.24.0

Release: v0.24.0-1
This commit is contained in:
Henrique Dias 2023-11-01 11:37:31 +01:00 committed by GitHub
commit 50160f728e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
105 changed files with 1655 additions and 1885 deletions

View File

@ -54,7 +54,7 @@ jobs:
shell: bash
strategy:
matrix:
repo-to-test-against: ["helia", "helia-ipns", "helia-unixfs"] # this needs to be manually kept in sync as new helia tests are written
repo-to-test-against: ["helia", "helia-ipns", "helia-unixfs", "helia-car", "helia-dag-json", "helia-dag-cbor", "helia-json", "helia-mfs"] # this needs to be manually kept in sync as new helia tests are written
steps:
- uses: actions/setup-node@v3
with:
@ -94,43 +94,6 @@ jobs:
working-directory: interop/packages/interop
env:
KUBO_BINARY: ${{ github.workspace }}/cmd/ipfs/ipfs
go-ipfs-api:
needs: [interop-prep]
runs-on: ubuntu-latest
timeout-minutes: 5
env:
TEST_DOCKER: 0
TEST_FUSE: 0
TEST_VERBOSE: 1
TRAVIS: 1
GIT_PAGER: cat
IPFS_CHECK_RCMGR_DEFAULTS: 1
defaults:
run:
shell: bash
steps:
- uses: actions/setup-go@v4
with:
go-version: ${{ env.GO_VERSION }}
- uses: actions/download-artifact@v3
with:
name: kubo
path: cmd/ipfs
- run: chmod +x cmd/ipfs/ipfs
- uses: actions/checkout@v4
with:
repository: ipfs/go-ipfs-api
path: go-ipfs-api
- run: cmd/ipfs/ipfs daemon --init --enable-namesys-pubsub &
- run: |
while ! cmd/ipfs/ipfs id --api=/ip4/127.0.0.1/tcp/5001 2>/dev/null; do
sleep 1
done
timeout-minutes: 5
- run: go test -count=1 -v ./...
working-directory: go-ipfs-api
- run: cmd/ipfs/ipfs shutdown
if: always()
ipfs-webui:
needs: [interop-prep]
runs-on: ${{ fromJSON(github.repository == 'ipfs/kubo' && '["self-hosted", "linux", "x64", "2xlarge"]' || '"ubuntu-latest"') }}

View File

@ -1,5 +1,6 @@
# Kubo Changelogs
- [v0.24](docs/changelogs/v0.24.md)
- [v0.23](docs/changelogs/v0.23.md)
- [v0.22](docs/changelogs/v0.22.md)
- [v0.21](docs/changelogs/v0.21.md)

View File

@ -30,6 +30,7 @@ Featureset
- [HTTP Kubo RPC API](https://docs.ipfs.tech/reference/kubo/rpc/) (`/api/v0`) to access and control the daemon
- [Command Line Interface](https://docs.ipfs.tech/reference/kubo/cli/) based on (`/api/v0`) RPC API
- [WebUI](https://github.com/ipfs/ipfs-webui/#readme) to manage the Kubo node
- [Content blocking](/docs/content-blocking.md) support for operators of public nodes
### Other implementations
@ -88,7 +89,6 @@ Before opening an issue, consider using one of the following locations to ensure
- [Install Go](#install-go)
- [Download and Compile IPFS](#download-and-compile-ipfs)
- [Cross Compiling](#cross-compiling)
- [OpenSSL](#openssl)
- [Troubleshooting](#troubleshooting)
- [Getting Started](#getting-started)
- [Usage](#usage)
@ -327,15 +327,6 @@ Compiling for a different platform is as simple as running:
make build GOOS=myTargetOS GOARCH=myTargetArchitecture
```
##### OpenSSL
To build go-ipfs with OpenSSL support, append `GOTAGS=openssl` to your `make` invocation. Building with OpenSSL should significantly reduce the background CPU usage on nodes that frequently make or receive new connections.
Note: OpenSSL requires CGO support and, by default, CGO is disabled when cross-compiling. To cross-compile with OpenSSL support, you must:
1. Install a compiler toolchain for the target platform.
2. Set the `CGO_ENABLED=1` environment variable.
#### Troubleshooting
- Separate [instructions are available for building on Windows](docs/windows.md).

View File

@ -9,8 +9,8 @@ import (
"github.com/ipfs/kubo/core/coreapi"
options "github.com/ipfs/boxo/coreiface/options"
"github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/files"
"github.com/ipfs/boxo/path"
cid "github.com/ipfs/go-cid"
)
@ -44,7 +44,7 @@ func addAssetList(nd *core.IpfsNode, l []string) (cid.Cid, error) {
return cid.Cid{}, err
}
basePath := path.IpfsPath(dirb.Cid())
basePath := path.FromCid(dirb.Cid())
for _, p := range l {
d, err := Asset.ReadFile(p)
@ -69,5 +69,5 @@ func addAssetList(nd *core.IpfsNode, l []string) (cid.Cid, error) {
return cid.Cid{}, err
}
return basePath.Cid(), nil
return basePath.RootCid(), nil
}

View File

@ -12,8 +12,8 @@ import (
"time"
iface "github.com/ipfs/boxo/coreiface"
"github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/coreiface/tests"
"github.com/ipfs/boxo/path"
"github.com/ipfs/kubo/test/cli/harness"
ma "github.com/multiformats/go-multiaddr"
"go.uber.org/multierr"
@ -70,7 +70,11 @@ func (np NodeProvider) MakeAPISwarm(t *testing.T, ctx context.Context, fullIdent
apis[i] = api
// empty node is pinned even with --empty-repo, we don't want that
emptyNode := path.New("/ipfs/QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn")
emptyNode, err := path.NewPath("/ipfs/QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn")
if err != nil {
return err
}
if err := api.Pin().Rm(ctx, emptyNode); err != nil {
return err
}
@ -126,7 +130,11 @@ func Test_NewURLApiWithClient_With_Headers(t *testing.T) {
t.Fatal(err)
}
api.Headers.Set(headerToTest, expectedHeaderValue)
if err := api.Pin().Rm(context.Background(), path.New("/ipfs/QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv")); err != nil {
p, err := path.NewPath("/ipfs/QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv")
if err != nil {
t.Fatal(err)
}
if err := api.Pin().Rm(context.Background(), p); err != nil {
t.Fatal(err)
}
}

View File

@ -6,9 +6,9 @@ import (
"fmt"
"io"
"github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/files"
unixfs "github.com/ipfs/boxo/ipld/unixfs"
"github.com/ipfs/boxo/path"
"github.com/ipfs/go-cid"
)
@ -17,7 +17,7 @@ const forwardSeekLimit = 1 << 14 // 16k
func (api *UnixfsAPI) Get(ctx context.Context, p path.Path) (files.Node, error) {
if p.Mutable() { // use resolved path in case we are dealing with IPNS / MFS
var err error
p, err = api.core().ResolvePath(ctx, p)
p, _, err = api.core().ResolvePath(ctx, p)
if err != nil {
return nil, err
}
@ -195,13 +195,13 @@ func (it *apiIter) Next() bool {
switch it.cur.Type {
case unixfs.THAMTShard, unixfs.TMetadata, unixfs.TDirectory:
it.curFile, err = it.core.getDir(it.ctx, path.IpfsPath(c), int64(it.cur.Size))
it.curFile, err = it.core.getDir(it.ctx, path.FromCid(c), int64(it.cur.Size))
if err != nil {
it.err = err
return false
}
case unixfs.TFile:
it.curFile, err = it.core.getFile(it.ctx, path.IpfsPath(c), int64(it.cur.Size))
it.curFile, err = it.core.getFile(it.ctx, path.FromCid(c), int64(it.cur.Size))
if err != nil {
it.err = err
return false

View File

@ -8,7 +8,7 @@ import (
iface "github.com/ipfs/boxo/coreiface"
caopts "github.com/ipfs/boxo/coreiface/options"
"github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/path"
"github.com/ipfs/go-cid"
mc "github.com/multiformats/go-multicodec"
mh "github.com/multiformats/go-multihash"
@ -27,8 +27,8 @@ func (s *blockStat) Size() int {
return s.BSize
}
func (s *blockStat) Path() path.Resolved {
return path.IpldPath(s.cid)
func (s *blockStat) Path() path.ImmutablePath {
return path.FromCid(s.cid)
}
func (api *BlockAPI) Put(ctx context.Context, r io.Reader, opts ...caopts.BlockPutOption) (iface.BlockStat, error) {

View File

@ -7,8 +7,8 @@ import (
"io"
"github.com/ipfs/boxo/coreiface/options"
"github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/go-block-format"
"github.com/ipfs/boxo/path"
blocks "github.com/ipfs/go-block-format"
"github.com/ipfs/go-cid"
format "github.com/ipfs/go-ipld-format"
multicodec "github.com/multiformats/go-multicodec"
@ -21,7 +21,7 @@ type (
)
func (api *HttpDagServ) Get(ctx context.Context, c cid.Cid) (format.Node, error) {
r, err := api.core().Block().Get(ctx, path.IpldPath(c))
r, err := api.core().Block().Get(ctx, path.FromCid(c))
if err != nil {
return nil, err
}
@ -79,8 +79,8 @@ func (api *httpNodeAdder) add(ctx context.Context, nd format.Node, pin bool) err
if err != nil {
return err
}
if !stat.Path().Cid().Equals(c) {
return fmt.Errorf("cids didn't match - local %s, remote %s", c.String(), stat.Path().Cid().String())
if !stat.Path().RootCid().Equals(c) {
return fmt.Errorf("cids didn't match - local %s, remote %s", c.String(), stat.Path().RootCid().String())
}
return nil
}
@ -116,7 +116,7 @@ func (api *HttpDagServ) Pinning() format.NodeAdder {
}
func (api *HttpDagServ) Remove(ctx context.Context, c cid.Cid) error {
return api.core().Block().Rm(ctx, path.IpldPath(c)) // TODO: should we force rm?
return api.core().Block().Rm(ctx, path.FromCid(c)) // TODO: should we force rm?
}
func (api *HttpDagServ) RemoveMany(ctx context.Context, cids []cid.Cid) error {

View File

@ -5,7 +5,7 @@ import (
"encoding/json"
caopts "github.com/ipfs/boxo/coreiface/options"
"github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/path"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/routing"
)
@ -42,12 +42,12 @@ func (api *DhtAPI) FindProviders(ctx context.Context, p path.Path, opts ...caopt
return nil, err
}
rp, err := api.core().ResolvePath(ctx, p)
rp, _, err := api.core().ResolvePath(ctx, p)
if err != nil {
return nil, err
}
resp, err := api.core().Request("dht/findprovs", rp.Cid().String()).
resp, err := api.core().Request("dht/findprovs", rp.RootCid().String()).
Option("num-providers", options.NumProviders).
Send(ctx)
if err != nil {
@ -98,12 +98,12 @@ func (api *DhtAPI) Provide(ctx context.Context, p path.Path, opts ...caopts.DhtP
return err
}
rp, err := api.core().ResolvePath(ctx, p)
rp, _, err := api.core().ResolvePath(ctx, p)
if err != nil {
return err
}
return api.core().Request("dht/provide", rp.Cid().String()).
return api.core().Request("dht/provide", rp.RootCid().String()).
Option("recursive", options.Recursive).
Exec(ctx, nil)
}

View File

@ -6,31 +6,50 @@ import (
iface "github.com/ipfs/boxo/coreiface"
caopts "github.com/ipfs/boxo/coreiface/options"
"github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/ipns"
"github.com/ipfs/boxo/path"
"github.com/libp2p/go-libp2p/core/peer"
)
type KeyAPI HttpApi
type keyOutput struct {
JName string `json:"Name"`
Id string
pid peer.ID
type key struct {
name string
pid peer.ID
path path.Path
}
func (k *keyOutput) Name() string {
return k.JName
func newKey(name, pidStr string) (*key, error) {
pid, err := peer.Decode(pidStr)
if err != nil {
return nil, err
}
path, err := path.NewPath("/ipns/" + ipns.NameFromPeer(pid).String())
if err != nil {
return nil, err
}
return &key{name: name, pid: pid, path: path}, nil
}
func (k *keyOutput) Path() path.Path {
return path.New("/ipns/" + k.Id)
func (k *key) Name() string {
return k.name
}
func (k *keyOutput) ID() peer.ID {
func (k *key) Path() path.Path {
return k.path
}
func (k *key) ID() peer.ID {
return k.pid
}
type keyOutput struct {
Name string
Id string
}
func (api *KeyAPI) Generate(ctx context.Context, name string, opts ...caopts.KeyGenerateOption) (iface.Key, error) {
options, err := caopts.KeyGenerateOptions(opts...)
if err != nil {
@ -45,8 +64,8 @@ func (api *KeyAPI) Generate(ctx context.Context, name string, opts ...caopts.Key
if err != nil {
return nil, err
}
out.pid, err = peer.Decode(out.Id)
return &out, err
return newKey(out.Name, out.Id)
}
func (api *KeyAPI) Rename(ctx context.Context, oldName string, newName string, opts ...caopts.KeyRenameOption) (iface.Key, bool, error) {
@ -68,25 +87,29 @@ func (api *KeyAPI) Rename(ctx context.Context, oldName string, newName string, o
return nil, false, err
}
id := &keyOutput{JName: out.Now, Id: out.Id}
id.pid, err = peer.Decode(id.Id)
return id, out.Overwrite, err
key, err := newKey(out.Now, out.Id)
if err != nil {
return nil, false, err
}
return key, out.Overwrite, err
}
func (api *KeyAPI) List(ctx context.Context) ([]iface.Key, error) {
var out struct{ Keys []*keyOutput }
var out struct {
Keys []keyOutput
}
if err := api.core().Request("key/list").Exec(ctx, &out); err != nil {
return nil, err
}
res := make([]iface.Key, len(out.Keys))
for i, k := range out.Keys {
var err error
k.pid, err = peer.Decode(k.Id)
key, err := newKey(k.Name, k.Id)
if err != nil {
return nil, err
}
res[i] = k
res[i] = key
}
return res, nil
@ -98,14 +121,13 @@ func (api *KeyAPI) Self(ctx context.Context) (iface.Key, error) {
return nil, err
}
var err error
out := keyOutput{JName: "self", Id: id.ID}
out.pid, err = peer.Decode(out.Id)
return &out, err
return newKey("self", id.ID)
}
func (api *KeyAPI) Remove(ctx context.Context, name string) (iface.Key, error) {
var out struct{ Keys []keyOutput }
var out struct {
Keys []keyOutput
}
if err := api.core().Request("key/rm", name).Exec(ctx, &out); err != nil {
return nil, err
}
@ -113,9 +135,7 @@ func (api *KeyAPI) Remove(ctx context.Context, name string) (iface.Key, error) {
return nil, errors.New("got unexpected number of keys back")
}
var err error
out.Keys[0].pid, err = peer.Decode(out.Keys[0].Id)
return &out.Keys[0], err
return newKey(out.Keys[0].Name, out.Keys[0].Id)
}
func (api *KeyAPI) core() *HttpApi {

View File

@ -8,9 +8,9 @@ import (
iface "github.com/ipfs/boxo/coreiface"
caopts "github.com/ipfs/boxo/coreiface/options"
nsopts "github.com/ipfs/boxo/coreiface/options/namesys"
"github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/ipns"
"github.com/ipfs/boxo/namesys"
"github.com/ipfs/boxo/path"
)
type NameAPI HttpApi
@ -49,9 +49,9 @@ func (api *NameAPI) Search(ctx context.Context, name string, opts ...caopts.Name
return nil, err
}
ropts := nsopts.ProcessOpts(options.ResolveOpts)
if ropts.Depth != nsopts.DefaultDepthLimit && ropts.Depth != 1 {
return nil, fmt.Errorf("Name.Resolve: depth other than 1 or %d not supported", nsopts.DefaultDepthLimit)
ropts := namesys.ProcessResolveOptions(options.ResolveOpts)
if ropts.Depth != namesys.DefaultDepthLimit && ropts.Depth != 1 {
return nil, fmt.Errorf("Name.Resolve: depth other than 1 or %d not supported", namesys.DefaultDepthLimit)
}
req := api.core().Request("name/resolve", name).
@ -84,7 +84,11 @@ func (api *NameAPI) Search(ctx context.Context, name string, opts ...caopts.Name
}
var ires iface.IpnsResult
if err == nil {
ires.Path = path.New(out.Path)
p, err := path.NewPath(out.Path)
if err != nil {
return
}
ires.Path = p
}
select {
@ -106,9 +110,9 @@ func (api *NameAPI) Resolve(ctx context.Context, name string, opts ...caopts.Nam
return nil, err
}
ropts := nsopts.ProcessOpts(options.ResolveOpts)
if ropts.Depth != nsopts.DefaultDepthLimit && ropts.Depth != 1 {
return nil, fmt.Errorf("Name.Resolve: depth other than 1 or %d not supported", nsopts.DefaultDepthLimit)
ropts := namesys.ProcessResolveOptions(options.ResolveOpts)
if ropts.Depth != namesys.DefaultDepthLimit && ropts.Depth != 1 {
return nil, fmt.Errorf("Name.Resolve: depth other than 1 or %d not supported", namesys.DefaultDepthLimit)
}
req := api.core().Request("name/resolve", name).
@ -122,7 +126,7 @@ func (api *NameAPI) Resolve(ctx context.Context, name string, opts ...caopts.Nam
return nil, err
}
return path.New(out.Path), nil
return path.NewPath(out.Path)
}
func (api *NameAPI) core() *HttpApi {

View File

@ -8,9 +8,9 @@ import (
iface "github.com/ipfs/boxo/coreiface"
caopts "github.com/ipfs/boxo/coreiface/options"
"github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/ipld/merkledag"
ft "github.com/ipfs/boxo/ipld/unixfs"
"github.com/ipfs/boxo/path"
"github.com/ipfs/go-cid"
ipld "github.com/ipfs/go-ipld-format"
)
@ -40,10 +40,10 @@ func (api *ObjectAPI) New(ctx context.Context, opts ...caopts.ObjectNewOption) (
return n, nil
}
func (api *ObjectAPI) Put(ctx context.Context, r io.Reader, opts ...caopts.ObjectPutOption) (path.Resolved, error) {
func (api *ObjectAPI) Put(ctx context.Context, r io.Reader, opts ...caopts.ObjectPutOption) (path.ImmutablePath, error) {
options, err := caopts.ObjectPutOptions(opts...)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
var out objectOut
@ -54,15 +54,15 @@ func (api *ObjectAPI) Put(ctx context.Context, r io.Reader, opts ...caopts.Objec
FileBody(r).
Exec(ctx, &out)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
c, err := cid.Parse(out.Hash)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
return path.IpfsPath(c), nil
return path.FromCid(c), nil
}
func (api *ObjectAPI) Get(ctx context.Context, p path.Path) (ipld.Node, error) {
@ -153,10 +153,10 @@ func (api *ObjectAPI) Stat(ctx context.Context, p path.Path) (*iface.ObjectStat,
}, nil
}
func (api *ObjectAPI) AddLink(ctx context.Context, base path.Path, name string, child path.Path, opts ...caopts.ObjectAddLinkOption) (path.Resolved, error) {
func (api *ObjectAPI) AddLink(ctx context.Context, base path.Path, name string, child path.Path, opts ...caopts.ObjectAddLinkOption) (path.ImmutablePath, error) {
options, err := caopts.ObjectAddLinkOptions(opts...)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
var out objectOut
@ -164,65 +164,65 @@ func (api *ObjectAPI) AddLink(ctx context.Context, base path.Path, name string,
Option("create", options.Create).
Exec(ctx, &out)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
c, err := cid.Parse(out.Hash)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
return path.IpfsPath(c), nil
return path.FromCid(c), nil
}
func (api *ObjectAPI) RmLink(ctx context.Context, base path.Path, link string) (path.Resolved, error) {
func (api *ObjectAPI) RmLink(ctx context.Context, base path.Path, link string) (path.ImmutablePath, error) {
var out objectOut
err := api.core().Request("object/patch/rm-link", base.String(), link).
Exec(ctx, &out)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
c, err := cid.Parse(out.Hash)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
return path.IpfsPath(c), nil
return path.FromCid(c), nil
}
func (api *ObjectAPI) AppendData(ctx context.Context, p path.Path, r io.Reader) (path.Resolved, error) {
func (api *ObjectAPI) AppendData(ctx context.Context, p path.Path, r io.Reader) (path.ImmutablePath, error) {
var out objectOut
err := api.core().Request("object/patch/append-data", p.String()).
FileBody(r).
Exec(ctx, &out)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
c, err := cid.Parse(out.Hash)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
return path.IpfsPath(c), nil
return path.FromCid(c), nil
}
func (api *ObjectAPI) SetData(ctx context.Context, p path.Path, r io.Reader) (path.Resolved, error) {
func (api *ObjectAPI) SetData(ctx context.Context, p path.Path, r io.Reader) (path.ImmutablePath, error) {
var out objectOut
err := api.core().Request("object/patch/set-data", p.String()).
FileBody(r).
Exec(ctx, &out)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
c, err := cid.Parse(out.Hash)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
return path.IpfsPath(c), nil
return path.FromCid(c), nil
}
type change struct {
@ -246,10 +246,10 @@ func (api *ObjectAPI) Diff(ctx context.Context, a path.Path, b path.Path) ([]ifa
Path: ch.Path,
}
if ch.Before != cid.Undef {
res[i].Before = path.IpfsPath(ch.Before)
res[i].Before = path.FromCid(ch.Before)
}
if ch.After != cid.Undef {
res[i].After = path.IpfsPath(ch.After)
res[i].After = path.FromCid(ch.After)
}
}
return res, nil

View File

@ -3,50 +3,46 @@ package rpc
import (
"context"
"github.com/ipfs/boxo/coreiface/path"
ipfspath "github.com/ipfs/boxo/path"
"github.com/ipfs/boxo/path"
cid "github.com/ipfs/go-cid"
ipld "github.com/ipfs/go-ipld-format"
)
func (api *HttpApi) ResolvePath(ctx context.Context, p path.Path) (path.Resolved, error) {
func (api *HttpApi) ResolvePath(ctx context.Context, p path.Path) (path.ImmutablePath, []string, error) {
var out struct {
Cid cid.Cid
RemPath string
}
// TODO: this is hacky, fixing https://github.com/ipfs/go-ipfs/issues/5703 would help
var err error
if p.Namespace() == "ipns" {
if p.Namespace() == path.IPNSNamespace {
if p, err = api.Name().Resolve(ctx, p.String()); err != nil {
return nil, err
return path.ImmutablePath{}, nil, err
}
}
if err := api.Request("dag/resolve", p.String()).Exec(ctx, &out); err != nil {
return nil, err
return path.ImmutablePath{}, nil, err
}
// TODO:
ipath, err := ipfspath.FromSegments("/"+p.Namespace()+"/", out.Cid.String(), out.RemPath)
p, err = path.NewPathFromSegments(p.Namespace(), out.Cid.String(), out.RemPath)
if err != nil {
return nil, err
return path.ImmutablePath{}, nil, err
}
root, err := cid.Parse(ipfspath.Path(p.String()).Segments()[1])
imPath, err := path.NewImmutablePath(p)
if err != nil {
return nil, err
return path.ImmutablePath{}, nil, err
}
return path.NewResolvedPath(ipath, out.Cid, root, out.RemPath), nil
return imPath, path.StringToSegments(out.RemPath), nil
}
func (api *HttpApi) ResolveNode(ctx context.Context, p path.Path) (ipld.Node, error) {
rp, err := api.ResolvePath(ctx, p)
rp, _, err := api.ResolvePath(ctx, p)
if err != nil {
return nil, err
}
return api.Dag().Get(ctx, rp.Cid())
return api.Dag().Get(ctx, rp.RootCid())
}

View File

@ -8,7 +8,7 @@ import (
iface "github.com/ipfs/boxo/coreiface"
caopts "github.com/ipfs/boxo/coreiface/options"
"github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/path"
"github.com/ipfs/go-cid"
"github.com/pkg/errors"
)
@ -24,7 +24,7 @@ type pinRefKeyList struct {
}
type pin struct {
path path.Resolved
path path.ImmutablePath
typ string
err error
}
@ -33,7 +33,7 @@ func (p pin) Err() error {
return p.err
}
func (p pin) Path() path.Resolved {
func (p pin) Path() path.ImmutablePath {
return p.path
}
@ -102,7 +102,7 @@ func (api *PinAPI) Ls(ctx context.Context, opts ...caopts.PinLsOption) (<-chan i
}
select {
case ch <- pin{typ: out.Type, path: path.IpldPath(c)}:
case ch <- pin{typ: out.Type, path: path.FromCid(c)}:
case <-ctx.Done():
return
}
@ -182,8 +182,8 @@ type badNode struct {
cid cid.Cid
}
func (n badNode) Path() path.Resolved {
return path.IpldPath(n.cid)
func (n badNode) Path() path.ImmutablePath {
return path.FromCid(n.cid)
}
func (n badNode) Err() error {

View File

@ -9,10 +9,10 @@ import (
iface "github.com/ipfs/boxo/coreiface"
caopts "github.com/ipfs/boxo/coreiface/options"
"github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/files"
unixfs "github.com/ipfs/boxo/ipld/unixfs"
unixfs_pb "github.com/ipfs/boxo/ipld/unixfs/pb"
"github.com/ipfs/boxo/path"
"github.com/ipfs/go-cid"
mh "github.com/multiformats/go-multihash"
)
@ -26,15 +26,15 @@ type addEvent struct {
type UnixfsAPI HttpApi
func (api *UnixfsAPI) Add(ctx context.Context, f files.Node, opts ...caopts.UnixfsAddOption) (path.Resolved, error) {
func (api *UnixfsAPI) Add(ctx context.Context, f files.Node, opts ...caopts.UnixfsAddOption) (path.ImmutablePath, error) {
options, _, err := caopts.UnixfsAddOptions(opts...)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
mht, ok := mh.Codes[options.MhType]
if !ok {
return nil, fmt.Errorf("unknowm mhType %d", options.MhType)
return path.ImmutablePath{}, fmt.Errorf("unknowm mhType %d", options.MhType)
}
req := api.core().Request("add").
@ -65,7 +65,7 @@ func (api *UnixfsAPI) Add(ctx context.Context, f files.Node, opts ...caopts.Unix
version, err := api.core().loadRemoteVersion()
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
useEncodedAbsPaths := version.LT(encodedAbsolutePathVersion)
req.Body(files.NewMultiFileReader(d, false, useEncodedAbsPaths))
@ -73,10 +73,10 @@ func (api *UnixfsAPI) Add(ctx context.Context, f files.Node, opts ...caopts.Unix
var out addEvent
resp, err := req.Send(ctx)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
if resp.Error != nil {
return nil, resp.Error
return path.ImmutablePath{}, resp.Error
}
defer resp.Output.Close()
dec := json.NewDecoder(resp.Output)
@ -88,7 +88,7 @@ loop:
case io.EOF:
break loop
default:
return nil, err
return path.ImmutablePath{}, err
}
out = evt
@ -102,26 +102,26 @@ loop:
if out.Hash != "" {
c, err := cid.Parse(out.Hash)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
ifevt.Path = path.IpfsPath(c)
ifevt.Path = path.FromCid(c)
}
select {
case options.Events <- ifevt:
case <-ctx.Done():
return nil, ctx.Err()
return path.ImmutablePath{}, ctx.Err()
}
}
}
c, err := cid.Parse(out.Hash)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
return path.IpfsPath(c), nil
return path.FromCid(c), nil
}
type lsLink struct {

View File

@ -10,8 +10,8 @@ import (
coreiface "github.com/ipfs/boxo/coreiface"
"github.com/ipfs/boxo/coreiface/options"
ipath "github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/files"
"github.com/ipfs/boxo/path"
"github.com/ipfs/kubo/core"
"github.com/ipfs/kubo/core/coreapi"
"github.com/ipfs/kubo/repo/fsrepo/migrations"
@ -98,7 +98,7 @@ func addMigrationFiles(ctx context.Context, node *core.IpfsNode, paths []string,
// addMigrationPaths adds the files at paths to IPFS, optionally pinning
// them. This is done after connecting to the peer.
func addMigrationPaths(ctx context.Context, node *core.IpfsNode, peerInfo peer.AddrInfo, paths []ipath.Path, pin bool) error {
func addMigrationPaths(ctx context.Context, node *core.IpfsNode, peerInfo peer.AddrInfo, paths []path.Path, pin bool) error {
if len(paths) == 0 {
return errors.New("nothing downloaded by ipfs fetcher")
}
@ -142,7 +142,7 @@ func addMigrationPaths(ctx context.Context, node *core.IpfsNode, peerInfo peer.A
return nil
}
func ipfsGet(ctx context.Context, ufs coreiface.UnixfsAPI, ipfsPath ipath.Path) error {
func ipfsGet(ctx context.Context, ufs coreiface.UnixfsAPI, ipfsPath path.Path) error {
nd, err := ufs.Get(ctx, ipfsPath)
if err != nil {
return err

View File

@ -11,7 +11,7 @@ import (
"strings"
unixfs "github.com/ipfs/boxo/ipld/unixfs"
path "github.com/ipfs/boxo/path"
"github.com/ipfs/boxo/path"
assets "github.com/ipfs/kubo/assets"
oldcmds "github.com/ipfs/kubo/commands"
core "github.com/ipfs/kubo/core"

View File

@ -1,371 +0,0 @@
package bootstrap
import (
"context"
"errors"
"io"
"math/rand"
"sync"
"sync/atomic"
"time"
logging "github.com/ipfs/go-log"
"github.com/jbenet/goprocess"
goprocessctx "github.com/jbenet/goprocess/context"
periodicproc "github.com/jbenet/goprocess/periodic"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/peerstore"
"github.com/libp2p/go-libp2p/core/routing"
)
var log = logging.Logger("bootstrap")
// ErrNotEnoughBootstrapPeers signals that we do not have enough bootstrap
// peers to bootstrap correctly.
var ErrNotEnoughBootstrapPeers = errors.New("not enough bootstrap peers to bootstrap")
// BootstrapConfig specifies parameters used in an IpfsNode's network
// bootstrapping process.
type BootstrapConfig struct {
// MinPeerThreshold governs whether to bootstrap more connections. If the
// node has less open connections than this number, it will open connections
// to the bootstrap nodes. From there, the routing system should be able
// to use the connections to the bootstrap nodes to connect to even more
// peers. Routing systems like the IpfsDHT do so in their own Bootstrap
// process, which issues random queries to find more peers.
MinPeerThreshold int
// Period governs the periodic interval at which the node will
// attempt to bootstrap. The bootstrap process is not very expensive, so
// this threshold can afford to be small (<=30s).
Period time.Duration
// ConnectionTimeout determines how long to wait for a bootstrap
// connection attempt before cancelling it.
ConnectionTimeout time.Duration
// BootstrapPeers is a function that returns a set of bootstrap peers
// for the bootstrap process to use. This makes it possible for clients
// to control the peers the process uses at any moment.
BootstrapPeers func() []peer.AddrInfo
// BackupBootstrapInterval governs the periodic interval at which the node will
// attempt to save connected nodes to use as temporary bootstrap peers.
BackupBootstrapInterval time.Duration
// MaxBackupBootstrapSize controls the maximum number of peers we're saving
// as backup bootstrap peers.
MaxBackupBootstrapSize int
saveBackupBootstrapPeers func(context.Context, []peer.AddrInfo)
loadBackupBootstrapPeers func(context.Context) []peer.AddrInfo
}
// DefaultBootstrapConfig specifies default sane parameters for bootstrapping.
var DefaultBootstrapConfig = BootstrapConfig{
MinPeerThreshold: 4,
Period: 30 * time.Second,
ConnectionTimeout: (30 * time.Second) / 3, // Perod / 3
BackupBootstrapInterval: 1 * time.Hour,
MaxBackupBootstrapSize: 20,
}
// BootstrapConfigWithPeers creates a default BootstrapConfig configured with
// the specified peers, and optional functions to load and save backup peers.
func BootstrapConfigWithPeers(pis []peer.AddrInfo, options ...func(*BootstrapConfig)) BootstrapConfig {
cfg := DefaultBootstrapConfig
cfg.BootstrapPeers = func() []peer.AddrInfo {
return pis
}
for _, opt := range options {
opt(&cfg)
}
return cfg
}
// WithBackupPeers configures functions to load and save backup bootstrap peers.
func WithBackupPeers(load func(context.Context) []peer.AddrInfo, save func(context.Context, []peer.AddrInfo)) func(*BootstrapConfig) {
if save == nil && load != nil || save != nil && load == nil {
panic("both load and save backup bootstrap peers functions must be defined")
}
return func(cfg *BootstrapConfig) {
cfg.loadBackupBootstrapPeers = load
cfg.saveBackupBootstrapPeers = save
}
}
// BackupPeers returns the load and save backup peers functions.
func (cfg *BootstrapConfig) BackupPeers() (func(context.Context) []peer.AddrInfo, func(context.Context, []peer.AddrInfo)) {
return cfg.loadBackupBootstrapPeers, cfg.saveBackupBootstrapPeers
}
// SetBackupPeers sets the load and save backup peers functions.
func (cfg *BootstrapConfig) SetBackupPeers(load func(context.Context) []peer.AddrInfo, save func(context.Context, []peer.AddrInfo)) {
opt := WithBackupPeers(load, save)
opt(cfg)
}
// Bootstrap kicks off IpfsNode bootstrapping. This function will periodically
// check the number of open connections and -- if there are too few -- initiate
// connections to well-known bootstrap peers. It also kicks off subsystem
// bootstrapping (i.e. routing).
func Bootstrap(id peer.ID, host host.Host, rt routing.Routing, cfg BootstrapConfig) (io.Closer, error) {
// make a signal to wait for one bootstrap round to complete.
doneWithRound := make(chan struct{})
if len(cfg.BootstrapPeers()) == 0 {
// We *need* to bootstrap but we have no bootstrap peers
// configured *at all*, inform the user.
log.Warn("no bootstrap nodes configured: go-ipfs may have difficulty connecting to the network")
}
// the periodic bootstrap function -- the connection supervisor
periodic := func(worker goprocess.Process) {
ctx := goprocessctx.OnClosingContext(worker)
if err := bootstrapRound(ctx, host, cfg); err != nil {
log.Debugf("%s bootstrap error: %s", id, err)
}
// Exit the first call (triggered independently by `proc.Go`, not `Tick`)
// only after being done with the *single* Routing.Bootstrap call. Following
// periodic calls (`Tick`) will not block on this.
<-doneWithRound
}
// kick off the node's periodic bootstrapping
proc := periodicproc.Tick(cfg.Period, periodic)
proc.Go(periodic) // run one right now.
// kick off Routing.Bootstrap
if rt != nil {
ctx := goprocessctx.OnClosingContext(proc)
if err := rt.Bootstrap(ctx); err != nil {
proc.Close()
return nil, err
}
}
doneWithRound <- struct{}{}
close(doneWithRound) // it no longer blocks periodic
// If loadBackupBootstrapPeers is not nil then saveBackupBootstrapPeers
// must also not be nil.
if cfg.loadBackupBootstrapPeers != nil {
startSavePeersAsTemporaryBootstrapProc(cfg, host, proc)
}
return proc, nil
}
// Aside of the main bootstrap process we also run a secondary one that saves
// connected peers as a backup measure if we can't connect to the official
// bootstrap ones. These peers will serve as *temporary* bootstrap nodes.
func startSavePeersAsTemporaryBootstrapProc(cfg BootstrapConfig, host host.Host, bootstrapProc goprocess.Process) {
savePeersFn := func(worker goprocess.Process) {
ctx := goprocessctx.OnClosingContext(worker)
if err := saveConnectedPeersAsTemporaryBootstrap(ctx, host, cfg); err != nil {
log.Debugf("saveConnectedPeersAsTemporaryBootstrap error: %s", err)
}
}
savePeersProc := periodicproc.Tick(cfg.BackupBootstrapInterval, savePeersFn)
// When the main bootstrap process ends also terminate the 'save connected
// peers' ones. Coupling the two seems the easiest way to handle this backup
// process without additional complexity.
go func() {
<-bootstrapProc.Closing()
savePeersProc.Close()
}()
// Run the first round now (after the first bootstrap process has finished)
// as the SavePeersPeriod can be much longer than bootstrap.
savePeersProc.Go(savePeersFn)
}
func saveConnectedPeersAsTemporaryBootstrap(ctx context.Context, host host.Host, cfg BootstrapConfig) error {
// Randomize the list of connected peers, we don't prioritize anyone.
connectedPeers := randomizeList(host.Network().Peers())
bootstrapPeers := cfg.BootstrapPeers()
backupPeers := make([]peer.AddrInfo, 0, cfg.MaxBackupBootstrapSize)
foundPeers := make(map[peer.ID]struct{}, cfg.MaxBackupBootstrapSize+len(bootstrapPeers))
// Don't record bootstrap peers
for _, b := range bootstrapPeers {
foundPeers[b.ID] = struct{}{}
}
// Choose peers to save and filter out the ones that are already bootstrap nodes.
for _, p := range connectedPeers {
if _, found := foundPeers[p]; found {
continue
}
foundPeers[p] = struct{}{}
backupPeers = append(backupPeers, peer.AddrInfo{
ID: p,
Addrs: host.Network().Peerstore().Addrs(p),
})
if len(backupPeers) >= cfg.MaxBackupBootstrapSize {
break
}
}
// If we didn't reach the target number use previously stored connected peers.
if len(backupPeers) < cfg.MaxBackupBootstrapSize {
oldSavedPeers := cfg.loadBackupBootstrapPeers(ctx)
log.Debugf("missing %d peers to reach backup bootstrap target of %d, trying from previous list of %d saved peers",
cfg.MaxBackupBootstrapSize-len(backupPeers), cfg.MaxBackupBootstrapSize, len(oldSavedPeers))
// Add some of the old saved peers. Ensure we don't duplicate them.
for _, p := range oldSavedPeers {
if _, found := foundPeers[p.ID]; found {
continue
}
foundPeers[p.ID] = struct{}{}
backupPeers = append(backupPeers, p)
if len(backupPeers) >= cfg.MaxBackupBootstrapSize {
break
}
}
}
cfg.saveBackupBootstrapPeers(ctx, backupPeers)
log.Debugf("saved %d peers (of %d target) as bootstrap backup in the config", len(backupPeers), cfg.MaxBackupBootstrapSize)
return nil
}
// Connect to as many peers needed to reach the BootstrapConfig.MinPeerThreshold.
// Peers can be original bootstrap or temporary ones (drawn from a list of
// persisted previously connected peers).
func bootstrapRound(ctx context.Context, host host.Host, cfg BootstrapConfig) error {
ctx, cancel := context.WithTimeout(ctx, cfg.ConnectionTimeout)
defer cancel()
id := host.ID()
// get bootstrap peers from config. retrieving them here makes
// sure we remain observant of changes to client configuration.
peers := cfg.BootstrapPeers()
// determine how many bootstrap connections to open
connected := host.Network().Peers()
if len(connected) >= cfg.MinPeerThreshold {
log.Debugf("%s core bootstrap skipped -- connected to %d (> %d) nodes",
id, len(connected), cfg.MinPeerThreshold)
return nil
}
numToDial := cfg.MinPeerThreshold - len(connected) // numToDial > 0
if len(peers) > 0 {
numToDial -= int(peersConnect(ctx, host, peers, numToDial, true))
if numToDial <= 0 {
return nil
}
}
if cfg.loadBackupBootstrapPeers == nil {
log.Debugf("not enough bootstrap peers to fill the remaining target of %d connections", numToDial)
return ErrNotEnoughBootstrapPeers
}
log.Debugf("not enough bootstrap peers to fill the remaining target of %d connections, trying backup list", numToDial)
tempBootstrapPeers := cfg.loadBackupBootstrapPeers(ctx)
if len(tempBootstrapPeers) > 0 {
numToDial -= int(peersConnect(ctx, host, tempBootstrapPeers, numToDial, false))
if numToDial <= 0 {
return nil
}
}
log.Debugf("tried both original bootstrap peers and temporary ones but still missing target of %d connections", numToDial)
return ErrNotEnoughBootstrapPeers
}
// Attempt to make `needed` connections from the `availablePeers` list. Mark
// peers as either `permanent` or temporary when adding them to the Peerstore.
// Return the number of connections completed. We eagerly over-connect in parallel,
// so we might connect to more than needed.
// (We spawn as many routines and attempt connections as the number of availablePeers,
// but this list comes from restricted sets of original or temporary bootstrap
// nodes which will keep it under a sane value.)
func peersConnect(ctx context.Context, ph host.Host, availablePeers []peer.AddrInfo, needed int, permanent bool) uint64 {
peers := randomizeList(availablePeers)
// Monitor the number of connections and stop if we reach the target.
var connected uint64
ctx, cancel := context.WithCancel(ctx)
defer cancel()
go func() {
for {
select {
case <-ctx.Done():
return
case <-time.After(1 * time.Second):
if int(atomic.LoadUint64(&connected)) >= needed {
cancel()
return
}
}
}
}()
var wg sync.WaitGroup
for _, p := range peers {
// performed asynchronously because when performed synchronously, if
// one `Connect` call hangs, subsequent calls are more likely to
// fail/abort due to an expiring context.
// Also, performed asynchronously for dial speed.
if int(atomic.LoadUint64(&connected)) >= needed {
cancel()
break
}
wg.Add(1)
go func(p peer.AddrInfo) {
defer wg.Done()
// Skip addresses belonging to a peer we're already connected to.
// (Not a guarantee but a best-effort policy.)
if ph.Network().Connectedness(p.ID) == network.Connected {
return
}
log.Debugf("%s bootstrapping to %s", ph.ID(), p.ID)
if err := ph.Connect(ctx, p); err != nil {
if ctx.Err() != context.Canceled {
log.Debugf("failed to bootstrap with %v: %s", p.ID, err)
}
return
}
if permanent {
// We're connecting to an original bootstrap peer, mark it as
// a permanent address (Connect will register it as TempAddrTTL).
ph.Peerstore().AddAddrs(p.ID, p.Addrs, peerstore.PermanentAddrTTL)
}
log.Infof("bootstrapped with %v", p.ID)
atomic.AddUint64(&connected, 1)
}(p)
}
wg.Wait()
return connected
}
func randomizeList[T any](in []T) []T {
out := make([]T, len(in))
for i, val := range rand.Perm(len(in)) {
out[i] = in[val]
}
return out
}

View File

@ -1,139 +0,0 @@
package bootstrap
import (
"context"
"crypto/rand"
"reflect"
"testing"
"time"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/test"
)
func TestRandomizeAddressList(t *testing.T) {
var ps []peer.AddrInfo
sizeofSlice := 10
for i := 0; i < sizeofSlice; i++ {
pid, err := test.RandPeerID()
if err != nil {
t.Fatal(err)
}
ps = append(ps, peer.AddrInfo{ID: pid})
}
out := randomizeList(ps)
if len(out) != len(ps) {
t.Fail()
}
}
func TestLoadAndSaveOptions(t *testing.T) {
loadFunc := func(_ context.Context) []peer.AddrInfo { return nil }
saveFunc := func(_ context.Context, _ []peer.AddrInfo) {}
bootCfg := BootstrapConfigWithPeers(nil, WithBackupPeers(loadFunc, saveFunc))
load, save := bootCfg.BackupPeers()
if load == nil {
t.Fatal("load function not assigned")
}
if reflect.ValueOf(load).Pointer() != reflect.ValueOf(loadFunc).Pointer() {
t.Fatal("load not assigned correct function")
}
if save == nil {
t.Fatal("save function not assigned")
}
if reflect.ValueOf(save).Pointer() != reflect.ValueOf(saveFunc).Pointer() {
t.Fatal("save not assigned correct function")
}
assertPanics(t, "with only load func", func() {
BootstrapConfigWithPeers(nil, WithBackupPeers(loadFunc, nil))
})
assertPanics(t, "with only save func", func() {
BootstrapConfigWithPeers(nil, WithBackupPeers(nil, saveFunc))
})
bootCfg = BootstrapConfigWithPeers(nil, WithBackupPeers(nil, nil))
load, save = bootCfg.BackupPeers()
if load != nil || save != nil {
t.Fatal("load and save functions should both be nil")
}
}
func TestSetBackupPeers(t *testing.T) {
loadFunc := func(_ context.Context) []peer.AddrInfo { return nil }
saveFunc := func(_ context.Context, _ []peer.AddrInfo) {}
bootCfg := DefaultBootstrapConfig
bootCfg.SetBackupPeers(loadFunc, saveFunc)
load, save := bootCfg.BackupPeers()
if load == nil {
t.Fatal("load function not assigned")
}
if reflect.ValueOf(load).Pointer() != reflect.ValueOf(loadFunc).Pointer() {
t.Fatal("load not assigned correct function")
}
if save == nil {
t.Fatal("save function not assigned")
}
if reflect.ValueOf(save).Pointer() != reflect.ValueOf(saveFunc).Pointer() {
t.Fatal("save not assigned correct function")
}
assertPanics(t, "with only load func", func() {
bootCfg.SetBackupPeers(loadFunc, nil)
})
assertPanics(t, "with only save func", func() {
bootCfg.SetBackupPeers(nil, saveFunc)
})
bootCfg.SetBackupPeers(nil, nil)
load, save = bootCfg.BackupPeers()
if load != nil || save != nil {
t.Fatal("load and save functions should both be nil")
}
}
func TestNoTempPeersLoadAndSave(t *testing.T) {
period := 500 * time.Millisecond
bootCfg := BootstrapConfigWithPeers(nil)
bootCfg.MinPeerThreshold = 2
bootCfg.Period = period
priv, pub, err := crypto.GenerateEd25519Key(rand.Reader)
if err != nil {
t.Fatal(err)
}
peerID, err := peer.IDFromPublicKey(pub)
if err != nil {
t.Fatal(err)
}
p2pHost, err := libp2p.New(libp2p.Identity(priv))
if err != nil {
t.Fatal(err)
}
bootstrapper, err := Bootstrap(peerID, p2pHost, nil, bootCfg)
if err != nil {
t.Fatal(err)
}
time.Sleep(4 * period)
bootstrapper.Close()
}
func assertPanics(t *testing.T, name string, f func()) {
defer func() {
if r := recover(); r == nil {
t.Errorf("%s: did not panic as expected", name)
}
}()
f()
}

View File

@ -7,7 +7,7 @@ import (
"sync"
"time"
"github.com/ipfs/kubo/core/bootstrap"
"github.com/ipfs/boxo/bootstrap"
"github.com/ipfs/kubo/core/node"
"github.com/ipfs/go-metrics-interface"

View File

@ -5,7 +5,7 @@ import (
"fmt"
"io"
"os"
"path"
gopath "path"
"strings"
"github.com/ipfs/kubo/core/commands/cmdenv"
@ -15,6 +15,7 @@ import (
"github.com/ipfs/boxo/coreiface/options"
"github.com/ipfs/boxo/files"
mfs "github.com/ipfs/boxo/mfs"
"github.com/ipfs/boxo/path"
cmds "github.com/ipfs/go-ipfs-cmds"
ipld "github.com/ipfs/go-ipld-format"
mh "github.com/multiformats/go-multihash"
@ -301,7 +302,7 @@ See 'dag export' and 'dag import' for more information.
return
}
// if MFS destination is a dir, append filename to the dir path
toFilesDst += path.Base(addit.Name())
toFilesDst += gopath.Base(addit.Name())
}
// error if we try to overwrite a preexisting file destination
@ -310,14 +311,14 @@ See 'dag export' and 'dag import' for more information.
return
}
_, err = mfs.Lookup(ipfsNode.FilesRoot, path.Dir(toFilesDst))
_, err = mfs.Lookup(ipfsNode.FilesRoot, gopath.Dir(toFilesDst))
if err != nil {
errCh <- fmt.Errorf("%s: MFS destination parent %q %q does not exist: %w", toFilesOptionName, toFilesDst, path.Dir(toFilesDst), err)
errCh <- fmt.Errorf("%s: MFS destination parent %q %q does not exist: %w", toFilesOptionName, toFilesDst, gopath.Dir(toFilesDst), err)
return
}
var nodeAdded ipld.Node
nodeAdded, err = api.Dag().Get(req.Context, pathAdded.Cid())
nodeAdded, err = api.Dag().Get(req.Context, pathAdded.RootCid())
if err != nil {
errCh <- err
return
@ -339,14 +340,14 @@ See 'dag export' and 'dag import' for more information.
}
h := ""
if output.Path != nil {
h = enc.Encode(output.Path.Cid())
if (output.Path != path.ImmutablePath{}) {
h = enc.Encode(output.Path.RootCid())
}
if !dir && addit.Name() != "" {
output.Name = addit.Name()
} else {
output.Name = path.Join(addit.Name(), output.Name)
output.Name = gopath.Join(addit.Name(), output.Name)
}
if err := res.Emit(&AddEvent{

View File

@ -12,7 +12,7 @@ import (
"github.com/ipfs/kubo/core/commands/cmdutils"
options "github.com/ipfs/boxo/coreiface/options"
path "github.com/ipfs/boxo/coreiface/path"
cmds "github.com/ipfs/go-ipfs-cmds"
mh "github.com/multiformats/go-multihash"
)
@ -66,13 +66,18 @@ on raw IPFS blocks. It outputs the following to stdout:
return err
}
b, err := api.Block().Stat(req.Context, path.New(req.Arguments[0]))
p, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return err
}
b, err := api.Block().Stat(req.Context, p)
if err != nil {
return err
}
return cmds.EmitOnce(res, &BlockStat{
Key: b.Path().Cid().String(),
Key: b.Path().RootCid().String(),
Size: b.Size(),
})
},
@ -103,7 +108,12 @@ It takes a <cid>, and outputs the block to stdout.
return err
}
r, err := api.Block().Get(req.Context, path.New(req.Arguments[0]))
p, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return err
}
r, err := api.Block().Get(req.Context, p)
if err != nil {
return err
}
@ -200,7 +210,7 @@ only for backward compatibility when a legacy CIDv0 is required (--format=v0).
}
err = res.Emit(&BlockStat{
Key: p.Path().Cid().String(),
Key: p.Path().RootCid().String(),
Size: p.Size(),
})
if err != nil {
@ -255,7 +265,12 @@ It takes a list of CIDs to remove from the local datastore..
// TODO: use batching coreapi when done
for _, b := range req.Arguments {
rp, err := api.ResolvePath(req.Context, path.New(b))
p, err := cmdutils.PathOrCidPath(b)
if err != nil {
return err
}
rp, _, err := api.ResolvePath(req.Context, p)
if err != nil {
return err
}
@ -263,7 +278,7 @@ It takes a list of CIDs to remove from the local datastore..
err = api.Block().Rm(req.Context, rp, options.Block.Force(force))
if err != nil {
if err := res.Emit(&removedBlock{
Hash: rp.Cid().String(),
Hash: rp.RootCid().String(),
Error: err.Error(),
}); err != nil {
return err
@ -273,7 +288,7 @@ It takes a list of CIDs to remove from the local datastore..
if !quiet {
err := res.Emit(&removedBlock{
Hash: rp.Cid().String(),
Hash: rp.RootCid().String(),
})
if err != nil {
return err

View File

@ -7,10 +7,10 @@ import (
"os"
"github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
"github.com/cheggaaa/pb"
iface "github.com/ipfs/boxo/coreiface"
"github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/files"
cmds "github.com/ipfs/go-ipfs-cmds"
)
@ -127,8 +127,13 @@ func cat(ctx context.Context, api iface.CoreAPI, paths []string, offset int64, m
if max == 0 {
return nil, 0, nil
}
for _, p := range paths {
f, err := api.Unixfs().Get(ctx, path.New(p))
for _, pString := range paths {
p, err := cmdutils.PathOrCidPath(pString)
if err != nil {
return nil, 0, err
}
f, err := api.Unixfs().Get(ctx, p)
if err != nil {
return nil, 0, err
}

View File

@ -6,6 +6,7 @@ import (
cmds "github.com/ipfs/go-ipfs-cmds"
coreiface "github.com/ipfs/boxo/coreiface"
"github.com/ipfs/boxo/path"
"github.com/ipfs/go-cid"
)
@ -48,3 +49,19 @@ func CheckBlockSize(req *cmds.Request, size uint64) error {
}
return nil
}
// PathOrCidPath returns a path.Path built from the argument. It keeps the old
// behaviour by building a path from a CID string.
func PathOrCidPath(str string) (path.Path, error) {
p, err := path.NewPath(str)
if err == nil {
return p, nil
}
if p, err := path.NewPath("/ipfs/" + str); err == nil {
return p, nil
}
// Send back original err.
return nil, err
}

View File

@ -5,11 +5,11 @@ import (
"encoding/json"
"fmt"
"io"
"path"
"github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
ipfspath "github.com/ipfs/boxo/path"
cid "github.com/ipfs/go-cid"
cidenc "github.com/ipfs/go-cidutil/cidenc"
cmds "github.com/ipfs/go-ipfs-cmds"
@ -157,7 +157,7 @@ var DagResolveCmd = &cmds.Command{
}
p := enc.Encode(out.Cid)
if out.RemPath != "" {
p = ipfspath.Join([]string{p, out.RemPath})
p = path.Join(p, out.RemPath)
}
fmt.Fprint(w, p)

View File

@ -14,6 +14,7 @@ import (
cid "github.com/ipfs/go-cid"
ipld "github.com/ipfs/go-ipld-format"
"github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
cmds "github.com/ipfs/go-ipfs-cmds"
gocar "github.com/ipld/go-car"
@ -21,12 +22,10 @@ import (
)
func dagExport(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
c, err := cid.Decode(req.Arguments[0])
// Accept CID or a content path
p, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return fmt.Errorf(
"unable to parse root specification (currently only bare CIDs are supported): %s",
err,
)
return err
}
api, err := cmdenv.GetApi(env, req)
@ -34,6 +33,13 @@ func dagExport(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment
return err
}
// Resolve path and confirm the root block is available, fail fast if not
b, err := api.Block().Stat(req.Context, p)
if err != nil {
return err
}
c := b.Path().RootCid()
pipeR, pipeW := io.Pipe()
errCh := make(chan error, 2) // we only report the 1st error

View File

@ -4,9 +4,10 @@ import (
"fmt"
"io"
"github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/path"
ipldlegacy "github.com/ipfs/go-ipld-legacy"
"github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
"github.com/ipld/go-ipld-prime"
"github.com/ipld/go-ipld-prime/multicodec"
@ -28,12 +29,17 @@ func dagGet(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) e
return err
}
rp, err := api.ResolvePath(req.Context, path.New(req.Arguments[0]))
p, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return err
}
obj, err := api.Dag().Get(req.Context, rp.Cid())
rp, remainder, err := api.ResolvePath(req.Context, p)
if err != nil {
return err
}
obj, err := api.Dag().Get(req.Context, rp.RootCid())
if err != nil {
return err
}
@ -45,8 +51,8 @@ func dagGet(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) e
finalNode := universal.(ipld.Node)
if len(rp.Remainder()) > 0 {
remainderPath := ipld.ParsePath(rp.Remainder())
if len(remainder) > 0 {
remainderPath := ipld.ParsePath(path.SegmentsToString(remainder...))
finalNode, err = traversal.Get(finalNode, remainderPath)
if err != nil {

View File

@ -1,8 +1,9 @@
package dagcmd
import (
"github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/path"
"github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
cmds "github.com/ipfs/go-ipfs-cmds"
)
@ -13,13 +14,18 @@ func dagResolve(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environmen
return err
}
rp, err := api.ResolvePath(req.Context, path.New(req.Arguments[0]))
p, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return err
}
rp, remainder, err := api.ResolvePath(req.Context, p)
if err != nil {
return err
}
return cmds.EmitOnce(res, &ResolveOutput{
Cid: rp.Cid(),
RemPath: rp.Remainder(),
Cid: rp.RootCid(),
RemPath: path.SegmentsToString(remainder...),
})
}

View File

@ -5,12 +5,12 @@ import (
"io"
"os"
"github.com/ipfs/boxo/coreiface/path"
mdag "github.com/ipfs/boxo/ipld/merkledag"
"github.com/ipfs/boxo/ipld/merkledag/traverse"
cid "github.com/ipfs/go-cid"
cmds "github.com/ipfs/go-ipfs-cmds"
"github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
"github.com/ipfs/kubo/core/commands/e"
)
@ -29,19 +29,23 @@ func dagStat(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment)
cidSet := cid.NewSet()
dagStatSummary := &DagStatSummary{DagStatsArray: []*DagStat{}}
for _, a := range req.Arguments {
rp, err := api.ResolvePath(req.Context, path.New(a))
p, err := cmdutils.PathOrCidPath(a)
if err != nil {
return err
}
if len(rp.Remainder()) > 0 {
rp, remainder, err := api.ResolvePath(req.Context, p)
if err != nil {
return err
}
if len(remainder) > 0 {
return fmt.Errorf("cannot return size for anything other than a DAG with a root CID")
}
obj, err := nodeGetter.Get(req.Context, rp.Cid())
obj, err := nodeGetter.Get(req.Context, rp.RootCid())
if err != nil {
return err
}
dagstats := &DagStat{Cid: rp.Cid()}
dagstats := &DagStat{Cid: rp.RootCid()}
dagStatSummary.appendStats(dagstats)
err = traverse.Traverse(obj, traverse.Options{
DAG: nodeGetter,

View File

@ -11,7 +11,7 @@ import (
func TestKeyTranslation(t *testing.T) {
pid := test.RandPeerIDFatal(t)
pkname := namesys.PkKeyForID(pid)
pkname := namesys.PkRoutingKey(pid)
ipnsname := ipns.NameFromPeer(pid).RoutingKey()
pkk, err := escapeDhtKey("/pk/" + pid.String())

View File

@ -4,8 +4,8 @@ import (
"fmt"
"io"
nsopts "github.com/ipfs/boxo/coreiface/options/namesys"
namesys "github.com/ipfs/boxo/namesys"
"github.com/ipfs/boxo/path"
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
ncmd "github.com/ipfs/kubo/core/commands/name"
@ -47,20 +47,25 @@ It will work across multiple DNSLinks and IPNS keys.
name := req.Arguments[0]
resolver := namesys.NewDNSResolver(node.DNSResolver.LookupTXT)
var routing []nsopts.ResolveOpt
var routing []namesys.ResolveOption
if !recursive {
routing = append(routing, nsopts.Depth(1))
routing = append(routing, namesys.ResolveWithDepth(1))
}
output, err := resolver.Resolve(req.Context, name, routing...)
p, err := path.NewPath(name)
if err != nil {
return err
}
val, err := resolver.Resolve(req.Context, p, routing...)
if err != nil && (recursive || err != namesys.ErrResolveRecursion) {
return err
}
return cmds.EmitOnce(res, &ncmd.ResolvedPath{Path: output})
return cmds.EmitOnce(res, &ncmd.ResolvedPath{Path: val.Path.String()})
},
Encoders: cmds.EncoderMap{
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *ncmd.ResolvedPath) error {
fmt.Fprintln(w, cmdenv.EscNonPrint(out.Path.String()))
fmt.Fprintln(w, cmdenv.EscNonPrint(out.Path))
return nil
}),
},

View File

@ -16,11 +16,11 @@ import (
bservice "github.com/ipfs/boxo/blockservice"
iface "github.com/ipfs/boxo/coreiface"
path "github.com/ipfs/boxo/coreiface/path"
offline "github.com/ipfs/boxo/exchange/offline"
dag "github.com/ipfs/boxo/ipld/merkledag"
ft "github.com/ipfs/boxo/ipld/unixfs"
mfs "github.com/ipfs/boxo/mfs"
"github.com/ipfs/boxo/path"
cid "github.com/ipfs/go-cid"
cidenc "github.com/ipfs/go-cidutil/cidenc"
cmds "github.com/ipfs/go-ipfs-cmds"
@ -423,7 +423,12 @@ being GC'ed.
func getNodeFromPath(ctx context.Context, node *core.IpfsNode, api iface.CoreAPI, p string) (ipld.Node, error) {
switch {
case strings.HasPrefix(p, "/ipfs/"):
return api.ResolveNode(ctx, path.New(p))
pth, err := path.NewPath(p)
if err != nil {
return nil, err
}
return api.ResolveNode(ctx, pth)
default:
fsn, err := mfs.Lookup(node.FilesRoot, p)
if err != nil {

View File

@ -12,10 +12,10 @@ import (
"strings"
"github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
"github.com/ipfs/kubo/core/commands/e"
"github.com/cheggaaa/pb"
"github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/files"
"github.com/ipfs/boxo/tar"
cmds "github.com/ipfs/go-ipfs-cmds"
@ -72,7 +72,10 @@ may also specify the level of compression by specifying '-l=<1-9>'.
return err
}
p := path.New(req.Arguments[0])
p, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return err
}
file, err := api.Unixfs().Get(ctx, p)
if err != nil {

View File

@ -8,10 +8,10 @@ import (
"text/tabwriter"
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
iface "github.com/ipfs/boxo/coreiface"
options "github.com/ipfs/boxo/coreiface/options"
path "github.com/ipfs/boxo/coreiface/path"
unixfs "github.com/ipfs/boxo/ipld/unixfs"
unixfs_pb "github.com/ipfs/boxo/ipld/unixfs/pb"
cmds "github.com/ipfs/go-ipfs-cmds"
@ -131,7 +131,12 @@ The JSON output contains type information.
}
for i, fpath := range paths {
results, err := api.Unixfs().Ls(req.Context, path.New(fpath),
pth, err := cmdutils.PathOrCidPath(fpath)
if err != nil {
return err
}
results, err := api.Unixfs().Ls(req.Context, pth,
options.Unixfs.ResolveChildren(resolveSize || resolveType))
if err != nil {
return err

View File

@ -7,20 +7,18 @@ import (
"strings"
"time"
namesys "github.com/ipfs/boxo/namesys"
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
options "github.com/ipfs/boxo/coreiface/options"
nsopts "github.com/ipfs/boxo/coreiface/options/namesys"
path "github.com/ipfs/boxo/path"
"github.com/ipfs/boxo/namesys"
"github.com/ipfs/boxo/path"
cmds "github.com/ipfs/go-ipfs-cmds"
logging "github.com/ipfs/go-log"
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
)
var log = logging.Logger("core/commands/ipns")
type ResolvedPath struct {
Path path.Path
Path string
}
const (
@ -75,8 +73,8 @@ Resolve the value of a dnslink:
Options: []cmds.Option{
cmds.BoolOption(recursiveOptionName, "r", "Resolve until the result is not an IPNS name.").WithDefault(true),
cmds.BoolOption(nocacheOptionName, "n", "Do not use cached entries."),
cmds.UintOption(dhtRecordCountOptionName, "dhtrc", "Number of records to request for DHT resolution."),
cmds.StringOption(dhtTimeoutOptionName, "dhtt", "Max time to collect values during DHT resolution eg \"30s\". Pass 0 for no timeout."),
cmds.UintOption(dhtRecordCountOptionName, "dhtrc", "Number of records to request for DHT resolution.").WithDefault(uint(namesys.DefaultResolverDhtRecordCount)),
cmds.StringOption(dhtTimeoutOptionName, "dhtt", "Max time to collect values during DHT resolution eg \"30s\". Pass 0 for no timeout.").WithDefault(namesys.DefaultResolverDhtTimeout.String()),
cmds.BoolOption(streamOptionName, "s", "Stream entries as they are found."),
},
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
@ -108,10 +106,10 @@ Resolve the value of a dnslink:
}
if !recursive {
opts = append(opts, options.Name.ResolveOption(nsopts.Depth(1)))
opts = append(opts, options.Name.ResolveOption(namesys.ResolveWithDepth(1)))
}
if rcok {
opts = append(opts, options.Name.ResolveOption(nsopts.DhtRecordCount(rc)))
opts = append(opts, options.Name.ResolveOption(namesys.ResolveWithDhtRecordCount(rc)))
}
if dhttok {
d, err := time.ParseDuration(dhtt)
@ -121,7 +119,7 @@ Resolve the value of a dnslink:
if d < 0 {
return errors.New("DHT timeout value must be >= 0")
}
opts = append(opts, options.Name.ResolveOption(nsopts.DhtTimeout(d)))
opts = append(opts, options.Name.ResolveOption(namesys.ResolveWithDhtTimeout(d)))
}
if !strings.HasPrefix(name, "/ipns/") {
@ -134,7 +132,12 @@ Resolve the value of a dnslink:
return err
}
return cmds.EmitOnce(res, &ResolvedPath{path.FromString(output.String())})
pth, err := path.NewPath(output.String())
if err != nil {
return err
}
return cmds.EmitOnce(res, &ResolvedPath{pth.String()})
}
output, err := api.Name().Search(req.Context, name, opts...)
@ -146,7 +149,7 @@ Resolve the value of a dnslink:
if v.Err != nil && (recursive || v.Err != namesys.ErrResolveRecursion) {
return v.Err
}
if err := res.Emit(&ResolvedPath{path.FromString(v.Path.String())}); err != nil {
if err := res.Emit(&ResolvedPath{v.Path.String()}); err != nil {
return err
}

View File

@ -10,7 +10,6 @@ import (
"github.com/ipfs/boxo/ipns"
ipns_pb "github.com/ipfs/boxo/ipns/pb"
"github.com/ipfs/boxo/path"
cmds "github.com/ipfs/go-ipfs-cmds"
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
"google.golang.org/protobuf/proto"
@ -87,7 +86,7 @@ type IpnsInspectValidation struct {
// IpnsInspectEntry contains the deserialized values from an IPNS Entry:
// https://github.com/ipfs/specs/blob/main/ipns/IPNS.md#record-serialization-format
type IpnsInspectEntry struct {
Value *path.Path
Value string
ValidityType *ipns.ValidityType
Validity *time.Time
Sequence *uint64
@ -157,7 +156,7 @@ Passing --verify will verify signature against provided public key.
// Best effort to get the fields. Show everything we can.
if v, err := rec.Value(); err == nil {
result.Entry.Value = &v
result.Entry.Value = v.String()
}
if v, err := rec.ValidityType(); err == nil {
@ -221,8 +220,8 @@ Passing --verify will verify signature against provided public key.
tw := tabwriter.NewWriter(w, 0, 0, 1, ' ', 0)
defer tw.Flush()
if out.Entry.Value != nil {
fmt.Fprintf(tw, "Value:\t%q\n", out.Entry.Value.String())
if out.Entry.Value != "" {
fmt.Fprintf(tw, "Value:\t%q\n", out.Entry.Value)
}
if out.Entry.ValidityType != nil {

View File

@ -7,10 +7,11 @@ import (
"time"
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
iface "github.com/ipfs/boxo/coreiface"
options "github.com/ipfs/boxo/coreiface/options"
path "github.com/ipfs/boxo/coreiface/path"
ipns "github.com/ipfs/boxo/ipns"
cmds "github.com/ipfs/go-ipfs-cmds"
ke "github.com/ipfs/kubo/core/commands/keyencode"
)
@ -59,7 +60,7 @@ Publish an <ipfs-path> with another name, added by an 'ipfs key' command:
> ipfs name publish --key=mykey /ipfs/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
Published to QmSrPmbaUKA3ZodhzPWZnpFgcPMFWF4QsxXbkWfEptTBJd: /ipfs/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
'ipfs key list -l'):
> ipfs name publish --key=QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n /ipfs/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
@ -72,16 +73,13 @@ Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
cmds.StringArg(ipfsPathOptionName, true, false, "ipfs path of the object to be published.").EnableStdin(),
},
Options: []cmds.Option{
cmds.BoolOption(resolveOptionName, "Check if the given path can be resolved before publishing.").WithDefault(true),
cmds.StringOption(lifeTimeOptionName, "t",
`Time duration that the record will be valid for. <<default>>
This accepts durations such as "300s", "1.5h" or "2h45m". Valid time units are
"ns", "us" (or "µs"), "ms", "s", "m", "h".`).WithDefault("24h"),
cmds.BoolOption(allowOfflineOptionName, "When offline, save the IPNS record to the the local datastore without broadcasting to the network instead of simply failing."),
cmds.StringOption(ttlOptionName, "Time duration this record should be cached for. Uses the same syntax as the lifetime option. (caution: experimental)"),
cmds.StringOption(keyOptionName, "k", "Name of the key to be used or a valid PeerID, as listed by 'ipfs key list -l'.").WithDefault("self"),
cmds.BoolOption(quieterOptionName, "Q", "Write only final hash."),
cmds.BoolOption(resolveOptionName, "Check if the given path can be resolved before publishing.").WithDefault(true),
cmds.StringOption(lifeTimeOptionName, "t", `Time duration the signed record will be valid for. Accepts durations such as "300s", "1.5h" or "7d2h45m"`).WithDefault(ipns.DefaultRecordLifetime.String()),
cmds.StringOption(ttlOptionName, "Time duration hint, akin to --lifetime, indicating how long to cache this record before checking for updates.").WithDefault(ipns.DefaultRecordTTL.String()),
cmds.BoolOption(quieterOptionName, "Q", "Write only final IPNS Name encoded as CIDv1 (for use in /ipns content paths)."),
cmds.BoolOption(v1compatOptionName, "Produce a backward-compatible IPNS Record by including fields for both V1 and V2 signatures.").WithDefault(true),
cmds.BoolOption(allowOfflineOptionName, "When --offline, save the IPNS record to the the local datastore without broadcasting to the network (instead of failing)."),
ke.OptionIPNSBase,
},
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
@ -116,7 +114,10 @@ Alternatively, publish an <ipfs-path> using a valid PeerID (as listed by
opts = append(opts, options.Name.TTL(d))
}
p := path.New(req.Arguments[0])
p, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return err
}
if verifyExists, _ := req.Options[resolveOptionName].(bool); verifyExists {
_, err := api.ResolveNode(req.Context, p)

View File

@ -4,11 +4,12 @@ import (
"fmt"
"io"
path "github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/ipld/merkledag/dagutils"
"github.com/ipfs/boxo/path"
cmds "github.com/ipfs/go-ipfs-cmds"
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
)
const (
@ -60,8 +61,15 @@ Example:
return err
}
pa := path.New(req.Arguments[0])
pb := path.New(req.Arguments[1])
pa, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return err
}
pb, err := cmdutils.PathOrCidPath(req.Arguments[1])
if err != nil {
return err
}
changes, err := api.Object().Diff(req.Context, pa, pb)
if err != nil {
@ -75,12 +83,12 @@ Example:
Path: change.Path,
}
if change.Before != nil {
out[i].Before = change.Before.Cid()
if (change.Before != path.ImmutablePath{}) {
out[i].Before = change.Before.RootCid()
}
if change.After != nil {
out[i].After = change.After.Cid()
if (change.After != path.ImmutablePath{}) {
out[i].After = change.After.RootCid()
}
}

View File

@ -9,10 +9,10 @@ import (
cmds "github.com/ipfs/go-ipfs-cmds"
"github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
humanize "github.com/dustin/go-humanize"
"github.com/ipfs/boxo/coreiface/options"
path "github.com/ipfs/boxo/coreiface/path"
dag "github.com/ipfs/boxo/ipld/merkledag"
"github.com/ipfs/go-cid"
ipld "github.com/ipfs/go-ipld-format"
@ -95,7 +95,10 @@ is the raw data of the object.
return err
}
path := path.New(req.Arguments[0])
path, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return err
}
data, err := api.Object().Data(req.Context, path)
if err != nil {
@ -135,9 +138,12 @@ multihash. Provided for legacy reasons. Use 'ipfs dag get' instead.
return err
}
path := path.New(req.Arguments[0])
path, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return err
}
rp, err := api.ResolvePath(req.Context, path)
rp, _, err := api.ResolvePath(req.Context, path)
if err != nil {
return err
}
@ -157,7 +163,7 @@ multihash. Provided for legacy reasons. Use 'ipfs dag get' instead.
}
out := &Object{
Hash: enc.Encode(rp.Cid()),
Hash: enc.Encode(rp.RootCid()),
Links: outLinks,
}
@ -212,7 +218,10 @@ DEPRECATED and provided for legacy reasons. Use 'ipfs dag get' instead.
return err
}
path := path.New(req.Arguments[0])
path, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return err
}
datafieldenc, _ := req.Options[encodingOptionName].(string)
if err != nil {
@ -333,7 +342,12 @@ DEPRECATED: Provided for legacy reasons. Modern replacements:
return err
}
ns, err := api.Object().Stat(req.Context, path.New(req.Arguments[0]))
p, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return err
}
ns, err := api.Object().Stat(req.Context, p)
if err != nil {
return err
}
@ -434,7 +448,7 @@ DEPRECATED and provided for legacy reasons. Use 'ipfs dag put' instead.
return err
}
return cmds.EmitOnce(res, &Object{Hash: enc.Encode(p.Cid())})
return cmds.EmitOnce(res, &Object{Hash: enc.Encode(p.RootCid())})
},
Encoders: cmds.EncoderMap{
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *Object) error {

View File

@ -9,7 +9,6 @@ import (
"github.com/ipfs/kubo/core/commands/cmdutils"
"github.com/ipfs/boxo/coreiface/options"
"github.com/ipfs/boxo/coreiface/path"
)
var ObjectPatchCmd = &cmds.Command{
@ -76,7 +75,10 @@ DEPRECATED and provided for legacy reasons. Use 'ipfs add' or 'ipfs files' inste
return err
}
root := path.New(req.Arguments[0])
root, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return err
}
file, err := cmdenv.GetFileArg(req.Files.Entries())
if err != nil {
@ -88,11 +90,11 @@ DEPRECATED and provided for legacy reasons. Use 'ipfs add' or 'ipfs files' inste
return err
}
if err := cmdutils.CheckCIDSize(req, p.Cid(), api.Dag()); err != nil {
if err := cmdutils.CheckCIDSize(req, p.RootCid(), api.Dag()); err != nil {
return err
}
return cmds.EmitOnce(res, &Object{Hash: p.Cid().String()})
return cmds.EmitOnce(res, &Object{Hash: p.RootCid().String()})
},
Type: &Object{},
Encoders: cmds.EncoderMap{
@ -127,7 +129,10 @@ DEPRECATED and provided for legacy reasons. Use 'files cp' and 'dag put' instead
return err
}
root := path.New(req.Arguments[0])
root, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return err
}
file, err := cmdenv.GetFileArg(req.Files.Entries())
if err != nil {
@ -139,11 +144,11 @@ DEPRECATED and provided for legacy reasons. Use 'files cp' and 'dag put' instead
return err
}
if err := cmdutils.CheckCIDSize(req, p.Cid(), api.Dag()); err != nil {
if err := cmdutils.CheckCIDSize(req, p.RootCid(), api.Dag()); err != nil {
return err
}
return cmds.EmitOnce(res, &Object{Hash: p.Cid().String()})
return cmds.EmitOnce(res, &Object{Hash: p.RootCid().String()})
},
Type: Object{},
Encoders: cmds.EncoderMap{
@ -174,7 +179,10 @@ DEPRECATED and provided for legacy reasons. Use 'files rm' instead.
return err
}
root := path.New(req.Arguments[0])
root, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return err
}
name := req.Arguments[1]
p, err := api.Object().RmLink(req.Context, root, name)
@ -182,11 +190,11 @@ DEPRECATED and provided for legacy reasons. Use 'files rm' instead.
return err
}
if err := cmdutils.CheckCIDSize(req, p.Cid(), api.Dag()); err != nil {
if err := cmdutils.CheckCIDSize(req, p.RootCid(), api.Dag()); err != nil {
return err
}
return cmds.EmitOnce(res, &Object{Hash: p.Cid().String()})
return cmds.EmitOnce(res, &Object{Hash: p.RootCid().String()})
},
Type: Object{},
Encoders: cmds.EncoderMap{
@ -238,9 +246,17 @@ Use MFS and 'files' commands instead:
return err
}
root := path.New(req.Arguments[0])
root, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return err
}
name := req.Arguments[1]
child := path.New(req.Arguments[2])
child, err := cmdutils.PathOrCidPath(req.Arguments[2])
if err != nil {
return err
}
create, _ := req.Options[createOptionName].(bool)
if err != nil {
@ -253,11 +269,11 @@ Use MFS and 'files' commands instead:
return err
}
if err := cmdutils.CheckCIDSize(req, p.Cid(), api.Dag()); err != nil {
if err := cmdutils.CheckCIDSize(req, p.RootCid(), api.Dag()); err != nil {
return err
}
return cmds.EmitOnce(res, &Object{Hash: p.Cid().String()})
return cmds.EmitOnce(res, &Object{Hash: p.RootCid().String()})
},
Type: Object{},
Encoders: cmds.EncoderMap{

View File

@ -11,7 +11,6 @@ import (
bserv "github.com/ipfs/boxo/blockservice"
coreiface "github.com/ipfs/boxo/coreiface"
options "github.com/ipfs/boxo/coreiface/options"
"github.com/ipfs/boxo/coreiface/path"
offline "github.com/ipfs/boxo/exchange/offline"
dag "github.com/ipfs/boxo/ipld/merkledag"
verifcid "github.com/ipfs/boxo/verifcid"
@ -21,6 +20,7 @@ import (
core "github.com/ipfs/kubo/core"
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
e "github.com/ipfs/kubo/core/commands/e"
)
@ -184,7 +184,12 @@ var addPinCmd = &cmds.Command{
func pinAddMany(ctx context.Context, api coreiface.CoreAPI, enc cidenc.Encoder, paths []string, recursive bool) ([]string, error) {
added := make([]string, len(paths))
for i, b := range paths {
rp, err := api.ResolvePath(ctx, path.New(b))
p, err := cmdutils.PathOrCidPath(b)
if err != nil {
return nil, err
}
rp, _, err := api.ResolvePath(ctx, p)
if err != nil {
return nil, err
}
@ -192,7 +197,7 @@ func pinAddMany(ctx context.Context, api coreiface.CoreAPI, enc cidenc.Encoder,
if err := api.Pin().Add(ctx, rp, options.Pin.Recursive(recursive)); err != nil {
return nil, err
}
added[i] = enc.Encode(rp.Cid())
added[i] = enc.Encode(rp.RootCid())
}
return added, nil
@ -242,12 +247,17 @@ ipfs pin ls -t indirect <cid>
pins := make([]string, 0, len(req.Arguments))
for _, b := range req.Arguments {
rp, err := api.ResolvePath(req.Context, path.New(b))
p, err := cmdutils.PathOrCidPath(b)
if err != nil {
return err
}
id := enc.Encode(rp.Cid())
rp, _, err := api.ResolvePath(req.Context, p)
if err != nil {
return err
}
id := enc.Encode(rp.RootCid())
pins = append(pins, id)
if err := api.Pin().Rm(req.Context, rp, options.Pin.RmRecursive(recursive)); err != nil {
return err
@ -453,7 +463,12 @@ func pinLsKeys(req *cmds.Request, typeStr string, api coreiface.CoreAPI, emit fu
}
for _, p := range req.Arguments {
rp, err := api.ResolvePath(req.Context, path.New(p))
p, err := cmdutils.PathOrCidPath(p)
if err != nil {
return err
}
rp, _, err := api.ResolvePath(req.Context, p)
if err != nil {
return err
}
@ -476,7 +491,7 @@ func pinLsKeys(req *cmds.Request, typeStr string, api coreiface.CoreAPI, emit fu
err = emit(PinLsOutputWrapper{
PinLsObject: PinLsObject{
Type: pinType,
Cid: enc.Encode(rp.Cid()),
Cid: enc.Encode(rp.RootCid()),
},
})
if err != nil {
@ -517,7 +532,7 @@ func pinLsAll(req *cmds.Request, typeStr string, api coreiface.CoreAPI, emit fun
err = emit(PinLsOutputWrapper{
PinLsObject: PinLsObject{
Type: p.Type(),
Cid: enc.Encode(p.Path().Cid()),
Cid: enc.Encode(p.Path().RootCid()),
},
})
if err != nil {
@ -568,12 +583,22 @@ pin.
unpin, _ := req.Options[pinUnpinOptionName].(bool)
// Resolve the paths ahead of time so we can return the actual CIDs
from, err := api.ResolvePath(req.Context, path.New(req.Arguments[0]))
fromPath, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return err
}
to, err := api.ResolvePath(req.Context, path.New(req.Arguments[1]))
toPath, err := cmdutils.PathOrCidPath(req.Arguments[1])
if err != nil {
return err
}
// Resolve the paths ahead of time so we can return the actual CIDs
from, _, err := api.ResolvePath(req.Context, fromPath)
if err != nil {
return err
}
to, _, err := api.ResolvePath(req.Context, toPath)
if err != nil {
return err
}
@ -583,7 +608,7 @@ pin.
return err
}
return cmds.EmitOnce(res, &PinOutput{Pins: []string{enc.Encode(from.Cid()), enc.Encode(to.Cid())}})
return cmds.EmitOnce(res, &PinOutput{Pins: []string{enc.Encode(from.RootCid()), enc.Encode(to.RootCid())}})
},
Encoders: cmds.EncoderMap{
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *PinOutput) error {

View File

@ -15,13 +15,13 @@ import (
"golang.org/x/sync/errgroup"
path "github.com/ipfs/boxo/coreiface/path"
pinclient "github.com/ipfs/boxo/pinning/remote/client"
cid "github.com/ipfs/go-cid"
cmds "github.com/ipfs/go-ipfs-cmds"
logging "github.com/ipfs/go-log"
config "github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
fsrepo "github.com/ipfs/kubo/repo/fsrepo"
"github.com/libp2p/go-libp2p/core/host"
peer "github.com/libp2p/go-libp2p/core/peer"
@ -157,7 +157,12 @@ NOTE: a comma-separated notation is supported in CLI for convenience:
if err != nil {
return err
}
rp, err := api.ResolvePath(ctx, path.New(req.Arguments[0]))
p, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return err
}
rp, _, err := api.ResolvePath(ctx, p)
if err != nil {
return err
}
@ -177,7 +182,7 @@ NOTE: a comma-separated notation is supported in CLI for convenience:
return err
}
isInBlockstore, err := node.Blockstore.Has(req.Context, rp.Cid())
isInBlockstore, err := node.Blockstore.Has(req.Context, rp.RootCid())
if err != nil {
return err
}
@ -194,7 +199,7 @@ NOTE: a comma-separated notation is supported in CLI for convenience:
// Execute remote pin request
// TODO: fix panic when pinning service is down
ps, err := c.Add(ctx, rp.Cid(), opts...)
ps, err := c.Add(ctx, rp.RootCid(), opts...)
if err != nil {
return err
}

View File

@ -8,9 +8,9 @@ import (
"strings"
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
iface "github.com/ipfs/boxo/coreiface"
path "github.com/ipfs/boxo/coreiface/path"
merkledag "github.com/ipfs/boxo/ipld/merkledag"
cid "github.com/ipfs/go-cid"
cidenc "github.com/ipfs/go-cidutil/cidenc"
@ -171,11 +171,15 @@ Displays the hashes of all local objects. NOTE: This treats all local objects as
func objectsForPaths(ctx context.Context, n iface.CoreAPI, paths []string) ([]cid.Cid, error) {
roots := make([]cid.Cid, len(paths))
for i, sp := range paths {
o, err := n.ResolvePath(ctx, path.New(sp))
p, err := cmdutils.PathOrCidPath(sp)
if err != nil {
return nil, err
}
roots[i] = o.Cid()
o, _, err := n.ResolvePath(ctx, p)
if err != nil {
return nil, err
}
roots[i] = o.RootCid()
}
return roots, nil
}

View File

@ -8,14 +8,13 @@ import (
"time"
ns "github.com/ipfs/boxo/namesys"
cidenc "github.com/ipfs/go-cidutil/cidenc"
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
ncmd "github.com/ipfs/kubo/core/commands/name"
options "github.com/ipfs/boxo/coreiface/options"
nsopts "github.com/ipfs/boxo/coreiface/options/namesys"
path "github.com/ipfs/boxo/coreiface/path"
ipfspath "github.com/ipfs/boxo/path"
cidenc "github.com/ipfs/go-cidutil/cidenc"
"github.com/ipfs/boxo/path"
cmds "github.com/ipfs/go-ipfs-cmds"
)
@ -87,11 +86,11 @@ Resolve the value of an IPFS DAG path:
rc, rcok := req.Options[resolveDhtRecordCountOptionName].(uint)
dhtt, dhttok := req.Options[resolveDhtTimeoutOptionName].(string)
ropts := []options.NameResolveOption{
options.Name.ResolveOption(nsopts.Depth(1)),
options.Name.ResolveOption(ns.ResolveWithDepth(1)),
}
if rcok {
ropts = append(ropts, options.Name.ResolveOption(nsopts.DhtRecordCount(rc)))
ropts = append(ropts, options.Name.ResolveOption(ns.ResolveWithDhtRecordCount(rc)))
}
if dhttok {
d, err := time.ParseDuration(dhtt)
@ -101,14 +100,14 @@ Resolve the value of an IPFS DAG path:
if d < 0 {
return errors.New("DHT timeout value must be >= 0")
}
ropts = append(ropts, options.Name.ResolveOption(nsopts.DhtTimeout(d)))
ropts = append(ropts, options.Name.ResolveOption(ns.ResolveWithDhtTimeout(d)))
}
p, err := api.Name().Resolve(req.Context, name, ropts...)
// ErrResolveRecursion is fine
if err != nil && err != ns.ErrResolveRecursion {
return err
}
return cmds.EmitOnce(res, &ncmd.ResolvedPath{Path: ipfspath.Path(p.String())})
return cmds.EmitOnce(res, &ncmd.ResolvedPath{Path: p.String()})
}
var enc cidenc.Encoder
@ -128,22 +127,34 @@ Resolve the value of an IPFS DAG path:
}
}
// else, ipfs path or ipns with recursive flag
rp, err := api.ResolvePath(req.Context, path.New(name))
p, err := cmdutils.PathOrCidPath(name)
if err != nil {
return err
}
encoded := "/" + rp.Namespace() + "/" + enc.Encode(rp.Cid())
if remainder := rp.Remainder(); remainder != "" {
encoded += "/" + remainder
// else, ipfs path or ipns with recursive flag
rp, remainder, err := api.ResolvePath(req.Context, p)
if err != nil {
return err
}
return cmds.EmitOnce(res, &ncmd.ResolvedPath{Path: ipfspath.Path(encoded)})
// Trick to encode path with correct encoding.
encodedPath := "/" + rp.Namespace() + "/" + enc.Encode(rp.RootCid())
if len(remainder) != 0 {
encodedPath += path.SegmentsToString(remainder...)
}
// Ensure valid and sanitized.
ep, err := path.NewPath(encodedPath)
if err != nil {
return err
}
return cmds.EmitOnce(res, &ncmd.ResolvedPath{Path: ep.String()})
},
Encoders: cmds.EncoderMap{
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, rp *ncmd.ResolvedPath) error {
fmt.Fprintln(w, rp.Path.String())
fmt.Fprintln(w, rp.Path)
return nil
}),
},

View File

@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"io"
"strings"
"time"
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
@ -13,7 +14,6 @@ import (
iface "github.com/ipfs/boxo/coreiface"
"github.com/ipfs/boxo/coreiface/options"
dag "github.com/ipfs/boxo/ipld/merkledag"
path "github.com/ipfs/boxo/path"
cid "github.com/ipfs/go-cid"
cmds "github.com/ipfs/go-ipfs-cmds"
ipld "github.com/ipfs/go-ipld-format"
@ -549,7 +549,7 @@ func printEvent(obj *routing.QueryEvent, out io.Writer, verbose bool, override p
}
func escapeDhtKey(s string) (string, error) {
parts := path.SplitList(s)
parts := strings.Split(s, "/")
if len(parts) != 3 ||
parts[0] != "" ||
!(parts[1] == "ipns" || parts[1] == "pk") {
@ -560,5 +560,6 @@ func escapeDhtKey(s string) (string, error) {
if err != nil {
return "", err
}
return path.Join(append(parts[:2], string(k))), nil
return strings.Join(append(parts[:2], string(k)), "/"), nil
}

View File

@ -6,9 +6,9 @@ import (
cmds "github.com/ipfs/go-ipfs-cmds"
"github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
tar "github.com/ipfs/kubo/tar"
path "github.com/ipfs/boxo/coreiface/path"
dag "github.com/ipfs/boxo/ipld/merkledag"
)
@ -93,7 +93,12 @@ var tarCatCmd = &cmds.Command{
return err
}
root, err := api.ResolveNode(req.Context, path.New(req.Arguments[0]))
p, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return err
}
root, err := api.ResolveNode(req.Context, p)
if err != nil {
return err
}

View File

@ -7,8 +7,8 @@ import (
"text/tabwriter"
cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
"github.com/ipfs/kubo/core/commands/cmdutils"
path "github.com/ipfs/boxo/coreiface/path"
merkledag "github.com/ipfs/boxo/ipld/merkledag"
unixfs "github.com/ipfs/boxo/ipld/unixfs"
cmds "github.com/ipfs/go-ipfs-cmds"
@ -96,7 +96,12 @@ If possible, please use 'ipfs ls' instead.
for _, p := range paths {
ctx := req.Context
merkleNode, err := api.ResolveNode(ctx, path.New(p))
pth, err := cmdutils.PathOrCidPath(p)
if err != nil {
return err
}
merkleNode, err := api.ResolveNode(ctx, pth)
if err != nil {
return err
}

View File

@ -92,7 +92,7 @@ settings for 'ipfs add'.
}
size, _ := file.Size()
return cmds.EmitOnce(res, &BlockStat{
Key: enc.Encode(path.Cid()),
Key: enc.Encode(path.RootCid()),
Size: int(size),
})
},

View File

@ -47,15 +47,15 @@ import (
ma "github.com/multiformats/go-multiaddr"
madns "github.com/multiformats/go-multiaddr-dns"
"github.com/ipfs/boxo/bootstrap"
"github.com/ipfs/boxo/namesys"
ipnsrp "github.com/ipfs/boxo/namesys/republisher"
"github.com/ipfs/boxo/peering"
"github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/core/bootstrap"
"github.com/ipfs/kubo/core/node"
"github.com/ipfs/kubo/core/node/libp2p"
"github.com/ipfs/kubo/fuse/mount"
"github.com/ipfs/kubo/p2p"
"github.com/ipfs/kubo/peering"
"github.com/ipfs/kubo/repo"
irouting "github.com/ipfs/kubo/routing"
)
@ -76,35 +76,39 @@ type IpfsNode struct {
PNetFingerprint libp2p.PNetFingerprint `optional:"true"` // fingerprint of private network
// Services
Peerstore pstore.Peerstore `optional:"true"` // storage for other Peer instances
Blockstore bstore.GCBlockstore // the block store (lower level)
Filestore *filestore.Filestore `optional:"true"` // the filestore blockstore
BaseBlocks node.BaseBlocks // the raw blockstore, no filestore wrapping
GCLocker bstore.GCLocker // the locker used to protect the blockstore during gc
Blocks bserv.BlockService // the block service, get/add blocks.
DAG ipld.DAGService // the merkle dag service, get/add objects.
IPLDFetcherFactory fetcher.Factory `name:"ipldFetcher"` // fetcher that paths over the IPLD data model
UnixFSFetcherFactory fetcher.Factory `name:"unixfsFetcher"` // fetcher that interprets UnixFS data
Reporter *metrics.BandwidthCounter `optional:"true"`
Discovery mdns.Service `optional:"true"`
FilesRoot *mfs.Root
RecordValidator record.Validator
Peerstore pstore.Peerstore `optional:"true"` // storage for other Peer instances
Blockstore bstore.GCBlockstore // the block store (lower level)
Filestore *filestore.Filestore `optional:"true"` // the filestore blockstore
BaseBlocks node.BaseBlocks // the raw blockstore, no filestore wrapping
GCLocker bstore.GCLocker // the locker used to protect the blockstore during gc
Blocks bserv.BlockService // the block service, get/add blocks.
DAG ipld.DAGService // the merkle dag service, get/add objects.
IPLDFetcherFactory fetcher.Factory `name:"ipldFetcher"` // fetcher that paths over the IPLD data model
UnixFSFetcherFactory fetcher.Factory `name:"unixfsFetcher"` // fetcher that interprets UnixFS data
OfflineIPLDFetcherFactory fetcher.Factory `name:"offlineIpldFetcher"` // fetcher that paths over the IPLD data model without fetching new blocks
OfflineUnixFSFetcherFactory fetcher.Factory `name:"offlineUnixfsFetcher"` // fetcher that interprets UnixFS data without fetching new blocks
Reporter *metrics.BandwidthCounter `optional:"true"`
Discovery mdns.Service `optional:"true"`
FilesRoot *mfs.Root
RecordValidator record.Validator
// Online
PeerHost p2phost.Host `optional:"true"` // the network host (server+client)
Peering *peering.PeeringService `optional:"true"`
Filters *ma.Filters `optional:"true"`
Bootstrapper io.Closer `optional:"true"` // the periodic bootstrapper
Routing irouting.ProvideManyRouter `optional:"true"` // the routing system. recommend ipfs-dht
DNSResolver *madns.Resolver // the DNS resolver
IPLDPathResolver pathresolver.Resolver `name:"ipldPathResolver"` // The IPLD path resolver
UnixFSPathResolver pathresolver.Resolver `name:"unixFSPathResolver"` // The UnixFS path resolver
Exchange exchange.Interface // the block exchange + strategy (bitswap)
Namesys namesys.NameSystem // the name system, resolves paths to hashes
Provider provider.System // the value provider system
IpnsRepub *ipnsrp.Republisher `optional:"true"`
GraphExchange graphsync.GraphExchange `optional:"true"`
ResourceManager network.ResourceManager `optional:"true"`
PeerHost p2phost.Host `optional:"true"` // the network host (server+client)
Peering *peering.PeeringService `optional:"true"`
Filters *ma.Filters `optional:"true"`
Bootstrapper io.Closer `optional:"true"` // the periodic bootstrapper
Routing irouting.ProvideManyRouter `optional:"true"` // the routing system. recommend ipfs-dht
DNSResolver *madns.Resolver // the DNS resolver
IPLDPathResolver pathresolver.Resolver `name:"ipldPathResolver"` // The IPLD path resolver
UnixFSPathResolver pathresolver.Resolver `name:"unixFSPathResolver"` // The UnixFS path resolver
OfflineIPLDPathResolver pathresolver.Resolver `name:"offlineIpldPathResolver"` // The IPLD path resolver that uses only locally available blocks
OfflineUnixFSPathResolver pathresolver.Resolver `name:"offlineUnixFSPathResolver"` // The UnixFS path resolver that uses only locally available blocks
Exchange exchange.Interface // the block exchange + strategy (bitswap)
Namesys namesys.NameSystem // the name system, resolves paths to hashes
Provider provider.System // the value provider system
IpnsRepub *ipnsrp.Republisher `optional:"true"`
GraphExchange graphsync.GraphExchange `optional:"true"`
ResourceManager network.ResourceManager `optional:"true"`
PubSub *pubsub.PubSub `optional:"true"`
PSRouter *psrouter.PubsubValueStore `optional:"true"`

View File

@ -8,7 +8,7 @@ import (
coreiface "github.com/ipfs/boxo/coreiface"
caopts "github.com/ipfs/boxo/coreiface/options"
path "github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/path"
pin "github.com/ipfs/boxo/pinning/pinner"
blocks "github.com/ipfs/go-block-format"
cid "github.com/ipfs/go-cid"
@ -22,7 +22,7 @@ import (
type BlockAPI CoreAPI
type BlockStat struct {
path path.Resolved
path path.ImmutablePath
size int
}
@ -68,18 +68,18 @@ func (api *BlockAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.Bloc
}
}
return &BlockStat{path: path.IpldPath(b.Cid()), size: len(data)}, nil
return &BlockStat{path: path.FromCid(b.Cid()), size: len(data)}, nil
}
func (api *BlockAPI) Get(ctx context.Context, p path.Path) (io.Reader, error) {
ctx, span := tracing.Span(ctx, "CoreAPI.BlockAPI", "Get", trace.WithAttributes(attribute.String("path", p.String())))
defer span.End()
rp, err := api.core().ResolvePath(ctx, p)
rp, _, err := api.core().ResolvePath(ctx, p)
if err != nil {
return nil, err
}
b, err := api.blocks.GetBlock(ctx, rp.Cid())
b, err := api.blocks.GetBlock(ctx, rp.RootCid())
if err != nil {
return nil, err
}
@ -91,7 +91,7 @@ func (api *BlockAPI) Rm(ctx context.Context, p path.Path, opts ...caopts.BlockRm
ctx, span := tracing.Span(ctx, "CoreAPI.BlockAPI", "Rm", trace.WithAttributes(attribute.String("path", p.String())))
defer span.End()
rp, err := api.core().ResolvePath(ctx, p)
rp, _, err := api.core().ResolvePath(ctx, p)
if err != nil {
return err
}
@ -100,7 +100,7 @@ func (api *BlockAPI) Rm(ctx context.Context, p path.Path, opts ...caopts.BlockRm
if err != nil {
return err
}
cids := []cid.Cid{rp.Cid()}
cids := []cid.Cid{rp.RootCid()}
o := util.RmBlocksOpts{Force: settings.Force}
out, err := util.RmBlocks(ctx, api.blockstore, api.pinning, cids, o)
@ -132,18 +132,18 @@ func (api *BlockAPI) Stat(ctx context.Context, p path.Path) (coreiface.BlockStat
ctx, span := tracing.Span(ctx, "CoreAPI.BlockAPI", "Stat", trace.WithAttributes(attribute.String("path", p.String())))
defer span.End()
rp, err := api.core().ResolvePath(ctx, p)
rp, _, err := api.core().ResolvePath(ctx, p)
if err != nil {
return nil, err
}
b, err := api.blocks.GetBlock(ctx, rp.Cid())
b, err := api.blocks.GetBlock(ctx, rp.RootCid())
if err != nil {
return nil, err
}
return &BlockStat{
path: path.IpldPath(b.Cid()),
path: path.FromCid(b.Cid()),
size: len(b.RawData()),
}, nil
}
@ -152,7 +152,7 @@ func (bs *BlockStat) Size() int {
return bs.size
}
func (bs *BlockStat) Path() path.Resolved {
func (bs *BlockStat) Path() path.ImmutablePath {
return bs.path
}

View File

@ -1,15 +1,12 @@
/*
**NOTE: this package is experimental.**
Package coreapi provides direct access to the core commands in IPFS. If you are
embedding IPFS directly in your Go program, this package is the public
interface you should use to read and write files or otherwise control IPFS.
If you are running IPFS as a separate process, you should use `go-ipfs-api` to
work with it via HTTP. As we finalize the interfaces here, `go-ipfs-api` will
transparently adopt them so you can use the same code with either package.
**NOTE: this package is experimental.** `go-ipfs` has mainly been developed
as a standalone application and library-style use of this package is still new.
Interfaces here aren't yet completely stable.
If you are running IPFS as a separate process, you should use `client/rpc` to
work with it via HTTP.
*/
package coreapi

View File

@ -8,9 +8,9 @@ import (
blockstore "github.com/ipfs/boxo/blockstore"
coreiface "github.com/ipfs/boxo/coreiface"
caopts "github.com/ipfs/boxo/coreiface/options"
path "github.com/ipfs/boxo/coreiface/path"
offline "github.com/ipfs/boxo/exchange/offline"
dag "github.com/ipfs/boxo/ipld/merkledag"
"github.com/ipfs/boxo/path"
cid "github.com/ipfs/go-cid"
cidutil "github.com/ipfs/go-cidutil"
"github.com/ipfs/kubo/tracing"
@ -53,7 +53,7 @@ func (api *DhtAPI) FindProviders(ctx context.Context, p path.Path, opts ...caopt
return nil, err
}
rp, err := api.core().ResolvePath(ctx, p)
rp, _, err := api.core().ResolvePath(ctx, p)
if err != nil {
return nil, err
}
@ -63,7 +63,7 @@ func (api *DhtAPI) FindProviders(ctx context.Context, p path.Path, opts ...caopt
return nil, fmt.Errorf("number of providers must be greater than 0")
}
pchan := api.routing.FindProvidersAsync(ctx, rp.Cid(), numProviders)
pchan := api.routing.FindProvidersAsync(ctx, rp.RootCid(), numProviders)
return pchan, nil
}
@ -82,12 +82,12 @@ func (api *DhtAPI) Provide(ctx context.Context, path path.Path, opts ...caopts.D
return err
}
rp, err := api.core().ResolvePath(ctx, path)
rp, _, err := api.core().ResolvePath(ctx, path)
if err != nil {
return err
}
c := rp.Cid()
c := rp.RootCid()
has, err := api.blockstore.Has(ctx, c)
if err != nil {

View File

@ -9,8 +9,8 @@ import (
coreiface "github.com/ipfs/boxo/coreiface"
caopts "github.com/ipfs/boxo/coreiface/options"
path "github.com/ipfs/boxo/coreiface/path"
ipfspath "github.com/ipfs/boxo/path"
"github.com/ipfs/boxo/ipns"
"github.com/ipfs/boxo/path"
"github.com/ipfs/kubo/tracing"
crypto "github.com/libp2p/go-libp2p/core/crypto"
peer "github.com/libp2p/go-libp2p/core/peer"
@ -23,6 +23,19 @@ type KeyAPI CoreAPI
type key struct {
name string
peerID peer.ID
path path.Path
}
func newKey(name string, pid peer.ID) (*key, error) {
p, err := path.NewPath("/ipns/" + ipns.NameFromPeer(pid).String())
if err != nil {
return nil, err
}
return &key{
name: name,
peerID: pid,
path: p,
}, nil
}
// Name returns the key name
@ -32,7 +45,7 @@ func (k *key) Name() string {
// Path returns the path of the key.
func (k *key) Path() path.Path {
return path.New(ipfspath.Join([]string{"/ipns", coreiface.FormatKeyID(k.peerID)}))
return k.path
}
// ID returns key PeerID
@ -98,7 +111,7 @@ func (api *KeyAPI) Generate(ctx context.Context, name string, opts ...caopts.Key
return nil, err
}
return &key{name, pid}, nil
return newKey(name, pid)
}
// List returns a list keys stored in keystore.
@ -114,7 +127,10 @@ func (api *KeyAPI) List(ctx context.Context) ([]coreiface.Key, error) {
sort.Strings(keys)
out := make([]coreiface.Key, len(keys)+1)
out[0] = &key{"self", api.identity}
out[0], err = newKey("self", api.identity)
if err != nil {
return nil, err
}
for n, k := range keys {
privKey, err := api.repo.Keystore().Get(k)
@ -129,7 +145,10 @@ func (api *KeyAPI) List(ctx context.Context) ([]coreiface.Key, error) {
return nil, err
}
out[n+1] = &key{k, pid}
out[n+1], err = newKey(k, pid)
if err != nil {
return nil, err
}
}
return out, nil
}
@ -171,7 +190,8 @@ func (api *KeyAPI) Rename(ctx context.Context, oldName string, newName string, o
// This is important, because future code will delete key `oldName`
// even if it is the same as newName.
if newName == oldName {
return &key{oldName, pid}, false, nil
k, err := newKey(oldName, pid)
return k, false, err
}
overwrite := false
@ -195,7 +215,13 @@ func (api *KeyAPI) Rename(ctx context.Context, oldName string, newName string, o
return nil, false, err
}
return &key{newName, pid}, overwrite, ks.Delete(oldName)
err = ks.Delete(oldName)
if err != nil {
return nil, false, err
}
k, err := newKey(newName, pid)
return k, overwrite, err
}
// Remove removes keys from keystore. Returns ipns path of the removed key.
@ -226,7 +252,7 @@ func (api *KeyAPI) Remove(ctx context.Context, name string) (coreiface.Key, erro
return nil, err
}
return &key{"", pid}, nil
return newKey("", pid)
}
func (api *KeyAPI) Self(ctx context.Context) (coreiface.Key, error) {
@ -234,5 +260,5 @@ func (api *KeyAPI) Self(ctx context.Context) (coreiface.Key, error) {
return nil, errors.New("identity not loaded")
}
return &key{"self", api.identity}, nil
return newKey("self", api.identity)
}

View File

@ -15,9 +15,7 @@ import (
coreiface "github.com/ipfs/boxo/coreiface"
caopts "github.com/ipfs/boxo/coreiface/options"
nsopts "github.com/ipfs/boxo/coreiface/options/namesys"
path "github.com/ipfs/boxo/coreiface/path"
ipath "github.com/ipfs/boxo/path"
"github.com/ipfs/boxo/path"
ci "github.com/libp2p/go-libp2p/core/crypto"
peer "github.com/libp2p/go-libp2p/core/peer"
)
@ -51,11 +49,6 @@ func (api *NameAPI) Publish(ctx context.Context, p path.Path, opts ...caopts.Nam
return ipns.Name{}, err
}
pth, err := ipath.ParsePath(p.String())
if err != nil {
return ipns.Name{}, err
}
k, err := keylookup(api.privateKey, api.repo.Keystore(), options.Key)
if err != nil {
return ipns.Name{}, err
@ -63,16 +56,16 @@ func (api *NameAPI) Publish(ctx context.Context, p path.Path, opts ...caopts.Nam
eol := time.Now().Add(options.ValidTime)
publishOptions := []nsopts.PublishOption{
nsopts.PublishWithEOL(eol),
nsopts.PublishCompatibleWithV1(options.CompatibleWithV1),
publishOptions := []namesys.PublishOption{
namesys.PublishWithEOL(eol),
namesys.PublishWithIPNSOption(ipns.WithV1Compatibility(options.CompatibleWithV1)),
}
if options.TTL != nil {
publishOptions = append(publishOptions, nsopts.PublishWithTTL(*options.TTL))
publishOptions = append(publishOptions, namesys.PublishWithTTL(*options.TTL))
}
err = api.namesys.Publish(ctx, k, pth, publishOptions...)
err = api.namesys.Publish(ctx, k, p, publishOptions...)
if err != nil {
return ipns.Name{}, err
}
@ -115,12 +108,17 @@ func (api *NameAPI) Search(ctx context.Context, name string, opts ...caopts.Name
name = "/ipns/" + name
}
p, err := path.NewPath(name)
if err != nil {
return nil, err
}
out := make(chan coreiface.IpnsResult)
go func() {
defer close(out)
for res := range resolver.ResolveAsync(ctx, name, options.ResolveOpts...) {
for res := range resolver.ResolveAsync(ctx, p, options.ResolveOpts...) {
select {
case out <- coreiface.IpnsResult{Path: path.New(res.Path.String()), Err: res.Err}:
case out <- coreiface.IpnsResult{Path: res.Path, Err: res.Err}:
case <-ctx.Done():
return
}

View File

@ -12,10 +12,10 @@ import (
coreiface "github.com/ipfs/boxo/coreiface"
caopts "github.com/ipfs/boxo/coreiface/options"
ipath "github.com/ipfs/boxo/coreiface/path"
dag "github.com/ipfs/boxo/ipld/merkledag"
"github.com/ipfs/boxo/ipld/merkledag/dagutils"
ft "github.com/ipfs/boxo/ipld/unixfs"
"github.com/ipfs/boxo/path"
pin "github.com/ipfs/boxo/pinning/pinner"
cid "github.com/ipfs/go-cid"
ipld "github.com/ipfs/go-ipld-format"
@ -65,13 +65,13 @@ func (api *ObjectAPI) New(ctx context.Context, opts ...caopts.ObjectNewOption) (
return n, nil
}
func (api *ObjectAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.ObjectPutOption) (ipath.Resolved, error) {
func (api *ObjectAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.ObjectPutOption) (path.ImmutablePath, error) {
ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "Put")
defer span.End()
options, err := caopts.ObjectPutOptions(opts...)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
span.SetAttributes(
attribute.Bool("pin", options.Pin),
@ -81,7 +81,7 @@ func (api *ObjectAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.Obj
data, err := io.ReadAll(io.LimitReader(src, inputLimit+10))
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
var dagnode *dag.ProtoNode
@ -92,12 +92,12 @@ func (api *ObjectAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.Obj
decoder.DisallowUnknownFields()
err = decoder.Decode(node)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
dagnode, err = deserializeNode(node, options.DataType)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
case "protobuf":
@ -107,20 +107,20 @@ func (api *ObjectAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.Obj
node := new(Node)
err = xml.Unmarshal(data, node)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
dagnode, err = deserializeNode(node, options.DataType)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
default:
return nil, errors.New("unknown object encoding")
return path.ImmutablePath{}, errors.New("unknown object encoding")
}
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
if options.Pin {
@ -129,30 +129,30 @@ func (api *ObjectAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.Obj
err = api.dag.Add(ctx, dagnode)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
if options.Pin {
if err := api.pinning.PinWithMode(ctx, dagnode.Cid(), pin.Recursive); err != nil {
return nil, err
return path.ImmutablePath{}, err
}
err = api.pinning.Flush(ctx)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
}
return ipath.IpfsPath(dagnode.Cid()), nil
return path.FromCid(dagnode.Cid()), nil
}
func (api *ObjectAPI) Get(ctx context.Context, path ipath.Path) (ipld.Node, error) {
func (api *ObjectAPI) Get(ctx context.Context, path path.Path) (ipld.Node, error) {
ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "Get", trace.WithAttributes(attribute.String("path", path.String())))
defer span.End()
return api.core().ResolveNode(ctx, path)
}
func (api *ObjectAPI) Data(ctx context.Context, path ipath.Path) (io.Reader, error) {
func (api *ObjectAPI) Data(ctx context.Context, path path.Path) (io.Reader, error) {
ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "Data", trace.WithAttributes(attribute.String("path", path.String())))
defer span.End()
@ -169,7 +169,7 @@ func (api *ObjectAPI) Data(ctx context.Context, path ipath.Path) (io.Reader, err
return bytes.NewReader(pbnd.Data()), nil
}
func (api *ObjectAPI) Links(ctx context.Context, path ipath.Path) ([]*ipld.Link, error) {
func (api *ObjectAPI) Links(ctx context.Context, path path.Path) ([]*ipld.Link, error) {
ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "Links", trace.WithAttributes(attribute.String("path", path.String())))
defer span.End()
@ -187,7 +187,7 @@ func (api *ObjectAPI) Links(ctx context.Context, path ipath.Path) ([]*ipld.Link,
return out, nil
}
func (api *ObjectAPI) Stat(ctx context.Context, path ipath.Path) (*coreiface.ObjectStat, error) {
func (api *ObjectAPI) Stat(ctx context.Context, path path.Path) (*coreiface.ObjectStat, error) {
ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "Stat", trace.WithAttributes(attribute.String("path", path.String())))
defer span.End()
@ -213,7 +213,7 @@ func (api *ObjectAPI) Stat(ctx context.Context, path ipath.Path) (*coreiface.Obj
return out, nil
}
func (api *ObjectAPI) AddLink(ctx context.Context, base ipath.Path, name string, child ipath.Path, opts ...caopts.ObjectAddLinkOption) (ipath.Resolved, error) {
func (api *ObjectAPI) AddLink(ctx context.Context, base path.Path, name string, child path.Path, opts ...caopts.ObjectAddLinkOption) (path.ImmutablePath, error) {
ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "AddLink", trace.WithAttributes(
attribute.String("base", base.String()),
attribute.String("name", name),
@ -223,23 +223,23 @@ func (api *ObjectAPI) AddLink(ctx context.Context, base ipath.Path, name string,
options, err := caopts.ObjectAddLinkOptions(opts...)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
span.SetAttributes(attribute.Bool("create", options.Create))
baseNd, err := api.core().ResolveNode(ctx, base)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
childNd, err := api.core().ResolveNode(ctx, child)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
basePb, ok := baseNd.(*dag.ProtoNode)
if !ok {
return nil, dag.ErrNotProtobuf
return path.ImmutablePath{}, dag.ErrNotProtobuf
}
var createfunc func() *dag.ProtoNode
@ -251,18 +251,18 @@ func (api *ObjectAPI) AddLink(ctx context.Context, base ipath.Path, name string,
err = e.InsertNodeAtPath(ctx, name, childNd, createfunc)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
nnode, err := e.Finalize(ctx, api.dag)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
return ipath.IpfsPath(nnode.Cid()), nil
return path.FromCid(nnode.Cid()), nil
}
func (api *ObjectAPI) RmLink(ctx context.Context, base ipath.Path, link string) (ipath.Resolved, error) {
func (api *ObjectAPI) RmLink(ctx context.Context, base path.Path, link string) (path.ImmutablePath, error) {
ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "RmLink", trace.WithAttributes(
attribute.String("base", base.String()),
attribute.String("link", link)),
@ -271,57 +271,57 @@ func (api *ObjectAPI) RmLink(ctx context.Context, base ipath.Path, link string)
baseNd, err := api.core().ResolveNode(ctx, base)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
basePb, ok := baseNd.(*dag.ProtoNode)
if !ok {
return nil, dag.ErrNotProtobuf
return path.ImmutablePath{}, dag.ErrNotProtobuf
}
e := dagutils.NewDagEditor(basePb, api.dag)
err = e.RmLink(ctx, link)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
nnode, err := e.Finalize(ctx, api.dag)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
return ipath.IpfsPath(nnode.Cid()), nil
return path.FromCid(nnode.Cid()), nil
}
func (api *ObjectAPI) AppendData(ctx context.Context, path ipath.Path, r io.Reader) (ipath.Resolved, error) {
func (api *ObjectAPI) AppendData(ctx context.Context, path path.Path, r io.Reader) (path.ImmutablePath, error) {
ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "AppendData", trace.WithAttributes(attribute.String("path", path.String())))
defer span.End()
return api.patchData(ctx, path, r, true)
}
func (api *ObjectAPI) SetData(ctx context.Context, path ipath.Path, r io.Reader) (ipath.Resolved, error) {
func (api *ObjectAPI) SetData(ctx context.Context, path path.Path, r io.Reader) (path.ImmutablePath, error) {
ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "SetData", trace.WithAttributes(attribute.String("path", path.String())))
defer span.End()
return api.patchData(ctx, path, r, false)
}
func (api *ObjectAPI) patchData(ctx context.Context, path ipath.Path, r io.Reader, appendData bool) (ipath.Resolved, error) {
nd, err := api.core().ResolveNode(ctx, path)
func (api *ObjectAPI) patchData(ctx context.Context, p path.Path, r io.Reader, appendData bool) (path.ImmutablePath, error) {
nd, err := api.core().ResolveNode(ctx, p)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
pbnd, ok := nd.(*dag.ProtoNode)
if !ok {
return nil, dag.ErrNotProtobuf
return path.ImmutablePath{}, dag.ErrNotProtobuf
}
data, err := io.ReadAll(r)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
if appendData {
@ -331,13 +331,13 @@ func (api *ObjectAPI) patchData(ctx context.Context, path ipath.Path, r io.Reade
err = api.dag.Add(ctx, pbnd)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
return ipath.IpfsPath(pbnd.Cid()), nil
return path.FromCid(pbnd.Cid()), nil
}
func (api *ObjectAPI) Diff(ctx context.Context, before ipath.Path, after ipath.Path) ([]coreiface.ObjectChange, error) {
func (api *ObjectAPI) Diff(ctx context.Context, before path.Path, after path.Path) ([]coreiface.ObjectChange, error) {
ctx, span := tracing.Span(ctx, "CoreAPI.ObjectAPI", "Diff", trace.WithAttributes(
attribute.String("before", before.String()),
attribute.String("after", after.String()),
@ -367,11 +367,11 @@ func (api *ObjectAPI) Diff(ctx context.Context, before ipath.Path, after ipath.P
}
if change.Before.Defined() {
out[i].Before = ipath.IpfsPath(change.Before)
out[i].Before = path.FromCid(change.Before)
}
if change.After.Defined() {
out[i].After = ipath.IpfsPath(change.After)
out[i].After = path.FromCid(change.After)
}
}

View File

@ -2,20 +2,18 @@ package coreapi
import (
"context"
"errors"
"fmt"
gopath "path"
"github.com/ipfs/boxo/namesys/resolve"
"github.com/ipfs/boxo/namesys"
"github.com/ipfs/kubo/tracing"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
coreiface "github.com/ipfs/boxo/coreiface"
path "github.com/ipfs/boxo/coreiface/path"
ipfspath "github.com/ipfs/boxo/path"
"github.com/ipfs/boxo/path"
ipfspathresolver "github.com/ipfs/boxo/path/resolver"
"github.com/ipfs/go-cid"
ipld "github.com/ipfs/go-ipld-format"
)
@ -25,12 +23,12 @@ func (api *CoreAPI) ResolveNode(ctx context.Context, p path.Path) (ipld.Node, er
ctx, span := tracing.Span(ctx, "CoreAPI", "ResolveNode", trace.WithAttributes(attribute.String("path", p.String())))
defer span.End()
rp, err := api.ResolvePath(ctx, p)
rp, _, err := api.ResolvePath(ctx, p)
if err != nil {
return nil, err
}
node, err := api.dag.Get(ctx, rp.Cid())
node, err := api.dag.Get(ctx, rp.RootCid())
if err != nil {
return nil, err
}
@ -39,45 +37,50 @@ func (api *CoreAPI) ResolveNode(ctx context.Context, p path.Path) (ipld.Node, er
// ResolvePath resolves the path `p` using Unixfs resolver, returns the
// resolved path.
func (api *CoreAPI) ResolvePath(ctx context.Context, p path.Path) (path.Resolved, error) {
func (api *CoreAPI) ResolvePath(ctx context.Context, p path.Path) (path.ImmutablePath, []string, error) {
ctx, span := tracing.Span(ctx, "CoreAPI", "ResolvePath", trace.WithAttributes(attribute.String("path", p.String())))
defer span.End()
if _, ok := p.(path.Resolved); ok {
return p.(path.Resolved), nil
}
if err := p.IsValid(); err != nil {
return nil, err
}
ipath := ipfspath.Path(p.String())
ipath, err := resolve.ResolveIPNS(ctx, api.namesys, ipath)
if err == resolve.ErrNoNamesys {
return nil, coreiface.ErrOffline
res, err := namesys.Resolve(ctx, api.namesys, p)
if errors.Is(err, namesys.ErrNoNamesys) {
return path.ImmutablePath{}, nil, coreiface.ErrOffline
} else if err != nil {
return nil, err
}
if ipath.Segments()[0] != "ipfs" && ipath.Segments()[0] != "ipld" {
return nil, fmt.Errorf("unsupported path namespace: %s", p.Namespace())
return path.ImmutablePath{}, nil, err
}
p = res.Path
var resolver ipfspathresolver.Resolver
if ipath.Segments()[0] == "ipld" {
switch p.Namespace() {
case path.IPLDNamespace:
resolver = api.ipldPathResolver
} else {
case path.IPFSNamespace:
resolver = api.unixFSPathResolver
default:
return path.ImmutablePath{}, nil, fmt.Errorf("unsupported path namespace: %s", p.Namespace())
}
node, rest, err := resolver.ResolveToLastNode(ctx, ipath)
imPath, err := path.NewImmutablePath(p)
if err != nil {
return nil, err
return path.ImmutablePath{}, nil, err
}
root, err := cid.Parse(ipath.Segments()[1])
node, remainder, err := resolver.ResolveToLastNode(ctx, imPath)
if err != nil {
return nil, err
return path.ImmutablePath{}, nil, err
}
return path.NewResolvedPath(ipath, node, root, gopath.Join(rest...)), nil
segments := []string{p.Namespace(), node.String()}
segments = append(segments, remainder...)
p, err = path.NewPathFromSegments(segments...)
if err != nil {
return path.ImmutablePath{}, nil, err
}
imPath, err = path.NewImmutablePath(p)
if err != nil {
return path.ImmutablePath{}, nil, err
}
return imPath, remainder, nil
}

View File

@ -7,9 +7,9 @@ import (
bserv "github.com/ipfs/boxo/blockservice"
coreiface "github.com/ipfs/boxo/coreiface"
caopts "github.com/ipfs/boxo/coreiface/options"
"github.com/ipfs/boxo/coreiface/path"
offline "github.com/ipfs/boxo/exchange/offline"
"github.com/ipfs/boxo/ipld/merkledag"
"github.com/ipfs/boxo/path"
pin "github.com/ipfs/boxo/pinning/pinner"
"github.com/ipfs/go-cid"
"go.opentelemetry.io/otel/attribute"
@ -74,7 +74,7 @@ func (api *PinAPI) IsPinned(ctx context.Context, p path.Path, opts ...caopts.Pin
ctx, span := tracing.Span(ctx, "CoreAPI.PinAPI", "IsPinned", trace.WithAttributes(attribute.String("path", p.String())))
defer span.End()
resolved, err := api.core().ResolvePath(ctx, p)
resolved, _, err := api.core().ResolvePath(ctx, p)
if err != nil {
return "", false, fmt.Errorf("error resolving path: %s", err)
}
@ -91,7 +91,7 @@ func (api *PinAPI) IsPinned(ctx context.Context, p path.Path, opts ...caopts.Pin
return "", false, fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", settings.WithType)
}
return api.pinning.IsPinnedWithType(ctx, resolved.Cid(), mode)
return api.pinning.IsPinnedWithType(ctx, resolved.RootCid(), mode)
}
// Rm pin rm api
@ -99,7 +99,7 @@ func (api *PinAPI) Rm(ctx context.Context, p path.Path, opts ...caopts.PinRmOpti
ctx, span := tracing.Span(ctx, "CoreAPI.PinAPI", "Rm", trace.WithAttributes(attribute.String("path", p.String())))
defer span.End()
rp, err := api.core().ResolvePath(ctx, p)
rp, _, err := api.core().ResolvePath(ctx, p)
if err != nil {
return err
}
@ -115,7 +115,7 @@ func (api *PinAPI) Rm(ctx context.Context, p path.Path, opts ...caopts.PinRmOpti
// to take a lock to prevent a concurrent garbage collection
defer api.blockstore.PinLock(ctx).Unlock(ctx)
if err = api.pinning.Unpin(ctx, rp.Cid(), settings.Recursive); err != nil {
if err = api.pinning.Unpin(ctx, rp.RootCid(), settings.Recursive); err != nil {
return err
}
@ -136,19 +136,19 @@ func (api *PinAPI) Update(ctx context.Context, from path.Path, to path.Path, opt
span.SetAttributes(attribute.Bool("unpin", settings.Unpin))
fp, err := api.core().ResolvePath(ctx, from)
fp, _, err := api.core().ResolvePath(ctx, from)
if err != nil {
return err
}
tp, err := api.core().ResolvePath(ctx, to)
tp, _, err := api.core().ResolvePath(ctx, to)
if err != nil {
return err
}
defer api.blockstore.PinLock(ctx).Unlock(ctx)
err = api.pinning.Update(ctx, fp.Cid(), tp.Cid(), settings.Unpin)
err = api.pinning.Update(ctx, fp.RootCid(), tp.RootCid(), settings.Unpin)
if err != nil {
return err
}
@ -165,7 +165,7 @@ type pinStatus struct {
// BadNode is used in PinVerifyRes
type badNode struct {
path path.Resolved
path path.ImmutablePath
err error
}
@ -181,7 +181,7 @@ func (s *pinStatus) Err() error {
return s.err
}
func (n *badNode) Path() path.Resolved {
func (n *badNode) Path() path.ImmutablePath {
return n.path
}
@ -210,7 +210,7 @@ func (api *PinAPI) Verify(ctx context.Context) (<-chan coreiface.PinStatus, erro
links, err := getLinks(ctx, root)
if err != nil {
status := &pinStatus{ok: false, cid: root}
status.badNodes = []coreiface.BadPinNode{&badNode{path: path.IpldPath(root), err: err}}
status.badNodes = []coreiface.BadPinNode{&badNode{path: path.FromCid(root), err: err}}
visited[root] = status
return status
}
@ -251,11 +251,11 @@ func (api *PinAPI) Verify(ctx context.Context) (<-chan coreiface.PinStatus, erro
type pinInfo struct {
pinType string
path path.Resolved
path path.ImmutablePath
err error
}
func (p *pinInfo) Path() path.Resolved {
func (p *pinInfo) Path() path.ImmutablePath {
return p.path
}
@ -281,7 +281,7 @@ func (api *PinAPI) pinLsAll(ctx context.Context, typeStr string) <-chan coreifac
select {
case out <- &pinInfo{
pinType: typeStr,
path: path.IpldPath(c),
path: path.FromCid(c),
}:
case <-ctx.Done():
return ctx.Err()

View File

@ -3,10 +3,10 @@ package coreapi
import (
"context"
"errors"
"strings"
coreiface "github.com/ipfs/boxo/coreiface"
caopts "github.com/ipfs/boxo/coreiface/options"
"github.com/ipfs/boxo/path"
peer "github.com/libp2p/go-libp2p/core/peer"
)
@ -45,7 +45,7 @@ func (r *RoutingAPI) Put(ctx context.Context, key string, value []byte, opts ...
}
func normalizeKey(s string) (string, error) {
parts := path.SplitList(s)
parts := strings.Split(s, "/")
if len(parts) != 3 ||
parts[0] != "" ||
!(parts[1] == "ipns" || parts[1] == "pk") {
@ -56,5 +56,5 @@ func normalizeKey(s string) (string, error) {
if err != nil {
return "", err
}
return path.Join(append(parts[:2], string(k))), nil
return strings.Join(append(parts[:2], string(k)), "/"), nil
}

View File

@ -8,10 +8,10 @@ import (
"path/filepath"
"testing"
"github.com/ipfs/boxo/bootstrap"
"github.com/ipfs/boxo/filestore"
keystore "github.com/ipfs/boxo/keystore"
"github.com/ipfs/kubo/core"
"github.com/ipfs/kubo/core/bootstrap"
"github.com/ipfs/kubo/core/coreapi"
mock "github.com/ipfs/kubo/core/mock"
"github.com/ipfs/kubo/core/node/libp2p"

View File

@ -7,10 +7,10 @@ import (
"time"
"github.com/ipfs/boxo/coreiface/options"
"github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/files"
"github.com/ipfs/boxo/ipld/merkledag"
uio "github.com/ipfs/boxo/ipld/unixfs/io"
"github.com/ipfs/boxo/path"
"github.com/ipld/go-ipld-prime"
)
@ -45,7 +45,7 @@ func TestPathUnixFSHAMTPartial(t *testing.T) {
}
// Get the root of the directory
nd, err := a.Dag().Get(ctx, r.Cid())
nd, err := a.Dag().Get(ctx, r.RootCid())
if err != nil {
t.Fatal(err)
}
@ -55,7 +55,7 @@ func TestPathUnixFSHAMTPartial(t *testing.T) {
pbNode := nd.(*merkledag.ProtoNode)
// Remove one of the sharded directory blocks
if err := a.Block().Rm(ctx, path.IpfsPath(pbNode.Links()[0].Cid)); err != nil {
if err := a.Block().Rm(ctx, path.FromCid(pbNode.Links()[0].Cid)); err != nil {
t.Fatal(err)
}
@ -67,7 +67,12 @@ func TestPathUnixFSHAMTPartial(t *testing.T) {
// The node will go out to the (non-existent) network looking for the missing block. Make sure we're erroring
// because we exceeded the timeout on our query
timeoutCtx, timeoutCancel := context.WithTimeout(ctx, time.Second*1)
_, err := a.ResolveNode(timeoutCtx, path.Join(r, k))
newPath, err := path.Join(r, k)
if err != nil {
t.Fatal(err)
}
_, err = a.ResolveNode(timeoutCtx, newPath)
if err != nil {
if timeoutCtx.Err() == nil {
t.Fatal(err)

View File

@ -16,7 +16,6 @@ import (
bstore "github.com/ipfs/boxo/blockstore"
coreiface "github.com/ipfs/boxo/coreiface"
options "github.com/ipfs/boxo/coreiface/options"
path "github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/files"
filestore "github.com/ipfs/boxo/filestore"
merkledag "github.com/ipfs/boxo/ipld/merkledag"
@ -25,6 +24,7 @@ import (
unixfile "github.com/ipfs/boxo/ipld/unixfs/file"
uio "github.com/ipfs/boxo/ipld/unixfs/io"
mfs "github.com/ipfs/boxo/mfs"
"github.com/ipfs/boxo/path"
cid "github.com/ipfs/go-cid"
cidutil "github.com/ipfs/go-cidutil"
ipld "github.com/ipfs/go-ipld-format"
@ -58,13 +58,13 @@ func getOrCreateNilNode() (*core.IpfsNode, error) {
// Add builds a merkledag node from a reader, adds it to the blockstore,
// and returns the key representing that node.
func (api *UnixfsAPI) Add(ctx context.Context, files files.Node, opts ...options.UnixfsAddOption) (path.Resolved, error) {
func (api *UnixfsAPI) Add(ctx context.Context, files files.Node, opts ...options.UnixfsAddOption) (path.ImmutablePath, error) {
ctx, span := tracing.Span(ctx, "CoreAPI.UnixfsAPI", "Add")
defer span.End()
settings, prefix, err := options.UnixfsAddOptions(opts...)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
span.SetAttributes(
@ -85,7 +85,7 @@ func (api *UnixfsAPI) Add(ctx context.Context, files files.Node, opts ...options
cfg, err := api.repo.Config()
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
// check if repo will exceed storage limit if added
@ -97,7 +97,7 @@ func (api *UnixfsAPI) Add(ctx context.Context, files files.Node, opts ...options
//}
if settings.NoCopy && !(cfg.Experimental.FilestoreEnabled || cfg.Experimental.UrlstoreEnabled) {
return nil, fmt.Errorf("either the filestore or the urlstore must be enabled to use nocopy, see: https://github.com/ipfs/kubo/blob/master/docs/experimental-features.md#ipfs-filestore")
return path.ImmutablePath{}, fmt.Errorf("either the filestore or the urlstore must be enabled to use nocopy, see: https://github.com/ipfs/kubo/blob/master/docs/experimental-features.md#ipfs-filestore")
}
addblockstore := api.blockstore
@ -110,7 +110,7 @@ func (api *UnixfsAPI) Add(ctx context.Context, files files.Node, opts ...options
if settings.OnlyHash {
node, err := getOrCreateNilNode()
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
addblockstore = node.Blockstore
exch = node.Exchange
@ -144,7 +144,7 @@ func (api *UnixfsAPI) Add(ctx context.Context, files files.Node, opts ...options
fileAdder, err := coreunix.NewAdder(ctx, pinning, addblockstore, syncDserv)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
fileAdder.Chunker = settings.Chunker
@ -164,7 +164,7 @@ func (api *UnixfsAPI) Add(ctx context.Context, files files.Node, opts ...options
case options.TrickleLayout:
fileAdder.Trickle = true
default:
return nil, fmt.Errorf("unknown layout: %d", settings.Layout)
return path.ImmutablePath{}, fmt.Errorf("unknown layout: %d", settings.Layout)
}
if settings.Inline {
@ -180,11 +180,11 @@ func (api *UnixfsAPI) Add(ctx context.Context, files files.Node, opts ...options
// Use the same prefix for the "empty" MFS root as for the file adder.
err := emptyDirNode.SetCidBuilder(fileAdder.CidBuilder)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
mr, err := mfs.NewRoot(ctx, md, emptyDirNode, nil)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
fileAdder.SetMfsRoot(mr)
@ -192,16 +192,16 @@ func (api *UnixfsAPI) Add(ctx context.Context, files files.Node, opts ...options
nd, err := fileAdder.AddAllAndPin(ctx, files)
if err != nil {
return nil, err
return path.ImmutablePath{}, err
}
if !settings.OnlyHash {
if err := api.provider.Provide(nd.Cid()); err != nil {
return nil, err
return path.ImmutablePath{}, err
}
}
return path.IpfsPath(nd.Cid()), nil
return path.FromCid(nd.Cid()), nil
}
func (api *UnixfsAPI) Get(ctx context.Context, p path.Path) (files.Node, error) {

View File

@ -9,7 +9,6 @@ import (
"strconv"
"strings"
path "github.com/ipfs/boxo/path"
cmds "github.com/ipfs/go-ipfs-cmds"
cmdsHttp "github.com/ipfs/go-ipfs-cmds/http"
version "github.com/ipfs/kubo"
@ -171,7 +170,7 @@ func CheckVersionOption() ServeOption {
parent.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(r.URL.Path, APIPath) {
cmdqry := r.URL.Path[len(APIPath):]
pth := path.SplitList(cmdqry)
pth := strings.Split(cmdqry, "/")
// backwards compatibility to previous version check
if len(pth) >= 2 && pth[1] != "version" {

View File

@ -7,14 +7,15 @@ import (
"io"
"net"
"net/http"
"time"
"github.com/ipfs/boxo/blockservice"
iface "github.com/ipfs/boxo/coreiface"
"github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/exchange/offline"
"github.com/ipfs/boxo/files"
"github.com/ipfs/boxo/gateway"
"github.com/ipfs/boxo/namesys"
"github.com/ipfs/boxo/path"
offlineroute "github.com/ipfs/boxo/routing/offline"
"github.com/ipfs/go-cid"
version "github.com/ipfs/kubo"
@ -80,7 +81,11 @@ func Libp2pGatewayOption() ServeOption {
return func(n *core.IpfsNode, _ net.Listener, mux *http.ServeMux) (*http.ServeMux, error) {
bserv := blockservice.New(n.Blocks.Blockstore(), offline.Exchange(n.Blocks.Blockstore()))
backend, err := gateway.NewBlocksBackend(bserv)
backend, err := gateway.NewBlocksBackend(bserv,
// GatewayOverLibp2p only returns things that are in local blockstore
// (same as Gateway.NoFetch=true), we have to pass offline path resolver
gateway.WithResolver(n.OfflineUnixFSPathResolver),
)
if err != nil {
return nil, err
}
@ -110,6 +115,8 @@ func newGatewayBackend(n *core.IpfsNode) (gateway.IPFSBackend, error) {
bserv := n.Blocks
var vsRouting routing.ValueStore = n.Routing
nsys := n.Namesys
pathResolver := n.UnixFSPathResolver
if cfg.Gateway.NoFetch {
bserv = blockservice.New(bserv.Blockstore(), offline.Exchange(bserv.Blockstore()))
@ -129,9 +136,17 @@ func newGatewayBackend(n *core.IpfsNode) (gateway.IPFSBackend, error) {
if err != nil {
return nil, fmt.Errorf("error constructing namesys: %w", err)
}
// Gateway.NoFetch=true requires offline path resolver
// to avoid fetching missing blocks during path traversal
pathResolver = n.OfflineUnixFSPathResolver
}
backend, err := gateway.NewBlocksBackend(bserv, gateway.WithValueStore(vsRouting), gateway.WithNameSystem(nsys))
backend, err := gateway.NewBlocksBackend(bserv,
gateway.WithValueStore(vsRouting),
gateway.WithNameSystem(nsys),
gateway.WithResolver(pathResolver),
)
if err != nil {
return nil, err
}
@ -149,37 +164,37 @@ func offlineErrWrap(err error) error {
return err
}
func (o *offlineGatewayErrWrapper) Get(ctx context.Context, path gateway.ImmutablePath, ranges ...gateway.ByteRange) (gateway.ContentPathMetadata, *gateway.GetResponse, error) {
func (o *offlineGatewayErrWrapper) Get(ctx context.Context, path path.ImmutablePath, ranges ...gateway.ByteRange) (gateway.ContentPathMetadata, *gateway.GetResponse, error) {
md, n, err := o.gwimpl.Get(ctx, path, ranges...)
err = offlineErrWrap(err)
return md, n, err
}
func (o *offlineGatewayErrWrapper) GetAll(ctx context.Context, path gateway.ImmutablePath) (gateway.ContentPathMetadata, files.Node, error) {
func (o *offlineGatewayErrWrapper) GetAll(ctx context.Context, path path.ImmutablePath) (gateway.ContentPathMetadata, files.Node, error) {
md, n, err := o.gwimpl.GetAll(ctx, path)
err = offlineErrWrap(err)
return md, n, err
}
func (o *offlineGatewayErrWrapper) GetBlock(ctx context.Context, path gateway.ImmutablePath) (gateway.ContentPathMetadata, files.File, error) {
func (o *offlineGatewayErrWrapper) GetBlock(ctx context.Context, path path.ImmutablePath) (gateway.ContentPathMetadata, files.File, error) {
md, n, err := o.gwimpl.GetBlock(ctx, path)
err = offlineErrWrap(err)
return md, n, err
}
func (o *offlineGatewayErrWrapper) Head(ctx context.Context, path gateway.ImmutablePath) (gateway.ContentPathMetadata, files.Node, error) {
func (o *offlineGatewayErrWrapper) Head(ctx context.Context, path path.ImmutablePath) (gateway.ContentPathMetadata, *gateway.HeadResponse, error) {
md, n, err := o.gwimpl.Head(ctx, path)
err = offlineErrWrap(err)
return md, n, err
}
func (o *offlineGatewayErrWrapper) ResolvePath(ctx context.Context, path gateway.ImmutablePath) (gateway.ContentPathMetadata, error) {
func (o *offlineGatewayErrWrapper) ResolvePath(ctx context.Context, path path.ImmutablePath) (gateway.ContentPathMetadata, error) {
md, err := o.gwimpl.ResolvePath(ctx, path)
err = offlineErrWrap(err)
return md, err
}
func (o *offlineGatewayErrWrapper) GetCAR(ctx context.Context, path gateway.ImmutablePath, params gateway.CarParams) (gateway.ContentPathMetadata, io.ReadCloser, error) {
func (o *offlineGatewayErrWrapper) GetCAR(ctx context.Context, path path.ImmutablePath, params gateway.CarParams) (gateway.ContentPathMetadata, io.ReadCloser, error) {
md, data, err := o.gwimpl.GetCAR(ctx, path, params)
err = offlineErrWrap(err)
return md, data, err
@ -195,10 +210,10 @@ func (o *offlineGatewayErrWrapper) GetIPNSRecord(ctx context.Context, c cid.Cid)
return rec, err
}
func (o *offlineGatewayErrWrapper) ResolveMutable(ctx context.Context, path path.Path) (gateway.ImmutablePath, error) {
imPath, err := o.gwimpl.ResolveMutable(ctx, path)
func (o *offlineGatewayErrWrapper) ResolveMutable(ctx context.Context, path path.Path) (path.ImmutablePath, time.Duration, time.Time, error) {
imPath, ttl, lastMod, err := o.gwimpl.ResolveMutable(ctx, path)
err = offlineErrWrap(err)
return imPath, err
return imPath, ttl, lastMod, err
}
func (o *offlineGatewayErrWrapper) GetDNSLinkRecord(ctx context.Context, s string) (path.Path, error) {

View File

@ -17,7 +17,6 @@ import (
"github.com/stretchr/testify/assert"
iface "github.com/ipfs/boxo/coreiface"
nsopts "github.com/ipfs/boxo/coreiface/options/namesys"
"github.com/ipfs/boxo/path"
"github.com/ipfs/go-datastore"
syncds "github.com/ipfs/go-datastore/sync"
@ -27,41 +26,47 @@ import (
type mockNamesys map[string]path.Path
func (m mockNamesys) Resolve(ctx context.Context, name string, opts ...nsopts.ResolveOpt) (value path.Path, err error) {
cfg := nsopts.DefaultResolveOpts()
func (m mockNamesys) Resolve(ctx context.Context, p path.Path, opts ...namesys.ResolveOption) (namesys.Result, error) {
cfg := namesys.DefaultResolveOptions()
for _, o := range opts {
o(&cfg)
}
depth := cfg.Depth
if depth == nsopts.UnlimitedDepth {
if depth == namesys.UnlimitedDepth {
// max uint
depth = ^uint(0)
}
var (
value path.Path
)
name := path.SegmentsToString(p.Segments()[:2]...)
for strings.HasPrefix(name, "/ipns/") {
if depth == 0 {
return value, namesys.ErrResolveRecursion
return namesys.Result{Path: value}, namesys.ErrResolveRecursion
}
depth--
var ok bool
value, ok = m[name]
v, ok := m[name]
if !ok {
return "", namesys.ErrResolveFailed
return namesys.Result{}, namesys.ErrResolveFailed
}
value = v
name = value.String()
}
return value, nil
value, err := path.Join(value, p.Segments()[2:]...)
return namesys.Result{Path: value}, err
}
func (m mockNamesys) ResolveAsync(ctx context.Context, name string, opts ...nsopts.ResolveOpt) <-chan namesys.Result {
out := make(chan namesys.Result, 1)
v, err := m.Resolve(ctx, name, opts...)
out <- namesys.Result{Path: v, Err: err}
func (m mockNamesys) ResolveAsync(ctx context.Context, p path.Path, opts ...namesys.ResolveOption) <-chan namesys.AsyncResult {
out := make(chan namesys.AsyncResult, 1)
res, err := m.Resolve(ctx, p, opts...)
out <- namesys.AsyncResult{Path: res.Path, TTL: res.TTL, LastMod: res.LastMod, Err: err}
close(out)
return out
}
func (m mockNamesys) Publish(ctx context.Context, name ci.PrivKey, value path.Path, opts ...nsopts.PublishOption) error {
func (m mockNamesys) Publish(ctx context.Context, name ci.PrivKey, value path.Path, opts ...namesys.PublishOption) error {
return errors.New("not implemented for mockNamesys")
}

View File

@ -42,7 +42,7 @@ func (r *contentRouter) ProvideBitswap(ctx context.Context, req *server.BitswapW
return 0, routing.ErrNotSupported
}
func (r *contentRouter) FindPeers(ctx context.Context, pid peer.ID, limit int) (iter.ResultIter[types.Record], error) {
func (r *contentRouter) FindPeers(ctx context.Context, pid peer.ID, limit int) (iter.ResultIter[*types.PeerRecord], error) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
@ -60,7 +60,7 @@ func (r *contentRouter) FindPeers(ctx context.Context, pid peer.ID, limit int) (
rec.Addrs = append(rec.Addrs, types.Multiaddr{Multiaddr: addr})
}
return iter.ToResultIter[types.Record](iter.FromSlice[types.Record]([]types.Record{rec})), nil
return iter.ToResultIter[*types.PeerRecord](iter.FromSlice[*types.PeerRecord]([]*types.PeerRecord{rec})), nil
}
func (r *contentRouter) GetIPNS(ctx context.Context, name ipns.Name) (*ipns.Record, error) {

View File

@ -11,7 +11,6 @@ import (
bstore "github.com/ipfs/boxo/blockstore"
chunker "github.com/ipfs/boxo/chunker"
coreiface "github.com/ipfs/boxo/coreiface"
"github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/files"
posinfo "github.com/ipfs/boxo/filestore/posinfo"
dag "github.com/ipfs/boxo/ipld/merkledag"
@ -20,6 +19,7 @@ import (
ihelper "github.com/ipfs/boxo/ipld/unixfs/importer/helpers"
"github.com/ipfs/boxo/ipld/unixfs/importer/trickle"
"github.com/ipfs/boxo/mfs"
"github.com/ipfs/boxo/path"
pin "github.com/ipfs/boxo/pinning/pinner"
"github.com/ipfs/go-cid"
ipld "github.com/ipfs/go-ipld-format"
@ -506,7 +506,7 @@ func getOutput(dagnode ipld.Node) (*coreiface.AddEvent, error) {
}
output := &coreiface.AddEvent{
Path: path.IpfsPath(c),
Path: path.FromCid(c),
Size: strconv.FormatUint(s, 10),
}

View File

@ -133,7 +133,7 @@ func TestAddMultipleGCLive(t *testing.T) {
}
for o := range out {
if _, ok := removedHashes[o.(*coreiface.AddEvent).Path.Cid().String()]; ok {
if _, ok := removedHashes[o.(*coreiface.AddEvent).Path.RootCid().String()]; ok {
t.Fatal("gc'ed a hash we just added")
}
}
@ -187,7 +187,7 @@ func TestAddGCLive(t *testing.T) {
addedHashes := make(map[string]struct{})
select {
case o := <-out:
addedHashes[o.(*coreiface.AddEvent).Path.Cid().String()] = struct{}{}
addedHashes[o.(*coreiface.AddEvent).Path.RootCid().String()] = struct{}{}
case <-addDone:
t.Fatal("add shouldn't complete yet")
}
@ -217,7 +217,7 @@ func TestAddGCLive(t *testing.T) {
// receive next object from adder
o := <-out
addedHashes[o.(*coreiface.AddEvent).Path.Cid().String()] = struct{}{}
addedHashes[o.(*coreiface.AddEvent).Path.RootCid().String()] = struct{}{}
<-gcstarted
@ -233,7 +233,7 @@ func TestAddGCLive(t *testing.T) {
var last cid.Cid
for a := range out {
// wait for it to finish
c, err := cid.Decode(a.(*coreiface.AddEvent).Path.Cid().String())
c, err := cid.Decode(a.(*coreiface.AddEvent).Path.RootCid().String())
if err != nil {
t.Fatal(err)
}

View File

@ -7,6 +7,7 @@ import (
"github.com/ipfs/boxo/blockservice"
blockstore "github.com/ipfs/boxo/blockstore"
exchange "github.com/ipfs/boxo/exchange"
offline "github.com/ipfs/boxo/exchange/offline"
"github.com/ipfs/boxo/fetcher"
bsfetcher "github.com/ipfs/boxo/fetcher/impl/blockservice"
"github.com/ipfs/boxo/filestore"
@ -21,9 +22,6 @@ import (
format "github.com/ipfs/go-ipld-format"
"github.com/ipfs/go-unixfsnode"
dagpb "github.com/ipld/go-codec-dagpb"
"github.com/ipld/go-ipld-prime"
basicnode "github.com/ipld/go-ipld-prime/node/basic"
"github.com/ipld/go-ipld-prime/schema"
"go.uber.org/fx"
"github.com/ipfs/kubo/core/node/helpers"
@ -87,43 +85,58 @@ func (s *syncDagService) Session(ctx context.Context) format.NodeGetter {
// FetchersOut allows injection of fetchers.
type FetchersOut struct {
fx.Out
IPLDFetcher fetcher.Factory `name:"ipldFetcher"`
UnixfsFetcher fetcher.Factory `name:"unixfsFetcher"`
IPLDFetcher fetcher.Factory `name:"ipldFetcher"`
UnixfsFetcher fetcher.Factory `name:"unixfsFetcher"`
OfflineIPLDFetcher fetcher.Factory `name:"offlineIpldFetcher"`
OfflineUnixfsFetcher fetcher.Factory `name:"offlineUnixfsFetcher"`
}
// FetchersIn allows using fetchers for other dependencies.
type FetchersIn struct {
fx.In
IPLDFetcher fetcher.Factory `name:"ipldFetcher"`
UnixfsFetcher fetcher.Factory `name:"unixfsFetcher"`
IPLDFetcher fetcher.Factory `name:"ipldFetcher"`
UnixfsFetcher fetcher.Factory `name:"unixfsFetcher"`
OfflineIPLDFetcher fetcher.Factory `name:"offlineIpldFetcher"`
OfflineUnixfsFetcher fetcher.Factory `name:"offlineUnixfsFetcher"`
}
// FetcherConfig returns a fetcher config that can build new fetcher instances
func FetcherConfig(bs blockservice.BlockService) FetchersOut {
ipldFetcher := bsfetcher.NewFetcherConfig(bs)
ipldFetcher.PrototypeChooser = dagpb.AddSupportToChooser(func(lnk ipld.Link, lnkCtx ipld.LinkContext) (ipld.NodePrototype, error) {
if tlnkNd, ok := lnkCtx.LinkNode.(schema.TypedLinkNode); ok {
return tlnkNd.LinkTargetNodePrototype(), nil
}
return basicnode.Prototype.Any, nil
})
ipldFetcher.PrototypeChooser = dagpb.AddSupportToChooser(bsfetcher.DefaultPrototypeChooser)
unixFSFetcher := ipldFetcher.WithReifier(unixfsnode.Reify)
return FetchersOut{IPLDFetcher: ipldFetcher, UnixfsFetcher: unixFSFetcher}
// Construct offline versions which we can safely use in contexts where
// path resolution should not fetch new blocks via exchange.
offlineBs := blockservice.New(bs.Blockstore(), offline.Exchange(bs.Blockstore()))
offlineIpldFetcher := bsfetcher.NewFetcherConfig(offlineBs)
offlineIpldFetcher.PrototypeChooser = dagpb.AddSupportToChooser(bsfetcher.DefaultPrototypeChooser)
offlineUnixFSFetcher := offlineIpldFetcher.WithReifier(unixfsnode.Reify)
return FetchersOut{
IPLDFetcher: ipldFetcher,
UnixfsFetcher: unixFSFetcher,
OfflineIPLDFetcher: offlineIpldFetcher,
OfflineUnixfsFetcher: offlineUnixFSFetcher,
}
}
// PathResolversOut allows injection of path resolvers
type PathResolversOut struct {
fx.Out
IPLDPathResolver pathresolver.Resolver `name:"ipldPathResolver"`
UnixFSPathResolver pathresolver.Resolver `name:"unixFSPathResolver"`
IPLDPathResolver pathresolver.Resolver `name:"ipldPathResolver"`
UnixFSPathResolver pathresolver.Resolver `name:"unixFSPathResolver"`
OfflineIPLDPathResolver pathresolver.Resolver `name:"offlineIpldPathResolver"`
OfflineUnixFSPathResolver pathresolver.Resolver `name:"offlineUnixFSPathResolver"`
}
// PathResolverConfig creates path resolvers with the given fetchers.
func PathResolverConfig(fetchers FetchersIn) PathResolversOut {
return PathResolversOut{
IPLDPathResolver: pathresolver.NewBasicResolver(fetchers.IPLDFetcher),
UnixFSPathResolver: pathresolver.NewBasicResolver(fetchers.UnixfsFetcher),
IPLDPathResolver: pathresolver.NewBasicResolver(fetchers.IPLDFetcher),
UnixFSPathResolver: pathresolver.NewBasicResolver(fetchers.UnixfsFetcher),
OfflineIPLDPathResolver: pathresolver.NewBasicResolver(fetchers.OfflineIPLDFetcher),
OfflineUnixFSPathResolver: pathresolver.NewBasicResolver(fetchers.OfflineUnixfsFetcher),
}
}

View File

@ -3,7 +3,7 @@ package node
import (
"context"
"github.com/ipfs/kubo/peering"
"github.com/ipfs/boxo/peering"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/peer"
"go.uber.org/fx"
@ -18,7 +18,8 @@ func Peering(lc fx.Lifecycle, host host.Host) *peering.PeeringService {
return ps.Start()
},
OnStop: func(context.Context) error {
return ps.Stop()
ps.Stop()
return nil
},
})
return ps

73
docs/changelogs/v0.24.md Normal file
View File

@ -0,0 +1,73 @@
# Kubo changelog v0.24
- [v0.24.0](#v0240)
## v0.24.0
- [Overview](#overview)
- [🔦 Highlights](#-highlights)
- [Support for content blocking](#support-for-content-blocking)
- [Gateway: the root of the CARs are no longer meaningful](#gateway-the-root-of-the-cars-are-no-longer-meaningful)
- [IPNS: improved publishing defaults](#ipns-improved-publishing-defaults)
- [IPNS: record TTL is used for caching](#ipns-record-ttl-is-used-for-caching)
- [📝 Changelog](#-changelog)
- [👨‍👩‍👧‍👦 Contributors](#-contributors)
### Overview
### 🔦 Highlights
#### Support for content blocking
This Kubo release ships with built-in content-blocking subsystem [announced earlier this year](https://blog.ipfs.tech/2023-content-blocking-for-the-ipfs-stack/).
Content blocking is an opt-in decision made by the operator of `ipfs daemon`.
The official build does not ship with any denylists.
Learn more at [`/docs/content-blocking.md`](https://github.com/ipfs/kubo/blob/master/docs/content-blocking.md)
#### Gateway: the root of the CARs are no longer meaningful
When requesting a CAR from the gateway, the root of the CAR might no longer be
meaningful. By default, the CAR root will be the last resolvable segment of the
path. However, in situations where the path cannot be resolved, such as when
the path does not exist, a CAR will be sent with a root of `bafkqaaa` (empty CID).
This CAR will contain all blocks necessary to validate that the path does not exist.
#### IPNS: improved publishing defaults
This release changes the default values used when publishing IPNS record
via `ipfs name publish` command:
- Default `--lifetime` increased from `24h` to `48h` to take full advantage of
the increased expiration window of Amino DHT
([go-libp2p-kad-dht#793](https://github.com/libp2p/go-libp2p-kad-dht/pull/793))
- Default `--ttl` increased from `1m` to `1h` to improve website caching and follow
saner defaults present in similar systems like DNS
([specs#371](https://github.com/ipfs/specs/pull/371))
This change only impacts the implicit defaults, when mentioned parameters are omitted
during publishing. Users are free to override the default if different value
makes more sense for their use case.
#### IPNS: record TTL is used for caching
In this release, we've made significant improvements to IPNS caching.
Previously, the TTL value in IPNS records was not utilized, and the
`boxo/namesys` library maintained a static one-minute resolution cache.
With this update, IPNS publishers gain more control over how long a valid IPNS
record remains cached before checking an upstream routing system, such as Amino
DHT, for updates. The TTL value in the IPNS record now serves as a hint for:
- `boxo/namesys`: the internal cache, determining how long the IPNS resolution
result is cached before asking upsteam routing systems for updates.
- `boxo/gateway`: the `Cache-Control` HTTP header in responses to requests made
for `/ipns/name` content paths.
These changes make it easier for rarely updated IPNS-hosted websites to be
cached more efficiently and load faster in browser contexts.
### 📝 Changelog
### 👨‍👩‍👧‍👦 Contributors

73
docs/content-blocking.md Normal file
View File

@ -0,0 +1,73 @@
<h1 align="center">
<br>
<a href="#readme"><img src="https://github.com/ipfs-shipyard/nopfs/blob/41484a818e6542314f784da852fc41b76f2d48a6/logo.png?raw=true" alt="content blocking logo" title="content blocking in Kubo" width="200"></a>
<br>
Content Blocking in Kubo
<br>
</h1>
Kubo ships with built-in support for denylist format from [IPIP-383](https://github.com/ipfs/specs/pull/383).
## Default behavior
Official Kubo build does not ship with any denylists enabled by default.
Content blocking is an opt-in decision made by the operator of `ipfs daemon`.
## How to enable blocking
Place a `*.deny` file in one of directories:
- `$IPFS_PATH/denylists/` (`$HOME/.ipfs/denylists/` if `IPFS_PATH` is not set)
- `$XDG_CONFIG_HOME/ipfs/denylists/` (`$HOME/.config/ipfs/denylists/` if `XDG_CONFIG_HOME` is not set)
- `/etc/ipfs/denylists/` (global)
Files need to be present before starting the `ipfs daemon` in order to be watched for updates.
If a new denylist file is added, `ipfs daemon` needs to be restarted.
CLI and Gateway users will receive errors in response to request impacted by a blocklist:
```
Error: /ipfs/QmQvjk82hPkSaZsyJ8vNER5cmzKW7HyGX5XVusK7EAenCN is blocked and cannot be provided
```
End user is not informed about the exact reason, see [How to
debug](#how-to-debug) if you need to find out which line of which denylist
caused the request to be blocked.
## Denylist file format
[NOpfs](https://github.com/ipfs-shipyard/nopfs) supports the format from [IPIP-383](https://github.com/ipfs/specs/pull/383).
Clear-text rules are simple: just put content paths to block, one per line.
Paths with unicode and whitespace need to be percend-encoded:
```
/ipfs/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR
/ipfs/bafybeihfg3d7rdltd43u3tfvncx7n5loqofbsobojcadtmokrljfthuc7y/927%20-%20Standards/927%20-%20Standards.png
```
Sensitive content paths can be double-hashed to block without revealing them.
Double-hashed list example: https://badbits.dwebops.pub/badbits.deny
See [IPIP-383](https://github.com/ipfs/specs/pull/383) for detailed format specification and more examples.
## How to suspend blocking without removing denylists
Set `IPFS_CONTENT_BLOCKING_DISABLE` environment variable to `true` and restart the daemon.
## How to debug
Debug logging of `nopfs` subsystem can be enabled with `GOLOG_LOG_LEVEL="nopfs=debug"`
All block events are logged as warnings on a separate level named `nopfs-blocks`.
To only log requests for blocked content set `GOLOG_LOG_LEVEL="nopfs-blocks=warn"`:
```
WARN (...) QmRFniDxwxoG2n4AcnGhRdjqDjCM5YeUcBE75K8WXmioH3: blocked (test.deny:9)
```

View File

@ -131,6 +131,12 @@ The above will replace implicit HTTP routers with single one, allowing for
inspection/debug of HTTP requests sent by Kubo via `while true ; do nc -l 7423; done`
or more advanced tools like [mitmproxy](https://docs.mitmproxy.org/stable/#mitmproxy).
## `IPFS_CONTENT_BLOCKING_DISABLE`
Disables the content-blocking subsystem. No denylists will be watched and no
content will be blocked.
## `LIBP2P_TCP_REUSEPORT`
Kubo tries to reuse the same source port for all connections to improve NAT

View File

@ -7,7 +7,7 @@ go 1.20
replace github.com/ipfs/kubo => ./../../..
require (
github.com/ipfs/boxo v0.13.1
github.com/ipfs/boxo v0.14.0
github.com/ipfs/kubo v0.0.0-00010101000000-000000000000
github.com/libp2p/go-libp2p v0.31.0
github.com/multiformats/go-multiaddr v0.11.0
@ -40,6 +40,7 @@ require (
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect
github.com/flynn/noise v1.0.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.1 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
@ -51,18 +52,20 @@ require (
github.com/golang/snappy v0.0.4 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect
github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/huin/goupnp v1.2.0 // indirect
github.com/ipfs-shipyard/nopfs v0.0.12-0.20231027223058-cde3b5ba964c // indirect
github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c // indirect
github.com/ipfs/bbloom v0.0.4 // indirect
github.com/ipfs/go-bitfield v1.1.0 // indirect
github.com/ipfs/go-block-format v0.1.2 // indirect
github.com/ipfs/go-block-format v0.2.0 // indirect
github.com/ipfs/go-cid v0.4.1 // indirect
github.com/ipfs/go-cidutil v0.1.0 // indirect
github.com/ipfs/go-datastore v0.6.0 // indirect
@ -80,7 +83,7 @@ require (
github.com/ipfs/go-ipfs-redirects-file v0.1.1 // indirect
github.com/ipfs/go-ipfs-util v0.0.3 // indirect
github.com/ipfs/go-ipld-cbor v0.0.6 // indirect
github.com/ipfs/go-ipld-format v0.5.0 // indirect
github.com/ipfs/go-ipld-format v0.6.0 // indirect
github.com/ipfs/go-ipld-git v0.1.1 // indirect
github.com/ipfs/go-ipld-legacy v0.2.1 // indirect
github.com/ipfs/go-log v1.0.5 // indirect
@ -142,10 +145,10 @@ require (
github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/polydawn/refmt v0.89.0 // indirect
github.com/prometheus/client_golang v1.16.0 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/client_golang v1.17.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-20 v0.3.3 // indirect
github.com/quic-go/quic-go v0.38.1 // indirect
@ -162,7 +165,7 @@ require (
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/otel v1.16.0 // indirect
go.opentelemetry.io/otel v1.17.0 // indirect
go.opentelemetry.io/otel/exporters/jaeger v1.14.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 // indirect
@ -170,29 +173,30 @@ require (
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0 // indirect
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.14.0 // indirect
go.opentelemetry.io/otel/exporters/zipkin v1.14.0 // indirect
go.opentelemetry.io/otel/metric v1.16.0 // indirect
go.opentelemetry.io/otel/metric v1.17.0 // indirect
go.opentelemetry.io/otel/sdk v1.16.0 // indirect
go.opentelemetry.io/otel/trace v1.16.0 // indirect
go.opentelemetry.io/otel/trace v1.17.0 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/dig v1.17.0 // indirect
go.uber.org/fx v1.20.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.25.0 // indirect
go.uber.org/zap v1.26.0 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/net v0.15.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/tools v0.13.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
gonum.org/v1/gonum v0.13.0 // indirect
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
google.golang.org/grpc v1.55.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
)

View File

@ -163,6 +163,7 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/gabriel-vasile/mimetype v1.4.1 h1:TRWk7se+TOjCYgRth7+1/OYLNiRNIotknkFtf/dnN7Q=
github.com/gabriel-vasile/mimetype v1.4.1/go.mod h1:05Vi0w3Y9c/lNvJOdmIwvrrAhX3rYhfQQCaf9VJcv7M=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@ -261,8 +262,8 @@ github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f/go.mod h1:czg5+yv1E0Z
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
@ -290,24 +291,28 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY=
github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/ipfs-shipyard/nopfs v0.0.12-0.20231027223058-cde3b5ba964c h1:17FO7HnKiFhO7iadu3zCgII+EblpdRmJt5qg9FqQo8Y=
github.com/ipfs-shipyard/nopfs v0.0.12-0.20231027223058-cde3b5ba964c/go.mod h1:1oj4+g/mN6JRuZiXHt5iFRG02e62wp5AKcB3gdgknbk=
github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c h1:7UynTbtdlt+w08ggb1UGLGaGjp1mMaZhoTZSctpn5Ak=
github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c/go.mod h1:6EekK/jo+TynwSE/ZOiOJd4eEvRXoavEC3vquKtv4yI=
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
github.com/ipfs/boxo v0.13.1 h1:nQ5oQzcMZR3oL41REJDcTbrvDvuZh3J9ckc9+ILeRQI=
github.com/ipfs/boxo v0.13.1/go.mod h1:btrtHy0lmO1ODMECbbEY1pxNtrLilvKSYLoGQt1yYCk=
github.com/ipfs/boxo v0.14.0 h1:gwSGW3xqUbtUOdn71oqBknpBFKpQm352g3I+RkebrX0=
github.com/ipfs/boxo v0.14.0/go.mod h1:pu8HsZvuyYeYJsqtLDCoYSvy8rHj6vI3dlh8P0f83Zs=
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY=
github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk=
github.com/ipfs/go-block-format v0.1.2 h1:GAjkfhVx1f4YTODS6Esrj1wt2HhrtwTnhEr+DyPUaJo=
github.com/ipfs/go-block-format v0.1.2/go.mod h1:mACVcrxarQKstUU3Yf/RdwbC4DzPV6++rO2a3d+a/KE=
github.com/ipfs/go-block-format v0.2.0 h1:ZqrkxBA2ICbDRbK8KJs/u0O3dlp6gmAuuXUJNiW1Ycs=
github.com/ipfs/go-block-format v0.2.0/go.mod h1:+jpL11nFx5A/SPpsoBn6Bzkra/zaArfSmsknbPMYgzM=
github.com/ipfs/go-blockservice v0.5.0 h1:B2mwhhhVQl2ntW2EIpaWPwSCxSuqr5fFA93Ms4bYLEY=
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
@ -365,8 +370,8 @@ github.com/ipfs/go-ipfs-util v0.0.3/go.mod h1:LHzG1a0Ig4G+iZ26UUOMjHd+lfM84LZCrn
github.com/ipfs/go-ipld-cbor v0.0.6 h1:pYuWHyvSpIsOOLw4Jy7NbBkCyzLDcl64Bf/LZW7eBQ0=
github.com/ipfs/go-ipld-cbor v0.0.6/go.mod h1:ssdxxaLJPXH7OjF5V4NSjBbcfh+evoR4ukuru0oPXMA=
github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dCDnkOJhcZkms=
github.com/ipfs/go-ipld-format v0.5.0 h1:WyEle9K96MSrvr47zZHKKcDxJ/vlpET6PSiQsAFO+Ds=
github.com/ipfs/go-ipld-format v0.5.0/go.mod h1:ImdZqJQaEouMjCvqCe0ORUS+uoBmf7Hf+EO/jh+nk3M=
github.com/ipfs/go-ipld-format v0.6.0 h1:VEJlA2kQ3LqFSIm5Vu6eIlSxD/Ze90xtc4Meten1F5U=
github.com/ipfs/go-ipld-format v0.6.0/go.mod h1:g4QVMTn3marU3qXchwjpKPKgJv+zF+OlaKMyhJ4LHPg=
github.com/ipfs/go-ipld-git v0.1.1 h1:TWGnZjS0htmEmlMFEkA3ogrNCqWjIxwr16x1OsdhG+Y=
github.com/ipfs/go-ipld-git v0.1.1/go.mod h1:+VyMqF5lMcJh4rwEppV0e6g4nCCHXThLYYDpKUkJubI=
github.com/ipfs/go-ipld-legacy v0.2.1 h1:mDFtrBpmU7b//LzLSypVrXsD8QxkEWxu5qVxN99/+tk=
@ -624,18 +629,18 @@ github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e/go.mod h1:uIp+gprXx
github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4=
github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/qtls-go1-20 v0.3.3 h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM=
@ -771,8 +776,8 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s=
go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4=
go.opentelemetry.io/otel v1.17.0 h1:MW+phZ6WZ5/uk2nd93ANk/6yJ+dVrvNWUjGhnnFU5jM=
go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0=
go.opentelemetry.io/otel/exporters/jaeger v1.14.0 h1:CjbUNd4iN2hHmWekmOqZ+zSCU+dzZppG8XsV+A3oc8Q=
go.opentelemetry.io/otel/exporters/jaeger v1.14.0/go.mod h1:4Ay9kk5vELRrbg5z4cpP9EtmQRFap2Wb0woPG4lujZA=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 h1:t4ZwRPU+emrcvM2e9DHd0Fsf0JTPVcbfa/BhTDF03d0=
@ -787,12 +792,12 @@ go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.14.0 h1:sEL90JjOO/4yhqu
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.14.0/go.mod h1:oCslUcizYdpKYyS9e8srZEqM6BB8fq41VJBjLAE6z1w=
go.opentelemetry.io/otel/exporters/zipkin v1.14.0 h1:reEVE1upBF9tcujgvSqLJS0SrI7JQPaTKP4s4rymnSs=
go.opentelemetry.io/otel/exporters/zipkin v1.14.0/go.mod h1:RcjvOAcvhzcufQP8aHmzRw1gE9g/VEZufDdo2w+s4sk=
go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo=
go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4=
go.opentelemetry.io/otel/metric v1.17.0 h1:iG6LGVz5Gh+IuO0jmgvpTB6YVrCGngi8QGm+pMd8Pdc=
go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o=
go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE=
go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4=
go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs=
go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0=
go.opentelemetry.io/otel/trace v1.17.0 h1:/SWhSRHmDPOImIAetP1QAeMnZYiQXrTy4fMMYOdSKWQ=
go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw=
go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
@ -817,8 +822,8 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
go4.org v0.0.0-20200411211856-f5505b9728dd/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZMZXMSBGhxRdsvzbkg=
go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc=
@ -840,8 +845,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -852,8 +857,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ=
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -921,8 +926,8 @@ golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -1001,10 +1006,11 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -1018,8 +1024,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -1077,8 +1083,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E=
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -12,8 +12,8 @@ import (
"sync"
icore "github.com/ipfs/boxo/coreiface"
icorepath "github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/files"
"github.com/ipfs/boxo/path"
ma "github.com/multiformats/go-multiaddr"
"github.com/ipfs/kubo/config"
@ -320,11 +320,11 @@ func main() {
}
}()
exampleCIDStr := peerCidFile.Cid().String()
exampleCIDStr := peerCidFile.RootCid().String()
fmt.Printf("Fetching a file from the network with CID %s\n", exampleCIDStr)
outputPath := outputBasePath + exampleCIDStr
testCID := icorepath.New(exampleCIDStr)
testCID := path.FromCid(peerCidFile.RootCid())
rootNode, err := ipfsB.Unixfs().Get(ctx, testCID)
if err != nil {

View File

@ -2,12 +2,6 @@
Kubo provides official HTTP RPC (`/api/v0`) clients for selected languages:
- [`js-kubo-rpc-client`](https://github.com/ipfs/js-kubo-rpc-client) - Official JS client for talking to Kubo RPC over HTTP
- [`go-ipfs-api`](https://github.com/ipfs/go-ipfs-api) - The go interface to ipfs's HTTP RPC - Follow https://github.com/ipfs/kubo/issues/9124 for coming changes.
- [`httpapi`](./client/rpc) (previously `go-ipfs-http-client`) - [`coreiface.CoreAPI`](https://pkg.go.dev/github.com/ipfs/boxo/coreiface#CoreAPI) implementation using HTTP RPC
## Recommended clients
| Language | Package Name | Github Repository |
|:--------:|:-------------------:|--------------------------------------------|
| JS | kubo-rpc-client | https://github.com/ipfs/js-kubo-rpc-client |

View File

@ -4,8 +4,8 @@ import (
"context"
ft "github.com/ipfs/boxo/ipld/unixfs"
nsys "github.com/ipfs/boxo/namesys"
path "github.com/ipfs/boxo/path"
"github.com/ipfs/boxo/namesys"
"github.com/ipfs/boxo/path"
"github.com/ipfs/kubo/core"
ci "github.com/libp2p/go-libp2p/core/crypto"
)
@ -28,7 +28,7 @@ func InitializeKeyspace(n *core.IpfsNode, key ci.PrivKey) error {
return err
}
pub := nsys.NewIpnsPublisher(n.Routing, n.Repo.Datastore())
pub := namesys.NewIPNSPublisher(n.Routing, n.Repo.Datastore())
return pub.Publish(ctx, key, path.FromCid(emptyDir.Cid()))
}

View File

@ -14,9 +14,9 @@ import (
"strings"
"syscall"
path "github.com/ipfs/boxo/coreiface/path"
dag "github.com/ipfs/boxo/ipld/merkledag"
ft "github.com/ipfs/boxo/ipld/unixfs"
"github.com/ipfs/boxo/path"
fuse "bazil.org/fuse"
fs "bazil.org/fuse/fs"
@ -86,7 +86,7 @@ type Root struct {
func ipnsPubFunc(ipfs iface.CoreAPI, key iface.Key) mfs.PubFunc {
return func(ctx context.Context, c cid.Cid) error {
_, err := ipfs.Name().Publish(ctx, path.IpfsPath(c), options.Name.Key(key.Name()))
_, err := ipfs.Name().Publish(ctx, path.FromCid(c), options.Name.Key(key.Name()))
return err
}
}
@ -186,7 +186,7 @@ func (r *Root) Lookup(ctx context.Context, name string) (fs.Node, error) {
return nil, syscall.Errno(syscall.ENOENT)
}
if resolved.Namespace() != "ipfs" {
if resolved.Namespace() != path.IPFSNamespace {
return nil, errors.New("invalid path from ipns record")
}

View File

@ -11,7 +11,7 @@ import (
"io"
"math/rand"
"os"
"path"
gopath "path"
"strings"
"sync"
"testing"
@ -24,11 +24,11 @@ import (
fstest "bazil.org/fuse/fs/fstestutil"
chunker "github.com/ipfs/boxo/chunker"
ipath "github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/files"
dag "github.com/ipfs/boxo/ipld/merkledag"
importer "github.com/ipfs/boxo/ipld/unixfs/importer"
uio "github.com/ipfs/boxo/ipld/unixfs/io"
"github.com/ipfs/boxo/path"
u "github.com/ipfs/boxo/util"
ipld "github.com/ipfs/go-ipld-format"
ci "github.com/libp2p/go-libp2p-testing/ci"
@ -89,7 +89,7 @@ func TestIpfsBasicRead(t *testing.T) {
fi, data := randObj(t, nd, 10000)
k := fi.Cid()
fname := path.Join(mnt.Dir, k.String())
fname := gopath.Join(mnt.Dir, k.String())
rbuf, err := os.ReadFile(fname)
if err != nil {
t.Fatal(err)
@ -116,7 +116,7 @@ func getPaths(t *testing.T, ipfs *core.IpfsNode, name string, n *dag.ProtoNode)
t.Fatal(dag.ErrNotProtobuf)
}
sub := getPaths(t, ipfs, path.Join(name, lnk.Name), childpb)
sub := getPaths(t, ipfs, gopath.Join(name, lnk.Name), childpb)
out = append(out, sub...)
}
return out
@ -184,10 +184,14 @@ func TestIpfsStressRead(t *testing.T) {
defer wg.Done()
for i := 0; i < 2000; i++ {
item := ipath.New(paths[rand.Intn(len(paths))])
item, err := path.NewPath(paths[rand.Intn(len(paths))])
if err != nil {
errs <- err
continue
}
relpath := strings.Replace(item.String(), item.Namespace(), "", 1)
fname := path.Join(mnt.Dir, relpath)
fname := gopath.Join(mnt.Dir, relpath)
rbuf, err := os.ReadFile(fname)
if err != nil {
@ -257,8 +261,8 @@ func TestIpfsBasicDirRead(t *testing.T) {
t.Fatal(err)
}
dirname := path.Join(mnt.Dir, d1nd.Cid().String())
fname := path.Join(dirname, "actual")
dirname := gopath.Join(mnt.Dir, d1nd.Cid().String())
fname := gopath.Join(dirname, "actual")
rbuf, err := os.ReadFile(fname)
if err != nil {
t.Fatal(err)
@ -291,7 +295,7 @@ func TestFileSizeReporting(t *testing.T) {
fi, data := randObj(t, nd, 10000)
k := fi.Cid()
fname := path.Join(mnt.Dir, k.String())
fname := gopath.Join(mnt.Dir, k.String())
finfo, err := os.Stat(fname)
if err != nil {

View File

@ -16,7 +16,7 @@ import (
mdag "github.com/ipfs/boxo/ipld/merkledag"
ft "github.com/ipfs/boxo/ipld/unixfs"
uio "github.com/ipfs/boxo/ipld/unixfs/io"
path "github.com/ipfs/boxo/path"
"github.com/ipfs/boxo/path"
"github.com/ipfs/go-cid"
ipld "github.com/ipfs/go-ipld-format"
logging "github.com/ipfs/go-log"
@ -62,13 +62,19 @@ func (s *Root) Lookup(ctx context.Context, name string) (fs.Node, error) {
return nil, syscall.Errno(syscall.ENOENT)
}
p, err := path.ParsePath(name)
p, err := path.NewPath(name)
if err != nil {
log.Debugf("fuse failed to parse path: %q: %s", name, err)
return nil, syscall.Errno(syscall.ENOENT)
}
nd, ndLnk, err := s.Ipfs.UnixFSPathResolver.ResolvePath(ctx, p)
imPath, err := path.NewImmutablePath(p)
if err != nil {
log.Debugf("fuse failed to convert path: %q: %s", name, err)
return nil, syscall.Errno(syscall.ENOENT)
}
nd, ndLnk, err := s.Ipfs.UnixFSPathResolver.ResolvePath(ctx, imPath)
if err != nil {
// todo: make this error more versatile.
return nil, syscall.Errno(syscall.ENOENT)

40
go.mod
View File

@ -13,10 +13,12 @@ require (
github.com/elgris/jsondiff v0.0.0-20160530203242-765b5c24c302
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5
github.com/fsnotify/fsnotify v1.6.0
github.com/google/uuid v1.3.0
github.com/google/uuid v1.3.1
github.com/hashicorp/go-multierror v1.1.1
github.com/ipfs/boxo v0.13.1
github.com/ipfs/go-block-format v0.1.2
github.com/ipfs-shipyard/nopfs v0.0.12-0.20231027223058-cde3b5ba964c
github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c
github.com/ipfs/boxo v0.14.0
github.com/ipfs/go-block-format v0.2.0
github.com/ipfs/go-cid v0.4.1
github.com/ipfs/go-cidutil v0.1.0
github.com/ipfs/go-datastore v0.6.0
@ -28,7 +30,7 @@ require (
github.com/ipfs/go-fs-lock v0.0.7
github.com/ipfs/go-graphsync v0.15.1
github.com/ipfs/go-ipfs-cmds v0.10.0
github.com/ipfs/go-ipld-format v0.5.0
github.com/ipfs/go-ipld-format v0.6.0
github.com/ipfs/go-ipld-git v0.1.1
github.com/ipfs/go-ipld-legacy v0.2.1
github.com/ipfs/go-log v1.0.5
@ -65,7 +67,7 @@ require (
github.com/opentracing/opentracing-go v1.2.0
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.16.0
github.com/prometheus/client_golang v1.17.0
github.com/stretchr/testify v1.8.4
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
github.com/tidwall/gjson v1.14.4
@ -75,18 +77,18 @@ require (
go.opencensus.io v0.24.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0
go.opentelemetry.io/contrib/propagators/autoprop v0.42.0
go.opentelemetry.io/otel v1.16.0
go.opentelemetry.io/otel v1.17.0
go.opentelemetry.io/otel/sdk v1.16.0
go.opentelemetry.io/otel/trace v1.16.0
go.opentelemetry.io/otel/trace v1.17.0
go.uber.org/dig v1.17.0
go.uber.org/fx v1.20.0
go.uber.org/multierr v1.11.0
go.uber.org/zap v1.25.0
golang.org/x/crypto v0.12.0
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63
go.uber.org/zap v1.26.0
golang.org/x/crypto v0.14.0
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
golang.org/x/mod v0.12.0
golang.org/x/sync v0.3.0
golang.org/x/sys v0.11.0
golang.org/x/sys v0.13.0
google.golang.org/protobuf v1.31.0
)
@ -131,7 +133,7 @@ require (
github.com/hannahhoward/go-pubsub v0.0.0-20200423002714-8d62886cc36e // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/huin/goupnp v1.2.0 // indirect
github.com/ipfs/bbloom v0.0.4 // indirect
github.com/ipfs/go-bitfield v1.1.0 // indirect
@ -186,9 +188,9 @@ require (
github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/polydawn/refmt v0.89.0 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/prometheus/statsd_exporter v0.22.7 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-20 v0.3.3 // indirect
@ -218,15 +220,15 @@ require (
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0 // indirect
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.14.0 // indirect
go.opentelemetry.io/otel/exporters/zipkin v1.14.0 // indirect
go.opentelemetry.io/otel/metric v1.16.0 // indirect
go.opentelemetry.io/otel/metric v1.17.0 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/net v0.15.0 // indirect
golang.org/x/oauth2 v0.8.0 // indirect
golang.org/x/term v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
golang.org/x/term v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/tools v0.13.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
gonum.org/v1/gonum v0.13.0 // indirect
google.golang.org/appengine v1.6.7 // indirect

80
go.sum
View File

@ -295,8 +295,8 @@ github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f/go.mod h1:czg5+yv1E0Z
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
@ -325,25 +325,29 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY=
github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/ipfs-shipyard/nopfs v0.0.12-0.20231027223058-cde3b5ba964c h1:17FO7HnKiFhO7iadu3zCgII+EblpdRmJt5qg9FqQo8Y=
github.com/ipfs-shipyard/nopfs v0.0.12-0.20231027223058-cde3b5ba964c/go.mod h1:1oj4+g/mN6JRuZiXHt5iFRG02e62wp5AKcB3gdgknbk=
github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c h1:7UynTbtdlt+w08ggb1UGLGaGjp1mMaZhoTZSctpn5Ak=
github.com/ipfs-shipyard/nopfs/ipfs v0.13.2-0.20231027223058-cde3b5ba964c/go.mod h1:6EekK/jo+TynwSE/ZOiOJd4eEvRXoavEC3vquKtv4yI=
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
github.com/ipfs/boxo v0.13.1 h1:nQ5oQzcMZR3oL41REJDcTbrvDvuZh3J9ckc9+ILeRQI=
github.com/ipfs/boxo v0.13.1/go.mod h1:btrtHy0lmO1ODMECbbEY1pxNtrLilvKSYLoGQt1yYCk=
github.com/ipfs/boxo v0.14.0 h1:gwSGW3xqUbtUOdn71oqBknpBFKpQm352g3I+RkebrX0=
github.com/ipfs/boxo v0.14.0/go.mod h1:pu8HsZvuyYeYJsqtLDCoYSvy8rHj6vI3dlh8P0f83Zs=
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
github.com/ipfs/go-bitswap v0.11.0 h1:j1WVvhDX1yhG32NTC9xfxnqycqYIlhzEzLXG/cU1HyQ=
github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY=
github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk=
github.com/ipfs/go-block-format v0.1.2 h1:GAjkfhVx1f4YTODS6Esrj1wt2HhrtwTnhEr+DyPUaJo=
github.com/ipfs/go-block-format v0.1.2/go.mod h1:mACVcrxarQKstUU3Yf/RdwbC4DzPV6++rO2a3d+a/KE=
github.com/ipfs/go-block-format v0.2.0 h1:ZqrkxBA2ICbDRbK8KJs/u0O3dlp6gmAuuXUJNiW1Ycs=
github.com/ipfs/go-block-format v0.2.0/go.mod h1:+jpL11nFx5A/SPpsoBn6Bzkra/zaArfSmsknbPMYgzM=
github.com/ipfs/go-blockservice v0.5.0 h1:B2mwhhhVQl2ntW2EIpaWPwSCxSuqr5fFA93Ms4bYLEY=
github.com/ipfs/go-blockservice v0.5.0/go.mod h1:W6brZ5k20AehbmERplmERn8o2Ni3ZZubvAxaIUeaT6w=
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
@ -405,8 +409,8 @@ github.com/ipfs/go-ipfs-util v0.0.3/go.mod h1:LHzG1a0Ig4G+iZ26UUOMjHd+lfM84LZCrn
github.com/ipfs/go-ipld-cbor v0.0.6 h1:pYuWHyvSpIsOOLw4Jy7NbBkCyzLDcl64Bf/LZW7eBQ0=
github.com/ipfs/go-ipld-cbor v0.0.6/go.mod h1:ssdxxaLJPXH7OjF5V4NSjBbcfh+evoR4ukuru0oPXMA=
github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dCDnkOJhcZkms=
github.com/ipfs/go-ipld-format v0.5.0 h1:WyEle9K96MSrvr47zZHKKcDxJ/vlpET6PSiQsAFO+Ds=
github.com/ipfs/go-ipld-format v0.5.0/go.mod h1:ImdZqJQaEouMjCvqCe0ORUS+uoBmf7Hf+EO/jh+nk3M=
github.com/ipfs/go-ipld-format v0.6.0 h1:VEJlA2kQ3LqFSIm5Vu6eIlSxD/Ze90xtc4Meten1F5U=
github.com/ipfs/go-ipld-format v0.6.0/go.mod h1:g4QVMTn3marU3qXchwjpKPKgJv+zF+OlaKMyhJ4LHPg=
github.com/ipfs/go-ipld-git v0.1.1 h1:TWGnZjS0htmEmlMFEkA3ogrNCqWjIxwr16x1OsdhG+Y=
github.com/ipfs/go-ipld-git v0.1.1/go.mod h1:+VyMqF5lMcJh4rwEppV0e6g4nCCHXThLYYDpKUkJubI=
github.com/ipfs/go-ipld-legacy v0.2.1 h1:mDFtrBpmU7b//LzLSypVrXsD8QxkEWxu5qVxN99/+tk=
@ -712,14 +716,14 @@ github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqr
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
@ -738,8 +742,8 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0=
github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
@ -909,8 +913,8 @@ go.opentelemetry.io/contrib/propagators/jaeger v1.17.0 h1:Zbpbmwav32Ea5jSotpmkWE
go.opentelemetry.io/contrib/propagators/jaeger v1.17.0/go.mod h1:tcTUAlmO8nuInPDSBVfG+CP6Mzjy5+gNV4mPxMbL0IA=
go.opentelemetry.io/contrib/propagators/ot v1.17.0 h1:ufo2Vsz8l76eI47jFjuVyjyB3Ae2DmfiCV/o6Vc8ii0=
go.opentelemetry.io/contrib/propagators/ot v1.17.0/go.mod h1:SbKPj5XGp8K/sGm05XblaIABgMgw2jDczP8gGeuaVLk=
go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s=
go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4=
go.opentelemetry.io/otel v1.17.0 h1:MW+phZ6WZ5/uk2nd93ANk/6yJ+dVrvNWUjGhnnFU5jM=
go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0=
go.opentelemetry.io/otel/exporters/jaeger v1.14.0 h1:CjbUNd4iN2hHmWekmOqZ+zSCU+dzZppG8XsV+A3oc8Q=
go.opentelemetry.io/otel/exporters/jaeger v1.14.0/go.mod h1:4Ay9kk5vELRrbg5z4cpP9EtmQRFap2Wb0woPG4lujZA=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 h1:t4ZwRPU+emrcvM2e9DHd0Fsf0JTPVcbfa/BhTDF03d0=
@ -925,12 +929,12 @@ go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.14.0 h1:sEL90JjOO/4yhqu
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.14.0/go.mod h1:oCslUcizYdpKYyS9e8srZEqM6BB8fq41VJBjLAE6z1w=
go.opentelemetry.io/otel/exporters/zipkin v1.14.0 h1:reEVE1upBF9tcujgvSqLJS0SrI7JQPaTKP4s4rymnSs=
go.opentelemetry.io/otel/exporters/zipkin v1.14.0/go.mod h1:RcjvOAcvhzcufQP8aHmzRw1gE9g/VEZufDdo2w+s4sk=
go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo=
go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4=
go.opentelemetry.io/otel/metric v1.17.0 h1:iG6LGVz5Gh+IuO0jmgvpTB6YVrCGngi8QGm+pMd8Pdc=
go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o=
go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE=
go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4=
go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs=
go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0=
go.opentelemetry.io/otel/trace v1.17.0 h1:/SWhSRHmDPOImIAetP1QAeMnZYiQXrTy4fMMYOdSKWQ=
go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw=
go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
@ -955,8 +959,8 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
go4.org v0.0.0-20200411211856-f5505b9728dd/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZMZXMSBGhxRdsvzbkg=
go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc=
@ -978,8 +982,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -990,8 +994,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ=
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -1065,8 +1069,8 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -1164,14 +1168,14 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1181,8 +1185,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -1240,8 +1244,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E=
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -1,73 +0,0 @@
{
"columns": [
"Name",
"CI/Travis",
"Coverage",
"Description"
],
"rows": [
"Libp2p",
["libp2p/go-libp2p", "go-libp2p", "p2p networking library"],
["libp2p/go-libp2p-pubsub", "go-libp2p-pubsub", "pubsub built on libp2p"],
["libp2p/go-libp2p-kad-dht", "go-libp2p-kad-dht", "dht-backed router"],
["libp2p/go-libp2p-pubsub-router", "go-libp2p-pubsub-router", "pubsub-backed router"],
"Multiformats",
["ipfs/go-cid", "go-cid", "CID implementation"],
["multiformats/go-multiaddr", "go-multiaddr", "multiaddr implementation"],
["multiformats/go-multihash", "go-multihash", "multihash implementation"],
["multiformats/go-multibase", "go-multibase", "mulitbase implementation"],
"Files",
["ipfs/go-unixfs", "go-unixfs", "the core 'filesystem' logic"],
["ipfs/go-mfs", "go-mfs", "a mutable filesystem editor for unixfs"],
["ipfs/go-ipfs-posinfo", "go-ipfs-posinfo", "helper datatypes for the filestore"],
["ipfs/go-ipfs-chunker", "go-ipfs-chunker", "file chunkers"],
"Exchange",
["ipfs/go-ipfs-exchange-interface", "go-ipfs-exchange-interface", "exchange service interface"],
["ipfs/go-ipfs-exchange-offline", "go-ipfs-exchange-offline", "(dummy) offline implementation of the exchange service"],
["ipfs/go-bitswap", "go-bitswap", "bitswap protocol implementation"],
["ipfs/go-blockservice", "go-blockservice", "service that plugs a blockstore and an exchange together"],
"Datastores",
["ipfs/go-datastore", "go-datastore", "datastore interfaces, adapters, and basic implementations"],
["ipfs/go-ipfs-ds-help", "go-ipfs-ds-help", "datastore utility functions"],
["ipfs/go-ds-flatfs", "go-ds-flatfs", "a filesystem-based datastore"],
["ipfs/go-ds-measure", "go-ds-measure", "a metric-collecting database adapter"],
["ipfs/go-ds-leveldb", "go-ds-leveldb", "a leveldb based datastore"],
["ipfs/go-ds-badger", "go-ds-badger", "a badgerdb based datastore"],
"Namesys",
["ipfs/go-ipns", "go-ipns", "IPNS datastructures and validation logic"],
"Repo",
["ipfs/go-fs-lock", "go-fs-lock", "lockfile management functions"],
["ipfs/fs-repo-migrations", "fs-repo-migrations", "repo migrations"],
"IPLD",
["ipfs/go-block-format", "go-block-format", "block interfaces and implementations"],
["ipfs/go-ipfs-blockstore", "go-ipfs-blockstore", "blockstore interfaces and implementations"],
["ipfs/go-ipld-format", "go-ipld-format", "IPLD interfaces"],
["ipfs/go-ipld-cbor", "go-ipld-cbor", "IPLD-CBOR implementation"],
["ipfs/go-ipld-git", "go-ipld-git", "IPLD-Git implementation"],
["ipfs/go-merkledag", "go-merkledag", "IPLD-Merkledag implementation (and then some)"],
"Commands",
["ipfs/go-ipfs-cmds", "go-ipfs-cmds", "CLI & HTTP commands library"],
["ipfs/go-ipfs-files", "go-ipfs-files", "CLI & HTTP commands library"],
["ipfs/go-ipfs-api", "go-ipfs-api", "an old, stable shell for the IPFS HTTP API"],
["ipfs/go-ipfs-http-client", "go-ipfs-http-client", "a new, unstable shell for the IPFS HTTP API"],
["ipfs/interface-go-ipfs-core", "interface-go-ipfs-core", "core go-ipfs API interface definitions"],
"Metrics & Logging",
["ipfs/go-metrics-interface", "go-metrics-interface", "metrics collection interfaces"],
["ipfs/go-metrics-prometheus", "go-metrics-prometheus", "prometheus-backed metrics collector"],
["ipfs/go-log", "go-log", "logging framework"],
"Generics/Utils",
["ipfs/go-ipfs-routing", "go-ipfs-routing", "routing (content, peer, value) helpers"],
["ipfs/go-ipfs-util", "go-ipfs-util", "the kitchen sink"],
["ipfs/go-ipfs-addr", "go-ipfs-addr", "utility functions for parsing IPFS multiaddrs"]
]
}

View File

@ -1,325 +0,0 @@
package peering
import (
"context"
"errors"
"math/rand"
"strconv"
"sync"
"time"
"github.com/ipfs/go-log"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/multiformats/go-multiaddr"
)
// Seed the random number generator.
//
// We don't need good randomness, but we do need randomness.
const (
// maxBackoff is the maximum time between reconnect attempts.
maxBackoff = 10 * time.Minute
// The backoff will be cut off when we get within 10% of the actual max.
// If we go over the max, we'll adjust the delay down to a random value
// between 90-100% of the max backoff.
maxBackoffJitter = 10 // %
connmgrTag = "ipfs-peering"
// This needs to be sufficient to prevent two sides from simultaneously
// dialing.
initialDelay = 5 * time.Second
)
var logger = log.Logger("peering")
type State uint
func (s State) String() string {
switch s {
case StateInit:
return "init"
case StateRunning:
return "running"
case StateStopped:
return "stopped"
default:
return "unknown peering state: " + strconv.FormatUint(uint64(s), 10)
}
}
const (
StateInit State = iota
StateRunning
StateStopped
)
// peerHandler keeps track of all state related to a specific "peering" peer.
type peerHandler struct {
peer peer.ID
host host.Host
ctx context.Context
cancel context.CancelFunc
mu sync.Mutex
addrs []multiaddr.Multiaddr
reconnectTimer *time.Timer
nextDelay time.Duration
}
// setAddrs sets the addresses for this peer.
func (ph *peerHandler) setAddrs(addrs []multiaddr.Multiaddr) {
// Not strictly necessary, but it helps to not trust the calling code.
addrCopy := make([]multiaddr.Multiaddr, len(addrs))
copy(addrCopy, addrs)
ph.mu.Lock()
defer ph.mu.Unlock()
ph.addrs = addrCopy
}
// getAddrs returns a shared slice of addresses for this peer. Do not modify.
func (ph *peerHandler) getAddrs() []multiaddr.Multiaddr {
ph.mu.Lock()
defer ph.mu.Unlock()
return ph.addrs
}
// stop permanently stops the peer handler.
func (ph *peerHandler) stop() {
ph.cancel()
ph.mu.Lock()
defer ph.mu.Unlock()
if ph.reconnectTimer != nil {
ph.reconnectTimer.Stop()
ph.reconnectTimer = nil
}
}
func (ph *peerHandler) nextBackoff() time.Duration {
if ph.nextDelay < maxBackoff {
ph.nextDelay += ph.nextDelay/2 + time.Duration(rand.Int63n(int64(ph.nextDelay)))
}
// If we've gone over the max backoff, reduce it under the max.
if ph.nextDelay > maxBackoff {
ph.nextDelay = maxBackoff
// randomize the backoff a bit (10%).
ph.nextDelay -= time.Duration(rand.Int63n(int64(maxBackoff) * maxBackoffJitter / 100))
}
return ph.nextDelay
}
func (ph *peerHandler) reconnect() {
// Try connecting
addrs := ph.getAddrs()
logger.Debugw("reconnecting", "peer", ph.peer, "addrs", addrs)
err := ph.host.Connect(ph.ctx, peer.AddrInfo{ID: ph.peer, Addrs: addrs})
if err != nil {
logger.Debugw("failed to reconnect", "peer", ph.peer, "error", err)
// Ok, we failed. Extend the timeout.
ph.mu.Lock()
if ph.reconnectTimer != nil {
// Only counts if the reconnectTimer still exists. If not, a
// connection _was_ somehow established.
ph.reconnectTimer.Reset(ph.nextBackoff())
}
// Otherwise, someone else has stopped us so we can assume that
// we're either connected or someone else will start us.
ph.mu.Unlock()
}
// Always call this. We could have connected since we processed the
// error.
ph.stopIfConnected()
}
func (ph *peerHandler) stopIfConnected() {
ph.mu.Lock()
defer ph.mu.Unlock()
if ph.reconnectTimer != nil && ph.host.Network().Connectedness(ph.peer) == network.Connected {
logger.Debugw("successfully reconnected", "peer", ph.peer)
ph.reconnectTimer.Stop()
ph.reconnectTimer = nil
ph.nextDelay = initialDelay
}
}
// startIfDisconnected is the inverse of stopIfConnected.
func (ph *peerHandler) startIfDisconnected() {
ph.mu.Lock()
defer ph.mu.Unlock()
if ph.reconnectTimer == nil && ph.host.Network().Connectedness(ph.peer) != network.Connected {
logger.Debugw("disconnected from peer", "peer", ph.peer)
// Always start with a short timeout so we can stagger things a bit.
ph.reconnectTimer = time.AfterFunc(ph.nextBackoff(), ph.reconnect)
}
}
// PeeringService maintains connections to specified peers, reconnecting on
// disconnect with a back-off.
type PeeringService struct {
host host.Host
mu sync.RWMutex
peers map[peer.ID]*peerHandler
state State
}
// NewPeeringService constructs a new peering service. Peers can be added and
// removed immediately, but connections won't be formed until `Start` is called.
func NewPeeringService(host host.Host) *PeeringService {
return &PeeringService{host: host, peers: make(map[peer.ID]*peerHandler)}
}
// Start starts the peering service, connecting and maintaining connections to
// all registered peers. It returns an error if the service has already been
// stopped.
func (ps *PeeringService) Start() error {
ps.mu.Lock()
defer ps.mu.Unlock()
switch ps.state {
case StateInit:
logger.Infow("starting")
case StateRunning:
return nil
case StateStopped:
return errors.New("already stopped")
}
ps.host.Network().Notify((*netNotifee)(ps))
ps.state = StateRunning
for _, handler := range ps.peers {
go handler.startIfDisconnected()
}
return nil
}
// GetState get the State of the PeeringService.
func (ps *PeeringService) GetState() State {
ps.mu.RLock()
defer ps.mu.RUnlock()
return ps.state
}
// Stop stops the peering service.
func (ps *PeeringService) Stop() error {
ps.host.Network().StopNotify((*netNotifee)(ps))
ps.mu.Lock()
defer ps.mu.Unlock()
switch ps.state {
case StateInit, StateRunning:
logger.Infow("stopping")
for _, handler := range ps.peers {
handler.stop()
}
ps.state = StateStopped
}
return nil
}
// AddPeer adds a peer to the peering service. This function may be safely
// called at any time: before the service is started, while running, or after it
// stops.
//
// Add peer may also be called multiple times for the same peer. The new
// addresses will replace the old.
func (ps *PeeringService) AddPeer(info peer.AddrInfo) {
ps.mu.Lock()
defer ps.mu.Unlock()
if handler, ok := ps.peers[info.ID]; ok {
logger.Infow("updating addresses", "peer", info.ID, "addrs", info.Addrs)
handler.setAddrs(info.Addrs)
} else {
logger.Infow("peer added", "peer", info.ID, "addrs", info.Addrs)
ps.host.ConnManager().Protect(info.ID, connmgrTag)
handler = &peerHandler{
host: ps.host,
peer: info.ID,
addrs: info.Addrs,
nextDelay: initialDelay,
}
handler.ctx, handler.cancel = context.WithCancel(context.Background())
ps.peers[info.ID] = handler
switch ps.state {
case StateRunning:
go handler.startIfDisconnected()
case StateStopped:
// We still construct everything in this state because
// it's easier to reason about. But we should still free
// resources.
handler.cancel()
}
}
}
// ListPeers lists peers in the peering service.
func (ps *PeeringService) ListPeers() []peer.AddrInfo {
ps.mu.RLock()
defer ps.mu.RUnlock()
out := make([]peer.AddrInfo, 0, len(ps.peers))
for id, addrs := range ps.peers {
ai := peer.AddrInfo{ID: id}
ai.Addrs = append(ai.Addrs, addrs.addrs...)
out = append(out, ai)
}
return out
}
// RemovePeer removes a peer from the peering service. This function may be
// safely called at any time: before the service is started, while running, or
// after it stops.
func (ps *PeeringService) RemovePeer(id peer.ID) {
ps.mu.Lock()
defer ps.mu.Unlock()
if handler, ok := ps.peers[id]; ok {
logger.Infow("peer removed", "peer", id)
ps.host.ConnManager().Unprotect(id, connmgrTag)
handler.stop()
delete(ps.peers, id)
}
}
type netNotifee PeeringService
func (nn *netNotifee) Connected(_ network.Network, c network.Conn) {
ps := (*PeeringService)(nn)
p := c.RemotePeer()
ps.mu.RLock()
defer ps.mu.RUnlock()
if handler, ok := ps.peers[p]; ok {
// use a goroutine to avoid blocking events.
go handler.stopIfConnected()
}
}
func (nn *netNotifee) Disconnected(_ network.Network, c network.Conn) {
ps := (*PeeringService)(nn)
p := c.RemotePeer()
ps.mu.RLock()
defer ps.mu.RUnlock()
if handler, ok := ps.peers[p]; ok {
// use a goroutine to avoid blocking events.
go handler.startIfDisconnected()
}
}
func (nn *netNotifee) OpenedStream(network.Network, network.Stream) {}
func (nn *netNotifee) ClosedStream(network.Network, network.Stream) {}
func (nn *netNotifee) Listen(network.Network, multiaddr.Multiaddr) {}
func (nn *netNotifee) ListenClose(network.Network, multiaddr.Multiaddr) {}

View File

@ -1,172 +0,0 @@
package peering
import (
"context"
"testing"
"time"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/p2p/net/connmgr"
"github.com/stretchr/testify/require"
)
func newNode(t *testing.T) host.Host {
cm, err := connmgr.NewConnManager(1, 100, connmgr.WithGracePeriod(0))
require.NoError(t, err)
h, err := libp2p.New(
libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0"),
// We'd like to set the connection manager low water to 0, but
// that would disable the connection manager.
libp2p.ConnectionManager(cm),
)
require.NoError(t, err)
return h
}
func TestPeeringService(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
h1 := newNode(t)
ps1 := NewPeeringService(h1)
h2 := newNode(t)
h3 := newNode(t)
h4 := newNode(t)
// peer 1 -> 2
ps1.AddPeer(peer.AddrInfo{ID: h2.ID(), Addrs: h2.Addrs()})
require.Contains(t, ps1.ListPeers(), peer.AddrInfo{ID: h2.ID(), Addrs: h2.Addrs()})
// We haven't started so we shouldn't have any peers.
require.Never(t, func() bool {
return len(h1.Network().Peers()) > 0
}, 100*time.Millisecond, 1*time.Second, "expected host 1 to have no peers")
// Use p4 to take up the one slot we have in the connection manager.
for _, h := range []host.Host{h1, h2} {
require.NoError(t, h.Connect(ctx, peer.AddrInfo{ID: h4.ID(), Addrs: h4.Addrs()}))
h.ConnManager().TagPeer(h4.ID(), "sticky-peer", 1000)
}
// Now start.
require.NoError(t, ps1.Start())
// starting twice is fine.
require.NoError(t, ps1.Start())
// We should eventually connect.
t.Logf("waiting for h1 to connect to h2")
require.Eventually(t, func() bool {
return h1.Network().Connectedness(h2.ID()) == network.Connected
}, 30*time.Second, 10*time.Millisecond)
// Now explicitly connect to h3.
t.Logf("waiting for h1's connection to h3 to work")
require.NoError(t, h1.Connect(ctx, peer.AddrInfo{ID: h3.ID(), Addrs: h3.Addrs()}))
require.Eventually(t, func() bool {
return h1.Network().Connectedness(h3.ID()) == network.Connected
}, 30*time.Second, 100*time.Millisecond)
require.Len(t, h1.Network().Peers(), 3)
// force a disconnect
h1.ConnManager().TrimOpenConns(ctx)
// Should disconnect from h3.
t.Logf("waiting for h1's connection to h3 to disconnect")
require.Eventually(t, func() bool {
return h1.Network().Connectedness(h3.ID()) != network.Connected
}, 5*time.Second, 10*time.Millisecond)
// Should remain connected to p2
require.Never(t, func() bool {
return h1.Network().Connectedness(h2.ID()) != network.Connected
}, 5*time.Second, 1*time.Second)
// Now force h2 to disconnect (we have an asymmetric peering).
conns := h2.Network().ConnsToPeer(h1.ID())
require.NotEmpty(t, conns)
h2.ConnManager().TrimOpenConns(ctx)
// All conns to peer should eventually close.
t.Logf("waiting for all connections to close")
for _, c := range conns {
require.Eventually(t, func() bool {
s, err := c.NewStream(context.Background())
if s != nil {
_ = s.Reset()
}
return err != nil
}, 5*time.Second, 10*time.Millisecond)
}
// Should eventually re-connect.
require.Eventually(t, func() bool {
return h1.Network().Connectedness(h2.ID()) == network.Connected
}, 30*time.Second, 1*time.Second)
// Unprotect 2 from 1.
ps1.RemovePeer(h2.ID())
require.NotContains(t, ps1.ListPeers(), peer.AddrInfo{ID: h2.ID(), Addrs: h2.Addrs()})
// Trim connections.
h1.ConnManager().TrimOpenConns(ctx)
// Should disconnect
t.Logf("waiting for h1 to disconnect from h2")
require.Eventually(t, func() bool {
return h1.Network().Connectedness(h2.ID()) != network.Connected
}, 5*time.Second, 10*time.Millisecond)
// Should never reconnect.
t.Logf("ensuring h1 is not connected to h2 again")
require.Never(t, func() bool {
return h1.Network().Connectedness(h2.ID()) == network.Connected
}, 20*time.Second, 1*time.Second)
// Until added back
ps1.AddPeer(peer.AddrInfo{ID: h2.ID(), Addrs: h2.Addrs()})
require.Contains(t, ps1.ListPeers(), peer.AddrInfo{ID: h2.ID(), Addrs: h2.Addrs()})
ps1.AddPeer(peer.AddrInfo{ID: h3.ID(), Addrs: h3.Addrs()})
require.Contains(t, ps1.ListPeers(), peer.AddrInfo{ID: h3.ID(), Addrs: h3.Addrs()})
t.Logf("wait for h1 to connect to h2 and h3 again")
require.Eventually(t, func() bool {
return h1.Network().Connectedness(h2.ID()) == network.Connected
}, 30*time.Second, 1*time.Second)
require.Eventually(t, func() bool {
return h1.Network().Connectedness(h3.ID()) == network.Connected
}, 30*time.Second, 1*time.Second)
// Should be able to repeatedly stop.
require.NoError(t, ps1.Stop())
require.NoError(t, ps1.Stop())
// Adding and removing should work after stopping.
ps1.AddPeer(peer.AddrInfo{ID: h4.ID(), Addrs: h4.Addrs()})
require.Contains(t, ps1.ListPeers(), peer.AddrInfo{ID: h4.ID(), Addrs: h4.Addrs()})
ps1.RemovePeer(h2.ID())
require.NotContains(t, ps1.ListPeers(), peer.AddrInfo{ID: h2.ID(), Addrs: h2.Addrs()})
}
func TestNextBackoff(t *testing.T) {
minMaxBackoff := (100 - maxBackoffJitter) / 100 * maxBackoff
for x := 0; x < 1000; x++ {
ph := peerHandler{nextDelay: time.Second}
for min, max := time.Second*3/2, time.Second*5/2; min < minMaxBackoff; min, max = min*3/2, max*5/2 {
b := ph.nextBackoff()
if b > max || b < min {
t.Errorf("expected backoff %s to be between %s and %s", b, min, max)
}
}
for i := 0; i < 100; i++ {
b := ph.nextBackoff()
if b < minMaxBackoff || b > maxBackoff {
t.Fatal("failed to stay within max bounds")
}
}
}
}

View File

@ -7,6 +7,7 @@ import (
pluginfxtest "github.com/ipfs/kubo/plugin/plugins/fxtest"
pluginipldgit "github.com/ipfs/kubo/plugin/plugins/git"
pluginlevelds "github.com/ipfs/kubo/plugin/plugins/levelds"
pluginnopfs "github.com/ipfs/kubo/plugin/plugins/nopfs"
pluginpeerlog "github.com/ipfs/kubo/plugin/plugins/peerlog"
)
@ -22,4 +23,5 @@ func init() {
Preload(pluginlevelds.Plugins...)
Preload(pluginpeerlog.Plugins...)
Preload(pluginfxtest.Plugins...)
Preload(pluginnopfs.Plugins...)
}

View File

@ -11,3 +11,4 @@ flatfs github.com/ipfs/kubo/plugin/plugins/flatfs *
levelds github.com/ipfs/kubo/plugin/plugins/levelds *
peerlog github.com/ipfs/kubo/plugin/plugins/peerlog *
fxtest github.com/ipfs/kubo/plugin/plugins/fxtest *
nopfs github.com/ipfs/kubo/plugin/plugins/nopfs *

View File

@ -0,0 +1,85 @@
package nopfs
import (
"os"
"path/filepath"
"github.com/ipfs-shipyard/nopfs"
"github.com/ipfs-shipyard/nopfs/ipfs"
"github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/core"
"github.com/ipfs/kubo/core/node"
"github.com/ipfs/kubo/plugin"
"go.uber.org/fx"
)
// Plugins sets the list of plugins to be loaded.
var Plugins = []plugin.Plugin{
&nopfsPlugin{},
}
// fxtestPlugin is used for testing the fx plugin.
// It merely adds an fx option that logs a debug statement, so we can verify that it works in tests.
type nopfsPlugin struct{}
var _ plugin.PluginFx = (*nopfsPlugin)(nil)
func (p *nopfsPlugin) Name() string {
return "nopfs"
}
func (p *nopfsPlugin) Version() string {
return "0.0.10"
}
func (p *nopfsPlugin) Init(env *plugin.Environment) error {
return nil
}
// MakeBlocker is a factory for the blocker so that it can be provided with Fx.
func MakeBlocker() (*nopfs.Blocker, error) {
ipfsPath, err := config.PathRoot()
if err != nil {
return nil, err
}
defaultFiles, err := nopfs.GetDenylistFiles()
if err != nil {
return nil, err
}
kuboFiles, err := nopfs.GetDenylistFilesInDir(filepath.Join(ipfsPath, "denylists"))
if err != nil {
return nil, err
}
files := append(defaultFiles, kuboFiles...)
return nopfs.NewBlocker(files)
}
// PathResolvers returns wrapped PathResolvers for Kubo.
func PathResolvers(fetchers node.FetchersIn, blocker *nopfs.Blocker) node.PathResolversOut {
res := node.PathResolverConfig(fetchers)
return node.PathResolversOut{
IPLDPathResolver: ipfs.WrapResolver(res.IPLDPathResolver, blocker),
UnixFSPathResolver: ipfs.WrapResolver(res.UnixFSPathResolver, blocker),
OfflineIPLDPathResolver: ipfs.WrapResolver(res.OfflineIPLDPathResolver, blocker),
OfflineUnixFSPathResolver: ipfs.WrapResolver(res.OfflineUnixFSPathResolver, blocker),
}
}
func (p *nopfsPlugin) Options(info core.FXNodeInfo) ([]fx.Option, error) {
if os.Getenv("IPFS_CONTENT_BLOCKING_DISABLE") != "" {
return info.FXOptions, nil
}
opts := append(
info.FXOptions,
fx.Provide(MakeBlocker),
fx.Decorate(ipfs.WrapBlockService),
fx.Decorate(ipfs.WrapNameSystem),
fx.Decorate(PathResolvers),
)
return opts, nil
}

View File

@ -7,14 +7,14 @@ import (
"io"
"net/url"
"os"
"path"
gopath "path"
"strings"
"sync"
iface "github.com/ipfs/boxo/coreiface"
"github.com/ipfs/boxo/coreiface/options"
ipath "github.com/ipfs/boxo/coreiface/path"
"github.com/ipfs/boxo/files"
"github.com/ipfs/boxo/path"
"github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/core"
"github.com/ipfs/kubo/core/coreapi"
@ -46,7 +46,7 @@ type IpfsFetcher struct {
ipfsTmpDir string
ipfsStopFunc func()
fetched []ipath.Path
fetched []path.Path
mutex sync.Mutex
addrInfo peer.AddrInfo
@ -108,7 +108,7 @@ func (f *IpfsFetcher) Fetch(ctx context.Context, filePath string) ([]byte, error
return nil, f.openErr
}
iPath, err := parsePath(path.Join(f.distPath, filePath))
iPath, err := parsePath(gopath.Join(f.distPath, filePath))
if err != nil {
return nil, err
}
@ -156,13 +156,13 @@ func (f *IpfsFetcher) AddrInfo() peer.AddrInfo {
}
// FetchedPaths returns the IPFS paths of all items fetched by this fetcher.
func (f *IpfsFetcher) FetchedPaths() []ipath.Path {
func (f *IpfsFetcher) FetchedPaths() []path.Path {
f.mutex.Lock()
defer f.mutex.Unlock()
return f.fetched
}
func (f *IpfsFetcher) recordFetched(fetchedPath ipath.Path) {
func (f *IpfsFetcher) recordFetched(fetchedPath path.Path) {
// Mutex protects against update by concurrent calls to Fetch
f.mutex.Lock()
defer f.mutex.Unlock()
@ -267,9 +267,8 @@ func (f *IpfsFetcher) startTempNode(ctx context.Context) error {
return nil
}
func parsePath(fetchPath string) (ipath.Path, error) {
ipfsPath := ipath.New(fetchPath)
if ipfsPath.IsValid() == nil {
func parsePath(fetchPath string) (path.Path, error) {
if ipfsPath, err := path.NewPath(fetchPath); err == nil {
return ipfsPath, nil
}
@ -280,11 +279,10 @@ func parsePath(fetchPath string) (ipath.Path, error) {
switch proto := u.Scheme; proto {
case "ipfs", "ipld", "ipns":
ipfsPath = ipath.New(path.Join("/", proto, u.Host, u.Path))
return path.NewPath(gopath.Join("/", proto, u.Host, u.Path))
default:
return nil, fmt.Errorf("%q is not an IPFS path", fetchPath)
}
return ipfsPath, ipfsPath.IsValid()
}
func readIpfsConfig(repoRoot *string, userConfigFile string) (bootstrap []string, peers []peer.AddrInfo) {

View File

@ -6,13 +6,13 @@ import (
"context"
"errors"
"io"
"path"
"strings"
dag "github.com/ipfs/boxo/ipld/merkledag"
"github.com/ipfs/boxo/ipld/merkledag/dagutils"
importer "github.com/ipfs/boxo/ipld/unixfs/importer"
uio "github.com/ipfs/boxo/ipld/unixfs/io"
path "github.com/ipfs/boxo/path"
chunker "github.com/ipfs/boxo/chunker"
ipld "github.com/ipfs/go-ipld-format"
@ -95,11 +95,11 @@ func ImportTar(ctx context.Context, r io.Reader, ds ipld.DAGService) (*dag.Proto
// adds a '-' to the beginning of each path element so we can use 'data' as a
// special link in the structure without having to worry about.
func escapePath(pth string) string {
elems := path.SplitList(strings.Trim(pth, "/"))
elems := strings.Split(strings.Trim(pth, "/"), "/")
for i, e := range elems {
elems[i] = "-" + e
}
return path.Join(elems)
return path.Join(elems...)
}
type tarReader struct {

View File

@ -0,0 +1,303 @@
package cli
import (
"context"
"fmt"
"io"
"log"
"net/http"
"net/url"
"os"
"path/filepath"
"strings"
"testing"
"github.com/ipfs/kubo/test/cli/harness"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/peer"
libp2phttp "github.com/libp2p/go-libp2p/p2p/http"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestContentBlocking(t *testing.T) {
// NOTE: we can't run this with t.Parallel() because we set IPFS_NS_MAP
// and running in parallel could impact other tests
const blockedMsg = "blocked and cannot be provided"
const statusExpl = "specific HTTP error code is expected"
const bodyExpl = "Error message informing about content block is expected"
h := harness.NewT(t)
// Init IPFS_PATH
node := h.NewNode().Init("--empty-repo", "--profile=test")
// Create CIDs we use in test
h.WriteFile("blocked-dir/subdir/indirectly-blocked-file.txt", "indirectly blocked file content")
parentDirCID := node.IPFS("add", "--raw-leaves", "-Q", "-r", filepath.Join(h.Dir, "blocked-dir")).Stdout.Trimmed()
h.WriteFile("directly-blocked-file.txt", "directly blocked file content")
blockedCID := node.IPFS("add", "--raw-leaves", "-Q", filepath.Join(h.Dir, "directly-blocked-file.txt")).Stdout.Trimmed()
h.WriteFile("not-blocked-file.txt", "not blocked file content")
allowedCID := node.IPFS("add", "--raw-leaves", "-Q", filepath.Join(h.Dir, "not-blocked-file.txt")).Stdout.Trimmed()
// Create denylist at $IPFS_PATH/denylists/test.deny
denylistTmp := h.WriteToTemp("name: test list\n---\n" +
"//QmX9dhRcQcKUw3Ws8485T5a9dtjrSCQaUAHnG4iK9i4ceM\n" + // Double hash (sha256) CID block: base58btc(sha256-multihash(QmVTF1yEejXd9iMgoRTFDxBv7HAz9kuZcQNBzHrceuK9HR))
"//gW813G35CnLsy7gRYYHuf63hrz71U1xoLFDVeV7actx6oX\n" + // Double hash (blake3) Path block under blake3 root CID: base58btc(blake3-multihash(gW7Nhu4HrfDtphEivm3Z9NNE7gpdh5Tga8g6JNZc1S8E47/path))
"//8526ba05eec55e28f8db5974cc891d0d92c8af69d386fc6464f1e9f372caf549\n" + // Legacy CID double-hash block: sha256(bafkqahtcnrxwg23fmqqgi33vmjwgk2dbonuca3dfm5qwg6jamnuwicq/)
"//e5b7d2ce2594e2e09901596d8e1f29fa249b74c8c9e32ea01eda5111e4d33f07\n" + // Legacy Path double-hash block: sha256(bafyaagyscufaqalqaacauaqiaejao43vmjygc5didacauaqiae/subpath)
"/ipfs/" + blockedCID + "\n" + // block specific CID
"/ipfs/" + parentDirCID + "/subdir*\n" + // block only specific subpath
"/ipns/blocked-cid.example.com\n" +
"/ipns/blocked-dnslink.example.com\n")
if err := os.MkdirAll(filepath.Join(node.Dir, "denylists"), 0o777); err != nil {
log.Panicf("failed to create denylists dir: %s", err.Error())
}
if err := os.Rename(denylistTmp, filepath.Join(node.Dir, "denylists", "test.deny")); err != nil {
log.Panicf("failed to create test denylist: %s", err.Error())
}
// Add two entries to namesys resolution cache
// /ipns/blocked-cid.example.com point at a blocked CID (to confirm blocking impacts /ipns resolution)
// /ipns/blocked-dnslink.example.com with safe CID (to test blocking of /ipns/ paths)
os.Setenv("IPFS_NS_MAP", "blocked-cid.example.com:/ipfs/"+blockedCID+",blocked-dnslink.example.com/ipns/QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn")
defer os.Unsetenv("IPFS_NS_MAP")
// Enable GatewayOverLibp2p as we want to test denylist there too
node.IPFS("config", "--json", "Experimental.GatewayOverLibp2p", "true")
// Start daemon, it should pick up denylist from $IPFS_PATH/denylists/test.deny
node.StartDaemon() // we need online mode for GatewayOverLibp2p tests
client := node.GatewayClient()
// First, confirm gateway works
t.Run("Gateway Allows CID that is not blocked", func(t *testing.T) {
t.Parallel()
resp := client.Get("/ipfs/" + allowedCID)
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Equal(t, "not blocked file content", resp.Body)
})
// Then, does the most basic blocking case work?
t.Run("Gateway Denies directly blocked CID", func(t *testing.T) {
t.Parallel()
resp := client.Get("/ipfs/" + blockedCID)
assert.Equal(t, http.StatusGone, resp.StatusCode, statusExpl)
assert.NotEqual(t, "directly blocked file content", resp.Body)
assert.Contains(t, resp.Body, blockedMsg, bodyExpl)
})
// Confirm parent of blocked subpath is not blocked
t.Run("Gateway Allows parent Path that is not blocked", func(t *testing.T) {
t.Parallel()
resp := client.Get("/ipfs/" + parentDirCID)
assert.Equal(t, http.StatusOK, resp.StatusCode)
})
// Ok, now the full list of test cases we want to cover in both CLI and Gateway
testCases := []struct {
name string
path string
}{
{
name: "directly blocked CID",
path: "/ipfs/" + blockedCID,
},
{
name: "indirectly blocked file (on a blocked subpath)",
path: "/ipfs/" + parentDirCID + "/subdir/indirectly-blocked-file.txt",
},
{
name: "/ipns path that resolves to a blocked CID",
path: "/ipns/blocked-cid.example.com",
},
{
name: "/ipns Path that is blocked by DNSLink name",
path: "/ipns/blocked-dnslink.example.com",
},
{
name: "double-hash CID block (sha256-multihash)",
path: "/ipfs/QmVTF1yEejXd9iMgoRTFDxBv7HAz9kuZcQNBzHrceuK9HR",
},
{
name: "double-hash Path block (blake3-multihash)",
path: "/ipfs/bafyb4ieqht3b2rssdmc7sjv2cy2gfdilxkfh7623nvndziyqnawkmo266a/path",
},
{
name: "legacy CID double-hash block (sha256)",
path: "/ipfs/bafkqahtcnrxwg23fmqqgi33vmjwgk2dbonuca3dfm5qwg6jamnuwicq",
},
{
name: "legacy Path double-hash block (sha256)",
path: "/ipfs/bafyaagyscufaqalqaacauaqiaejao43vmjygc5didacauaqiae/subpath",
},
}
// Which specific cliCmds we test against testCases
cliCmds := [][]string{
{"block", "get"},
{"block", "stat"},
{"dag", "get"},
{"dag", "export"},
{"dag", "stat"},
{"cat"},
{"ls"},
{"get"},
{"refs"},
}
expectedMsg := blockedMsg
for _, testCase := range testCases {
// Confirm that denylist is active for every command in 'cliCmds' x 'testCases'
for _, cmd := range cliCmds {
cmd := cmd
cliTestName := fmt.Sprintf("CLI '%s' denies %s", strings.Join(cmd, " "), testCase.name)
t.Run(cliTestName, func(t *testing.T) {
t.Parallel()
args := append(cmd, testCase.path)
errMsg := node.RunIPFS(args...).Stderr.Trimmed()
if !strings.Contains(errMsg, expectedMsg) {
t.Errorf("Expected STDERR error message %q, but got: %q", expectedMsg, errMsg)
}
})
}
// Confirm that denylist is active for every content path in 'testCases'
gwTestName := fmt.Sprintf("Gateway denies %s", testCase.name)
t.Run(gwTestName, func(t *testing.T) {
resp := client.Get(testCase.path)
assert.Equal(t, http.StatusGone, resp.StatusCode, statusExpl)
assert.Contains(t, resp.Body, blockedMsg, bodyExpl)
})
}
// Extra edge cases on subdomain gateway
t.Run("Gateway Denies /ipns Path that is blocked by DNSLink name (subdomain redirect)", func(t *testing.T) {
t.Parallel()
gwURL, _ := url.Parse(node.GatewayURL())
resp := client.Get("/ipns/blocked-dnslink.example.com", func(r *http.Request) {
r.Host = "localhost:" + gwURL.Port()
})
assert.Equal(t, http.StatusGone, resp.StatusCode, statusExpl)
assert.Contains(t, resp.Body, blockedMsg, bodyExpl)
})
t.Run("Gateway Denies /ipns Path that is blocked by DNSLink name (subdomain, no TLS)", func(t *testing.T) {
t.Parallel()
gwURL, _ := url.Parse(node.GatewayURL())
resp := client.Get("/", func(r *http.Request) {
r.Host = "blocked-dnslink.example.com.ipns.localhost:" + gwURL.Port()
})
assert.Equal(t, http.StatusGone, resp.StatusCode, statusExpl)
assert.Contains(t, resp.Body, blockedMsg, bodyExpl)
})
t.Run("Gateway Denies /ipns Path that is blocked by DNSLink name (subdomain, inlined for TLS)", func(t *testing.T) {
t.Parallel()
gwURL, _ := url.Parse(node.GatewayURL())
resp := client.Get("/", func(r *http.Request) {
// Inlined DNSLink to fit in single DNS label for TLS interop:
// https://specs.ipfs.tech/http-gateways/subdomain-gateway/#host-request-header
r.Host = "blocked--dnslink-example-com.ipns.localhost:" + gwURL.Port()
})
assert.Equal(t, http.StatusGone, resp.StatusCode, statusExpl)
assert.Contains(t, resp.Body, blockedMsg, bodyExpl)
})
// We need to confirm denylist is active when gateway is run in NoFetch
// mode (which usually swaps blockservice to a read-only one, and that swap
// may cause denylists to not be applied, as it is a separate code path)
t.Run("GatewayNoFetch", func(t *testing.T) {
// NOTE: we don't run this in parallel, as it requires restart with different config
// Switch gateway to NoFetch mode
node.StopDaemon()
node.IPFS("config", "--json", "Gateway.NoFetch", "true")
node.StartDaemon()
// update client, as the port of test node might've changed after restart
client = node.GatewayClient()
// First, confirm gateway works
t.Run("Allows CID that is not blocked", func(t *testing.T) {
resp := client.Get("/ipfs/" + allowedCID)
assert.Equal(t, http.StatusOK, resp.StatusCode)
assert.Equal(t, "not blocked file content", resp.Body)
})
// Then, does the most basic blocking case work?
t.Run("Denies directly blocked CID", func(t *testing.T) {
resp := client.Get("/ipfs/" + blockedCID)
assert.Equal(t, http.StatusGone, resp.StatusCode, statusExpl)
assert.NotEqual(t, "directly blocked file content", resp.Body)
assert.Contains(t, resp.Body, blockedMsg, bodyExpl)
})
// Restore default
node.StopDaemon()
node.IPFS("config", "--json", "Gateway.NoFetch", "false")
node.StartDaemon()
client = node.GatewayClient()
})
// We need to confirm denylist is active on the
// trustless gateway exposed over libp2p
// when Experimental.GatewayOverLibp2p=true
// (https://github.com/ipfs/kubo/blob/master/docs/experimental-features.md#http-gateway-over-libp2p)
// NOTE: this type fo gateway is hardcoded to be NoFetch: it does not fetch
// data that is not in local store, so we only need to run it once: a
// simple smoke-test for allowed CID and blockedCID.
t.Run("GatewayOverLibp2p", func(t *testing.T) {
t.Parallel()
// Create libp2p client that connects to our node over
// /http1.1 and then talks gateway semantics over the /ipfs/gateway sub-protocol
clientHost, err := libp2p.New(libp2p.NoListenAddrs)
require.NoError(t, err)
err = clientHost.Connect(context.Background(), peer.AddrInfo{
ID: node.PeerID(),
Addrs: node.SwarmAddrs(),
})
require.NoError(t, err)
libp2pClient, err := (&libp2phttp.Host{StreamHost: clientHost}).NamespacedClient("/ipfs/gateway", peer.AddrInfo{ID: node.PeerID()})
require.NoError(t, err)
t.Run("Serves Allowed CID", func(t *testing.T) {
t.Parallel()
resp, err := libp2pClient.Get(fmt.Sprintf("/ipfs/%s?format=raw", allowedCID))
require.NoError(t, err)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
body, err := io.ReadAll(resp.Body)
require.NoError(t, err)
require.Equal(t, string(body), "not blocked file content", bodyExpl)
})
t.Run("Denies Blocked CID", func(t *testing.T) {
t.Parallel()
resp, err := libp2pClient.Get(fmt.Sprintf("/ipfs/%s?format=raw", blockedCID))
require.NoError(t, err)
defer resp.Body.Close()
assert.Equal(t, http.StatusGone, resp.StatusCode, statusExpl)
body, err := io.ReadAll(resp.Body)
require.NoError(t, err)
assert.NotEqual(t, string(body), "directly blocked file content")
assert.Contains(t, string(body), blockedMsg, bodyExpl)
})
})
}

View File

@ -43,11 +43,11 @@ func (r *fakeHTTPContentRouter) ProvideBitswap(ctx context.Context, req *server.
return 0, nil
}
func (r *fakeHTTPContentRouter) FindPeers(ctx context.Context, pid peer.ID, limit int) (iter.ResultIter[types.Record], error) {
func (r *fakeHTTPContentRouter) FindPeers(ctx context.Context, pid peer.ID, limit int) (iter.ResultIter[*types.PeerRecord], error) {
r.m.Lock()
defer r.m.Unlock()
r.findPeersCalls++
return iter.FromSlice([]iter.Result[types.Record]{}), nil
return iter.FromSlice([]iter.Result[*types.PeerRecord]{}), nil
}
func (r *fakeHTTPContentRouter) GetIPNS(ctx context.Context, name ipns.Name) (*ipns.Record, error) {

View File

@ -80,7 +80,7 @@ func TestRoutingV1Server(t *testing.T) {
assert.IsType(t, records[0].GetSchema(), records[0].GetSchema())
assert.IsType(t, records[0], &types.PeerRecord{})
peer := records[0].(*types.PeerRecord)
peer := records[0]
assert.Equal(t, nodes[2].PeerID().String(), peer.ID.String())
assert.NotEmpty(t, peer.Addrs)
})

View File

@ -41,7 +41,7 @@ func TestGatewayHAMTDirectory(t *testing.T) {
assert.Equal(t, http.StatusOK, resp.StatusCode)
}
func TestGatewayMultiRange(t *testing.T) {
func TestGatewayHAMTRanges(t *testing.T) {
t.Parallel()
const (
@ -65,11 +65,36 @@ func TestGatewayMultiRange(t *testing.T) {
err = node.IPFSDagImport(r, fixtureCid)
assert.NoError(t, err)
// Succeeds fetching a range of blocks we have
resp := client.Get(fmt.Sprintf("/ipfs/%s", fileCid), func(r *http.Request) {
r.Header.Set("Range", "bytes=1276-1279, 29839070-29839080")
t.Run("Succeeds Fetching Range", func(t *testing.T) {
t.Parallel()
resp := client.Get(fmt.Sprintf("/ipfs/%s", fileCid), func(r *http.Request) {
r.Header.Set("Range", "bytes=1276-1279")
})
assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
assert.Equal(t, "bytes 1276-1279/109266405", resp.Headers.Get("Content-Range"))
assert.Equal(t, "iana", resp.Body)
})
t.Run("Succeeds Fetching Second Range", func(t *testing.T) {
t.Parallel()
resp := client.Get(fmt.Sprintf("/ipfs/%s", fileCid), func(r *http.Request) {
r.Header.Set("Range", "bytes=29839070-29839080")
})
assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
assert.Equal(t, "bytes 29839070-29839080/109266405", resp.Headers.Get("Content-Range"))
assert.Equal(t, "EXAMPLE.COM", resp.Body)
})
t.Run("Succeeds Fetching First Range of Multi-range Request", func(t *testing.T) {
t.Parallel()
resp := client.Get(fmt.Sprintf("/ipfs/%s", fileCid), func(r *http.Request) {
r.Header.Set("Range", "bytes=1276-1279, 29839070-29839080")
})
assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
assert.Equal(t, "bytes 1276-1279/109266405", resp.Headers.Get("Content-Range"))
assert.Equal(t, "iana", resp.Body)
})
assert.Equal(t, http.StatusPartialContent, resp.StatusCode)
assert.Contains(t, resp.Body, "Content-Range: bytes 1276-1279/109266405\r\nContent-Type: text/plain; charset=utf-8\r\n\r\niana\r\n")
assert.Contains(t, resp.Body, "Content-Range: bytes 29839070-29839080/109266405\r\nContent-Type: text/plain; charset=utf-8\r\n\r\nEXAMPLE.COM\r\n")
}

View File

@ -8,6 +8,8 @@ import (
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"testing"
"github.com/ipfs/kubo/config"
@ -169,7 +171,7 @@ func TestGateway(t *testing.T) {
t.Run("IPNS", func(t *testing.T) {
t.Parallel()
node.IPFS("name", "publish", "--allow-offline", cid)
node.IPFS("name", "publish", "--allow-offline", "--ttl", "42h", cid)
t.Run("GET invalid IPNS root returns 500 (Internal Server Error)", func(t *testing.T) {
t.Parallel()
@ -184,6 +186,17 @@ func TestGateway(t *testing.T) {
assert.Equal(t, "Hello Worlds!", resp.Body)
})
t.Run("GET IPNS path has correct Cache-Control", func(t *testing.T) {
t.Parallel()
resp := client.Get("/ipns/{{.PeerID}}")
assert.Equal(t, 200, resp.StatusCode)
cacheControl := resp.Headers.Get("Cache-Control")
assert.True(t, strings.HasPrefix(cacheControl, "public, max-age="))
maxAge, err := strconv.Atoi(strings.TrimPrefix(cacheControl, "public, max-age="))
assert.NoError(t, err)
assert.True(t, maxAge-151200 < 60) // MaxAge within 42h and 42h-1m
})
t.Run("GET /ipfs/ipns/{peerid} returns redirect to the valid path", func(t *testing.T) {
t.Parallel()
resp := client.Get("/ipfs/ipns/{{.PeerID}}?query=to-remember")
@ -408,9 +421,9 @@ func TestGateway(t *testing.T) {
t.Parallel()
gatewayAddr := URLStrToMultiaddr(node.GatewayURL())
res := node.RunIPFS("--api", gatewayAddr.String(), "refs", "local")
assert.Equal(t,
`Error: invalid path "local": invalid cid: selected encoding not supported`,
assert.Contains(t,
res.Stderr.Trimmed(),
`Error: invalid path "local":`,
)
})

View File

@ -7,7 +7,7 @@ replace github.com/ipfs/kubo => ../../
require (
github.com/Kubuxu/gocovmerge v0.0.0-20161216165753-7ecaa51963cd
github.com/golangci/golangci-lint v1.54.1
github.com/ipfs/boxo v0.13.1
github.com/ipfs/boxo v0.14.0
github.com/ipfs/go-cid v0.4.1
github.com/ipfs/go-cidutil v0.1.0
github.com/ipfs/go-datastore v0.6.0
@ -107,7 +107,7 @@ require (
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/gordonklaus/ineffassign v0.0.0-20230610083614-0e73809eb601 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/gostaticanalysis/analysisutil v0.7.1 // indirect
@ -120,20 +120,20 @@ require (
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hexops/gotextdiff v1.0.3 // indirect
github.com/huin/goupnp v1.2.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/ipfs/bbloom v0.0.4 // indirect
github.com/ipfs/go-bitfield v1.1.0 // indirect
github.com/ipfs/go-block-format v0.1.2 // indirect
github.com/ipfs/go-block-format v0.2.0 // indirect
github.com/ipfs/go-ipfs-blockstore v1.3.0 // indirect
github.com/ipfs/go-ipfs-ds-help v1.1.0 // indirect
github.com/ipfs/go-ipfs-files v0.2.0 // indirect
github.com/ipfs/go-ipfs-pq v0.0.3 // indirect
github.com/ipfs/go-ipfs-util v0.0.3 // indirect
github.com/ipfs/go-ipld-format v0.5.0 // indirect
github.com/ipfs/go-ipld-format v0.6.0 // indirect
github.com/ipfs/go-ipld-legacy v0.2.1 // indirect
github.com/ipfs/go-log/v2 v2.5.1 // indirect
github.com/ipfs/go-metrics-interface v0.0.1 // indirect
@ -165,6 +165,10 @@ require (
github.com/libp2p/go-cidranger v1.1.0 // indirect
github.com/libp2p/go-flow-metrics v0.1.0 // indirect
github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect
github.com/libp2p/go-libp2p-kad-dht v0.24.4 // indirect
github.com/libp2p/go-libp2p-kbucket v0.6.3 // indirect
github.com/libp2p/go-libp2p-record v0.2.0 // indirect
github.com/libp2p/go-libp2p-routing-helpers v0.7.3 // indirect
github.com/libp2p/go-msgio v0.3.0 // indirect
github.com/libp2p/go-nat v0.2.0 // indirect
github.com/libp2p/go-netroute v0.2.1 // indirect
@ -214,10 +218,10 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/polydawn/refmt v0.89.0 // indirect
github.com/polyfloyd/go-errorlint v1.4.3 // indirect
github.com/prometheus/client_golang v1.16.0 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/client_golang v1.17.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/quasilyte/go-ruleguard v0.4.0 // indirect
github.com/quasilyte/gogrep v0.5.0 // indirect
github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect
@ -264,30 +268,34 @@ require (
github.com/ultraware/whitespace v0.0.5 // indirect
github.com/urfave/cli v1.22.10 // indirect
github.com/uudashr/gocognit v1.0.7 // indirect
github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc // indirect
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
github.com/xen0n/gosmopolitan v1.2.1 // indirect
github.com/yagipy/maintidx v1.0.0 // indirect
github.com/yeya24/promlinter v0.2.0 // indirect
github.com/ykadowak/zerologlint v0.1.3 // indirect
gitlab.com/bosi/decorder v0.4.0 // indirect
go.opentelemetry.io/otel v1.16.0 // indirect
go.opentelemetry.io/otel/metric v1.16.0 // indirect
go.opentelemetry.io/otel/trace v1.16.0 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/otel v1.19.0 // indirect
go.opentelemetry.io/otel/metric v1.19.0 // indirect
go.opentelemetry.io/otel/trace v1.19.0 // indirect
go.tmz.dev/musttag v0.7.1 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/dig v1.17.0 // indirect
go.uber.org/fx v1.20.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.25.0 // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect
go.uber.org/zap v1.26.0 // indirect
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/net v0.15.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/term v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/term v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/tools v0.13.0 // indirect
gonum.org/v1/gonum v0.13.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect

View File

@ -252,6 +252,7 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
@ -310,6 +311,7 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@ -339,8 +341,8 @@ github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f/go.mod h1:czg5+yv1E0Z
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
@ -381,8 +383,8 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
@ -396,12 +398,12 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
github.com/ipfs/boxo v0.13.1 h1:nQ5oQzcMZR3oL41REJDcTbrvDvuZh3J9ckc9+ILeRQI=
github.com/ipfs/boxo v0.13.1/go.mod h1:btrtHy0lmO1ODMECbbEY1pxNtrLilvKSYLoGQt1yYCk=
github.com/ipfs/boxo v0.14.0 h1:gwSGW3xqUbtUOdn71oqBknpBFKpQm352g3I+RkebrX0=
github.com/ipfs/boxo v0.14.0/go.mod h1:pu8HsZvuyYeYJsqtLDCoYSvy8rHj6vI3dlh8P0f83Zs=
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
github.com/ipfs/go-block-format v0.1.2 h1:GAjkfhVx1f4YTODS6Esrj1wt2HhrtwTnhEr+DyPUaJo=
github.com/ipfs/go-block-format v0.1.2/go.mod h1:mACVcrxarQKstUU3Yf/RdwbC4DzPV6++rO2a3d+a/KE=
github.com/ipfs/go-block-format v0.2.0 h1:ZqrkxBA2ICbDRbK8KJs/u0O3dlp6gmAuuXUJNiW1Ycs=
github.com/ipfs/go-block-format v0.2.0/go.mod h1:+jpL11nFx5A/SPpsoBn6Bzkra/zaArfSmsknbPMYgzM=
github.com/ipfs/go-blockservice v0.5.0 h1:B2mwhhhVQl2ntW2EIpaWPwSCxSuqr5fFA93Ms4bYLEY=
github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog=
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
@ -433,8 +435,8 @@ github.com/ipfs/go-ipfs-pq v0.0.3/go.mod h1:btNw5hsHBpRcSSgZtiNm/SLj5gYIZ18AKtv3
github.com/ipfs/go-ipfs-util v0.0.3 h1:2RFdGez6bu2ZlZdI+rWfIdbQb1KudQp3VGwPtdNCmE0=
github.com/ipfs/go-ipfs-util v0.0.3/go.mod h1:LHzG1a0Ig4G+iZ26UUOMjHd+lfM84LZCrn17xAKWBvs=
github.com/ipfs/go-ipld-cbor v0.0.6 h1:pYuWHyvSpIsOOLw4Jy7NbBkCyzLDcl64Bf/LZW7eBQ0=
github.com/ipfs/go-ipld-format v0.5.0 h1:WyEle9K96MSrvr47zZHKKcDxJ/vlpET6PSiQsAFO+Ds=
github.com/ipfs/go-ipld-format v0.5.0/go.mod h1:ImdZqJQaEouMjCvqCe0ORUS+uoBmf7Hf+EO/jh+nk3M=
github.com/ipfs/go-ipld-format v0.6.0 h1:VEJlA2kQ3LqFSIm5Vu6eIlSxD/Ze90xtc4Meten1F5U=
github.com/ipfs/go-ipld-format v0.6.0/go.mod h1:g4QVMTn3marU3qXchwjpKPKgJv+zF+OlaKMyhJ4LHPg=
github.com/ipfs/go-ipld-legacy v0.2.1 h1:mDFtrBpmU7b//LzLSypVrXsD8QxkEWxu5qVxN99/+tk=
github.com/ipfs/go-ipld-legacy v0.2.1/go.mod h1:782MOUghNzMO2DER0FlBR94mllfdCJCkTtDtPM51otM=
github.com/ipfs/go-libipfs v0.7.0 h1:Mi54WJTODaOL2/ZSm5loi3SwI3jI2OuFWUrQIkJ5cpM=
@ -546,7 +548,14 @@ github.com/libp2p/go-libp2p v0.31.0 h1:LFShhP8F6xthWiBBq3euxbKjZsoRajVEyBS9snfHx
github.com/libp2p/go-libp2p v0.31.0/go.mod h1:W/FEK1c/t04PbRH3fA9i5oucu5YcgrG0JVoBWT1B7Eg=
github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s=
github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w=
github.com/libp2p/go-libp2p-kad-dht v0.24.4 h1:ktNiJe7ffsJ1wX3ULpMCwXts99mPqGFSE/Qn1i8pErQ=
github.com/libp2p/go-libp2p-kad-dht v0.24.4/go.mod h1:ybWBJ5Fbvz9sSLkNtXt+2+bK0JB8+tRPvhBbRGHegRU=
github.com/libp2p/go-libp2p-kbucket v0.6.3 h1:p507271wWzpy2f1XxPzCQG9NiN6R6lHL9GiSErbQQo0=
github.com/libp2p/go-libp2p-kbucket v0.6.3/go.mod h1:RCseT7AH6eJWxxk2ol03xtP9pEHetYSPXOaJnOiD8i0=
github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0=
github.com/libp2p/go-libp2p-record v0.2.0/go.mod h1:I+3zMkvvg5m2OcSdoL0KPljyJyvNDFGKX7QdlpYUcwk=
github.com/libp2p/go-libp2p-routing-helpers v0.7.3 h1:u1LGzAMVRK9Nqq5aYDVOiq/HaB93U9WWczBzGyAC5ZY=
github.com/libp2p/go-libp2p-routing-helpers v0.7.3/go.mod h1:cN4mJAD/7zfPKXBcs9ze31JGYAZgzdABEm+q/hkswb8=
github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=
github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM=
@ -707,14 +716,14 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
@ -728,8 +737,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/quasilyte/go-ruleguard v0.4.0 h1:DyM6r+TKL+xbKB4Nm7Afd1IQh9kEUKQs2pboWGKtvQo=
github.com/quasilyte/go-ruleguard v0.4.0/go.mod h1:Eu76Z/R8IXtViWUIHkE3p8gdH3/PKk1eh3YGfaEof10=
github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo=
@ -848,6 +857,7 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
@ -887,9 +897,13 @@ github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMI
github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s=
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc h1:BCPnHtcboadS0DvysUuJXZ4lWVv5Bh5i7+tbIyi+ck4=
github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc/go.mod h1:r45hJU7yEoA81k6MWNhpMj/kms0n14dkzkxYHoB96UM=
github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIfyDmc1Em5GqlNRzcdtlv4HTNmdpt7XH0=
github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa h1:EyA027ZAkuaCLoxVX4r1TZMPy1d31fM6hbfQ4OU4I5o=
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E=
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k=
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc=
github.com/xen0n/gosmopolitan v1.2.1 h1:3pttnTuFumELBRSh+KQs1zcz4fN6Zy7aB0xlnQSn1Iw=
github.com/xen0n/gosmopolitan v1.2.1/go.mod h1:JsHq/Brs1o050OOdmzHeOr0N7OtlnKRAGAsElF8xBQA=
github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM=
@ -915,13 +929,15 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s=
go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4=
go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo=
go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs=
go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE=
go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE=
go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs=
go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0=
go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg=
go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=
go.tmz.dev/musttag v0.7.1 h1:9lFmeSFnFfPuMq4IksHGomItE6NgKMNW2Nt2FPOhCfU=
go.tmz.dev/musttag v0.7.1/go.mod h1:oJLkpR56EsIryktZJk/B0IroSMi37YWver47fibGh5U=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
@ -941,8 +957,8 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@ -960,8 +976,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -972,8 +988,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ=
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833 h1:jWGQJV4niP+CCmFW9ekjA9Zx8vYORzOUH2/Nl5WPuLQ=
@ -1045,6 +1061,7 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
@ -1057,8 +1074,8 @@ golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -1155,16 +1172,16 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1176,8 +1193,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -1259,13 +1276,15 @@ golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E=
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
gonum.org/v1/gonum v0.13.0 h1:a0T3bh+7fhRyqeNbiC3qVHYmkiQgit3wnNan/2c0HMM=
gonum.org/v1/gonum v0.13.0/go.mod h1:/WPYRckkfWrhWefxyYTfrTtQR0KH4iyHNuzxqXAKyAU=
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=

View File

@ -11,10 +11,10 @@ import (
"testing"
"time"
"github.com/ipfs/boxo/bootstrap"
"github.com/ipfs/boxo/files"
logging "github.com/ipfs/go-log"
"github.com/ipfs/kubo/core"
"github.com/ipfs/kubo/core/bootstrap"
"github.com/ipfs/kubo/core/coreapi"
mock "github.com/ipfs/kubo/core/mock"
"github.com/ipfs/kubo/thirdparty/unit"

View File

@ -8,9 +8,9 @@ import (
"math"
"testing"
"github.com/ipfs/boxo/bootstrap"
"github.com/ipfs/boxo/files"
"github.com/ipfs/kubo/core"
"github.com/ipfs/kubo/core/bootstrap"
"github.com/ipfs/kubo/core/coreapi"
mock "github.com/ipfs/kubo/core/mock"
"github.com/ipfs/kubo/thirdparty/unit"

View File

@ -10,9 +10,9 @@ import (
"go.uber.org/fx"
"github.com/ipfs/boxo/bootstrap"
"github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/core"
"github.com/ipfs/kubo/core/bootstrap"
"github.com/ipfs/kubo/core/coreapi"
libp2p2 "github.com/ipfs/kubo/core/node/libp2p"
"github.com/ipfs/kubo/repo"

Some files were not shown because too many files have changed in this diff Show More