mirror of
https://github.com/ipfs/kubo.git
synced 2026-03-06 16:58:11 +08:00
commit
50160f728e
39
.github/workflows/build.yml
vendored
39
.github/workflows/build.yml
vendored
@ -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"') }}
|
||||
|
||||
@ -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)
|
||||
|
||||
11
README.md
11
README.md
@ -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).
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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())
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -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()
|
||||
}
|
||||
@ -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"
|
||||
|
||||
@ -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{
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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...),
|
||||
})
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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())
|
||||
|
||||
@ -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
|
||||
}),
|
||||
},
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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{
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
}),
|
||||
},
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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),
|
||||
})
|
||||
},
|
||||
|
||||
62
core/core.go
62
core/core.go
@ -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"`
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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" {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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")
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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),
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
73
docs/changelogs/v0.24.md
Normal 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
73
docs/content-blocking.md
Normal 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)
|
||||
```
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
)
|
||||
|
||||
@ -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=
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 |
|
||||
|
||||
@ -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()))
|
||||
}
|
||||
|
||||
@ -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")
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
40
go.mod
@ -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
80
go.sum
@ -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=
|
||||
|
||||
@ -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"]
|
||||
]
|
||||
}
|
||||
@ -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) {}
|
||||
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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...)
|
||||
}
|
||||
|
||||
@ -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 *
|
||||
85
plugin/plugins/nopfs/nopfs.go
Normal file
85
plugin/plugins/nopfs/nopfs.go
Normal 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
|
||||
}
|
||||
@ -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) {
|
||||
|
||||
@ -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 {
|
||||
|
||||
303
test/cli/content_blocking_test.go
Normal file
303
test/cli/content_blocking_test.go
Normal 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)
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -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) {
|
||||
|
||||
@ -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)
|
||||
})
|
||||
|
||||
@ -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")
|
||||
}
|
||||
|
||||
@ -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":`,
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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=
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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
Loading…
Reference in New Issue
Block a user