From 76b1546211ad618cf0d2740380d41dab84750cc0 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 21 Aug 2019 19:17:01 -0700 Subject: [PATCH 1/3] mount: switch over to the CoreAPI 1. Fix resolution of sharded directories. 2. Slowly kill off users of the IpfsNode object. --- fuse/ipns/ipns_test.go | 8 +++- fuse/ipns/ipns_unix.go | 100 +++++++++++++++------------------------- fuse/ipns/mount_unix.go | 8 +++- 3 files changed, 50 insertions(+), 66 deletions(-) diff --git a/fuse/ipns/ipns_test.go b/fuse/ipns/ipns_test.go index a9406670e11..8b749f74d46 100644 --- a/fuse/ipns/ipns_test.go +++ b/fuse/ipns/ipns_test.go @@ -16,6 +16,7 @@ import ( "bazil.org/fuse" core "github.com/ipfs/go-ipfs/core" + coreapi "github.com/ipfs/go-ipfs/core/coreapi" fstest "bazil.org/fuse/fs/fstestutil" racedet "github.com/ipfs/go-detect-race" @@ -115,7 +116,12 @@ func setupIpnsTest(t *testing.T, node *core.IpfsNode) (*core.IpfsNode, *mountWra } } - fs, err := NewFileSystem(node, node.PrivateKey, "", "") + coreApi, err := coreapi.NewCoreAPI(node) + if err != nil { + t.Fatal(err) + } + + fs, err := NewFileSystem(node.Context(), coreApi, "", "") if err != nil { t.Fatal(err) } diff --git a/fuse/ipns/ipns_unix.go b/fuse/ipns/ipns_unix.go index 6b18b716d5f..64233a3be38 100644 --- a/fuse/ipns/ipns_unix.go +++ b/fuse/ipns/ipns_unix.go @@ -10,22 +10,19 @@ import ( "fmt" "io" "os" - - core "github.com/ipfs/go-ipfs/core" - namesys "github.com/ipfs/go-ipfs/namesys" - resolve "github.com/ipfs/go-ipfs/namesys/resolve" + "strings" dag "github.com/ipfs/go-merkledag" - path "github.com/ipfs/go-path" ft "github.com/ipfs/go-unixfs" + path "github.com/ipfs/interface-go-ipfs-core/path" fuse "bazil.org/fuse" fs "bazil.org/fuse/fs" cid "github.com/ipfs/go-cid" logging "github.com/ipfs/go-log" mfs "github.com/ipfs/go-mfs" - ci "github.com/libp2p/go-libp2p-core/crypto" - peer "github.com/libp2p/go-libp2p-core/peer" + iface "github.com/ipfs/interface-go-ipfs-core" + options "github.com/ipfs/interface-go-ipfs-core/options" ) func init() { @@ -40,17 +37,17 @@ var log = logging.Logger("fuse/ipns") // FileSystem is the readwrite IPNS Fuse Filesystem. type FileSystem struct { - Ipfs *core.IpfsNode + Ipfs iface.CoreAPI RootNode *Root } // NewFileSystem constructs new fs using given core.IpfsNode instance. -func NewFileSystem(ipfs *core.IpfsNode, sk ci.PrivKey, ipfspath, ipnspath string) (*FileSystem, error) { - - kmap := map[string]ci.PrivKey{ - "local": sk, +func NewFileSystem(ctx context.Context, ipfs iface.CoreAPI, ipfspath, ipnspath string) (*FileSystem, error) { + key, err := ipfs.Key().Self(ctx) + if err != nil { + return nil, err } - root, err := CreateRoot(ipfs, kmap, ipfspath, ipnspath) + root, err := CreateRoot(ctx, ipfs, map[string]iface.Key{"local": key}, ipfspath, ipnspath) if err != nil { return nil, err } @@ -73,80 +70,62 @@ func (f *FileSystem) Destroy() { // Root is the root object of the filesystem tree. type Root struct { - Ipfs *core.IpfsNode - Keys map[string]ci.PrivKey + Ipfs iface.CoreAPI + Keys map[string]iface.Key // Used for symlinking into ipfs IpfsRoot string IpnsRoot string LocalDirs map[string]fs.Node - Roots map[string]*keyRoot + Roots map[string]*mfs.Root LocalLinks map[string]*Link } -func ipnsPubFunc(ipfs *core.IpfsNode, k ci.PrivKey) mfs.PubFunc { +func ipnsPubFunc(ipfs iface.CoreAPI, key iface.Key) mfs.PubFunc { return func(ctx context.Context, c cid.Cid) error { - return ipfs.Namesys.Publish(ctx, k, path.FromCid(c)) + _, err := ipfs.Name().Publish(ctx, path.IpfsPath(c), options.Name.Key(key.Name())) + return err } } -func loadRoot(ctx context.Context, rt *keyRoot, ipfs *core.IpfsNode, name string) (fs.Node, error) { - p, err := path.ParsePath("/ipns/" + name) - if err != nil { - log.Errorf("mkpath %s: %s", name, err) - return nil, err - } - - node, err := resolve.Resolve(ctx, ipfs.Namesys, ipfs.Resolver, p) +func loadRoot(ctx context.Context, ipfs iface.CoreAPI, key iface.Key) (*mfs.Root, fs.Node, error) { + node, err := ipfs.ResolveNode(ctx, key.Path()) switch err { case nil: - case namesys.ErrResolveFailed: + case iface.ErrResolveFailed: node = ft.EmptyDirNode() default: - log.Errorf("looking up %s: %s", p, err) - return nil, err + log.Errorf("looking up %s: %s", key.Path(), err) + return nil, nil, err } pbnode, ok := node.(*dag.ProtoNode) if !ok { - return nil, dag.ErrNotProtobuf + return nil, nil, dag.ErrNotProtobuf } - root, err := mfs.NewRoot(ctx, ipfs.DAG, pbnode, ipnsPubFunc(ipfs, rt.k)) + root, err := mfs.NewRoot(ctx, ipfs.Dag(), pbnode, ipnsPubFunc(ipfs, key)) if err != nil { - return nil, err + return nil, nil, err } - rt.root = root - - return &Directory{dir: root.GetDirectory()}, nil -} - -type keyRoot struct { - k ci.PrivKey - alias string - root *mfs.Root + return root, &Directory{dir: root.GetDirectory()}, nil } -func CreateRoot(ipfs *core.IpfsNode, keys map[string]ci.PrivKey, ipfspath, ipnspath string) (*Root, error) { +func CreateRoot(ctx context.Context, ipfs iface.CoreAPI, keys map[string]iface.Key, ipfspath, ipnspath string) (*Root, error) { ldirs := make(map[string]fs.Node) - roots := make(map[string]*keyRoot) + roots := make(map[string]*mfs.Root) links := make(map[string]*Link) for alias, k := range keys { - pid, err := peer.IDFromPrivateKey(k) + root, fsn, err := loadRoot(ctx, ipfs, k) if err != nil { return nil, err } - name := pid.Pretty() - kr := &keyRoot{k: k, alias: alias} - fsn, err := loadRoot(ipfs.Context(), kr, ipfs, name) - if err != nil { - return nil, err - } + name := k.ID().String() - roots[name] = kr + roots[name] = root ldirs[name] = fsn // set up alias symlink @@ -199,25 +178,22 @@ func (s *Root) Lookup(ctx context.Context, name string) (fs.Node, error) { // other links go through ipns resolution and are symlinked into the ipfs mountpoint ipnsName := "/ipns/" + name - resolved, err := s.Ipfs.Namesys.Resolve(s.Ipfs.Context(), ipnsName) + resolved, err := s.Ipfs.Name().Resolve(ctx, ipnsName) if err != nil { log.Warnf("ipns: namesys resolve error: %s", err) return nil, fuse.ENOENT } - segments := resolved.Segments() - if segments[0] == "ipfs" { - p := path.Join(resolved.Segments()[1:]) - return &Link{s.IpfsRoot + "/" + p}, nil + if resolved.Namespace() != "ipfs" { + return nil, errors.New("invalid path from ipns record") } - log.Error("Invalid path.Path: ", resolved) - return nil, errors.New("invalid path from ipns record") + return &Link{s.IpfsRoot + "/" + strings.TrimPrefix("/ipfs/", resolved.String())}, nil } func (r *Root) Close() error { for _, mr := range r.Roots { - err := mr.root.Close() + err := mr.Close() if err != nil { return err } @@ -241,12 +217,8 @@ func (r *Root) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { var listing []fuse.Dirent for alias, k := range r.Keys { - pid, err := peer.IDFromPrivateKey(k) - if err != nil { - continue - } ent := fuse.Dirent{ - Name: pid.Pretty(), + Name: k.ID().Pretty(), Type: fuse.DT_Dir, } link := fuse.Dirent{ diff --git a/fuse/ipns/mount_unix.go b/fuse/ipns/mount_unix.go index 54e62df6018..7c24e53beff 100644 --- a/fuse/ipns/mount_unix.go +++ b/fuse/ipns/mount_unix.go @@ -5,11 +5,17 @@ package ipns import ( core "github.com/ipfs/go-ipfs/core" + coreapi "github.com/ipfs/go-ipfs/core/coreapi" mount "github.com/ipfs/go-ipfs/fuse/mount" ) // Mount mounts ipns at a given location, and returns a mount.Mount instance. func Mount(ipfs *core.IpfsNode, ipnsmp, ipfsmp string) (mount.Mount, error) { + coreApi, err := coreapi.NewCoreAPI(ipfs) + if err != nil { + return nil, err + } + cfg, err := ipfs.Repo.Config() if err != nil { return nil, err @@ -17,7 +23,7 @@ func Mount(ipfs *core.IpfsNode, ipnsmp, ipfsmp string) (mount.Mount, error) { allow_other := cfg.Mounts.FuseAllowOther - fsys, err := NewFileSystem(ipfs, ipfs.PrivateKey, ipfsmp, ipnsmp) + fsys, err := NewFileSystem(ipfs.Context(), coreApi, ipfsmp, ipnsmp) if err != nil { return nil, err } From 8643d949f375e3564f9698a791c3794a815a40a7 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 21 Aug 2019 19:24:23 -0700 Subject: [PATCH 2/3] cmds/tar: use the coreapi --- core/commands/tar.go | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/core/commands/tar.go b/core/commands/tar.go index 0c12fdfff5c..a85b909eba4 100644 --- a/core/commands/tar.go +++ b/core/commands/tar.go @@ -5,12 +5,11 @@ import ( "io" "github.com/ipfs/go-ipfs/core/commands/cmdenv" - "github.com/ipfs/go-ipfs/namesys/resolve" tar "github.com/ipfs/go-ipfs/tar" "github.com/ipfs/go-ipfs-cmds" dag "github.com/ipfs/go-merkledag" - "github.com/ipfs/go-path" + path "github.com/ipfs/interface-go-ipfs-core/path" ) var TarCmd = &cmds.Command{ @@ -37,7 +36,7 @@ represent it. cmds.FileArg("file", true, false, "Tar file to add.").EnableStdin(), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { - nd, err := cmdenv.GetNode(env) + api, err := cmdenv.GetApi(env, req) if err != nil { return err } @@ -53,7 +52,7 @@ represent it. return err } - node, err := tar.ImportTar(req.Context, file, nd.DAG) + node, err := tar.ImportTar(req.Context, file, api.Dag()) if err != nil { return err } @@ -86,17 +85,12 @@ var tarCatCmd = &cmds.Command{ cmds.StringArg("path", true, false, "ipfs path of archive to export.").EnableStdin(), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { - nd, err := cmdenv.GetNode(env) + api, err := cmdenv.GetApi(env, req) if err != nil { return err } - p, err := path.ParsePath(req.Arguments[0]) - if err != nil { - return err - } - - root, err := resolve.Resolve(req.Context, nd.Namesys, nd.Resolver, p) + root, err := api.ResolveNode(req.Context, path.New(req.Arguments[0])) if err != nil { return err } @@ -106,7 +100,7 @@ var tarCatCmd = &cmds.Command{ return dag.ErrNotProtobuf } - r, err := tar.ExportTar(req.Context, rootpb, nd.DAG) + r, err := tar.ExportTar(req.Context, rootpb, api.Dag()) if err != nil { return err } From 97bc89d56029f2275f42c9d8564151388c51bec9 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Wed, 21 Aug 2019 19:25:07 -0700 Subject: [PATCH 3/3] resolve: kill off buggy resolve function This resolve function assumed that all paths were of the same type (ipfs, ipld, etc.). The CoreAPI does a much better job. --- namesys/resolve/pathresolver_test.go | 32 ---------------------------- namesys/resolve/resolve.go | 15 ------------- 2 files changed, 47 deletions(-) delete mode 100644 namesys/resolve/pathresolver_test.go diff --git a/namesys/resolve/pathresolver_test.go b/namesys/resolve/pathresolver_test.go deleted file mode 100644 index 3d9c04fa2f1..00000000000 --- a/namesys/resolve/pathresolver_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package resolve_test - -import ( - "testing" - - coremock "github.com/ipfs/go-ipfs/core/mock" - "github.com/ipfs/go-ipfs/namesys/resolve" - - path "github.com/ipfs/go-path" -) - -func TestResolveNoComponents(t *testing.T) { - n, err := coremock.NewMockNode() - if n == nil || err != nil { - t.Fatal("Should have constructed a mock node", err) - } - - _, err = resolve.Resolve(n.Context(), n.Namesys, n.Resolver, path.Path("/ipns/")) - if err.Error() != "invalid path \"/ipns/\": ipns path missing IPNS ID" { - t.Error("Should error with no components (/ipns/).", err) - } - - _, err = resolve.Resolve(n.Context(), n.Namesys, n.Resolver, path.Path("/ipfs/")) - if err.Error() != "invalid path \"/ipfs/\": not enough path components" { - t.Error("Should error with no components (/ipfs/).", err) - } - - _, err = resolve.Resolve(n.Context(), n.Namesys, n.Resolver, path.Path("/../..")) - if err.Error() != "invalid path \"/../..\": unknown namespace \"..\"" { - t.Error("Should error with invalid path.", err) - } -} diff --git a/namesys/resolve/resolve.go b/namesys/resolve/resolve.go index 5b5dc515efe..f838a6611f7 100644 --- a/namesys/resolve/resolve.go +++ b/namesys/resolve/resolve.go @@ -6,9 +6,7 @@ import ( "fmt" "strings" - "github.com/ipfs/go-ipld-format" "github.com/ipfs/go-path" - "github.com/ipfs/go-path/resolver" "github.com/ipfs/go-ipfs/namesys" ) @@ -52,16 +50,3 @@ func ResolveIPNS(ctx context.Context, nsys namesys.NameSystem, p path.Path) (pat } return p, nil } - -// Resolve resolves the given path by parsing out protocol-specific -// entries (e.g. /ipns/) and then going through the /ipfs/ -// entries and returning the final node. -func Resolve(ctx context.Context, nsys namesys.NameSystem, r *resolver.Resolver, p path.Path) (format.Node, error) { - p, err := ResolveIPNS(ctx, nsys, p) - if err != nil { - return nil, err - } - - // ok, we have an IPFS path now (or what we'll treat as one) - return r.ResolvePath(ctx, p) -}