From 95ea5772cab425a30eac278fd86a2e0756809707 Mon Sep 17 00:00:00 2001 From: Adin Schmahmann Date: Wed, 26 Aug 2020 13:31:38 -0400 Subject: [PATCH 1/4] chore: bump go version --- .travis.yml | 3 ++- go.mod | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5163d69..23775ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,8 @@ os: language: go go: - - 1.11.x + - 1.14.x + - 1.15.x env: global: diff --git a/go.mod b/go.mod index a048a15..b070559 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,7 @@ module github.com/ipfs/go-path +go 1.14 + require ( github.com/ipfs/go-cid v0.0.2 github.com/ipfs/go-ipld-format v0.0.2 From 9ba33de2c4e628f0942e4846366978910d627d77 Mon Sep 17 00:00:00 2001 From: Adin Schmahmann Date: Wed, 26 Aug 2020 13:17:48 -0400 Subject: [PATCH 2/4] ResolveToLastNode no longer fetches nodes it does not need --- resolver/resolver.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resolver/resolver.go b/resolver/resolver.go index 67bb9f6..9f15384 100644 --- a/resolver/resolver.go +++ b/resolver/resolver.go @@ -89,6 +89,10 @@ func (r *Resolver) ResolveToLastNode(ctx context.Context, fpath path.Path) (cid. return cid.Cid{}, nil, err } + if len(rest) == 0 { + return lnk.Cid, nil, nil + } + next, err := lnk.GetNode(ctx, r.DAG) if err != nil { return cid.Cid{}, nil, err From 692649d53149f2ccd5db0e5de350f305b65805b9 Mon Sep 17 00:00:00 2001 From: Adin Schmahmann Date: Wed, 26 Aug 2020 13:59:39 -0400 Subject: [PATCH 3/4] test: add test that ResolveToLastNode does not perform unncessary fetches --- resolver/resolver_test.go | 40 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/resolver/resolver_test.go b/resolver/resolver_test.go index 480ccdf..d3c6913 100644 --- a/resolver/resolver_test.go +++ b/resolver/resolver_test.go @@ -105,3 +105,43 @@ func TestRecurivePathResolution(t *testing.T) { p.String(), rCid.String(), cKey.String())) } } + +func TestResolveToLastNode_NoUnnecessaryFetching(t *testing.T) { + ctx := context.Background() + dagService := dagmock.Mock() + + a := randNode() + b := randNode() + + err := a.AddNodeLink("child", b) + if err != nil { + t.Fatal(err) + } + + err = dagService.Add(ctx, a) + if err != nil { + t.Fatal(err) + } + + aKey := a.Cid() + + segments := []string{aKey.String(), "child"} + p, err := path.FromSegments("/ipfs/", segments...) + if err != nil { + t.Fatal(err) + } + + resolver := resolver.NewBasicResolver(dagService) + resolvedCID, remainingPath, err := resolver.ResolveToLastNode(ctx, p) + if err != nil { + t.Fatal(err) + } + + if len(remainingPath) > 0 { + t.Fatal("cannot have remaining path") + } + + if !resolvedCID.Equals(b.Cid()) { + t.Fatal("resolved to the wrong CID") + } +} From 5e8ad22f98b2095a11e1d735856ba25fad40c294 Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Wed, 2 Dec 2020 11:55:42 +1100 Subject: [PATCH 4/4] fix: improved error message on broken CIDv0 move lidel's fix from https://github.com/ipfs/go-cid/pull/116 --- path.go | 16 ++++++++++++---- path_test.go | 11 +++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/path.go b/path.go index 18a85a9..df05000 100644 --- a/path.go +++ b/path.go @@ -96,7 +96,7 @@ func ParsePath(txt string) (Path, error) { // if the path doesnt begin with a '/' // we expect this to start with a hash, and be an 'ipfs' path if parts[0] != "" { - if _, err := cid.Decode(parts[0]); err != nil { + if _, err := decodeCid(parts[0]); err != nil { return "", &pathError{error: err, path: txt} } // The case when the path starts with hash without a protocol prefix @@ -114,7 +114,7 @@ func ParsePath(txt string) (Path, error) { return "", &pathError{error: fmt.Errorf("not enough path components"), path: txt} } // Validate Cid. - _, err := cid.Decode(parts[2]) + _, err := decodeCid(parts[2]) if err != nil { return "", &pathError{error: fmt.Errorf("invalid CID: %s", err), path: txt} } @@ -135,7 +135,7 @@ func ParseCidToPath(txt string) (Path, error) { return "", &pathError{error: fmt.Errorf("empty"), path: txt} } - c, err := cid.Decode(txt) + c, err := decodeCid(txt) if err != nil { return "", &pathError{error: err, path: txt} } @@ -172,7 +172,7 @@ func SplitAbsPath(fpath Path) (cid.Cid, []string, error) { return cid.Cid{}, nil, &pathError{error: fmt.Errorf("empty"), path: string(fpath)} } - c, err := cid.Decode(parts[0]) + c, err := decodeCid(parts[0]) // first element in the path is a cid if err != nil { return cid.Cid{}, nil, &pathError{error: fmt.Errorf("invalid CID: %s", err), path: string(fpath)} @@ -180,3 +180,11 @@ func SplitAbsPath(fpath Path) (cid.Cid, []string, error) { return c, parts[1:], nil } + +func decodeCid(cstr string) (cid.Cid, error) { + c, err := cid.Decode(cstr) + if err != nil && len(cstr) == 46 && cstr[:2] == "qm" { // https://github.com/ipfs/go-ipfs/issues/7792 + return cid.Cid{}, fmt.Errorf("%v (possible lowercased CIDv0; consider converting to a case-agnostic CIDv1, such as base32)", err) + } + return c, err +} diff --git a/path_test.go b/path_test.go index fdd71fc..4552fc5 100644 --- a/path_test.go +++ b/path_test.go @@ -102,3 +102,14 @@ func TestPopLastSegment(t *testing.T) { } } } + +func TestV0ErrorDueToLowercase(t *testing.T) { + badb58 := "/ipfs/qmbwqxbekc3p8tqskc98xmwnzrzdtrlmimpl8wbutgsmnr" + _, err := ParsePath(badb58) + if err == nil { + t.Fatal("should have failed to decode") + } + if !strings.HasSuffix(err.Error(), "(possible lowercased CIDv0; consider converting to a case-agnostic CIDv1, such as base32)") { + t.Fatal("should have meaningful info about case-insensitive fix") + } +}