Skip to content

Commit 7383a0d

Browse files
committed
ipfs: fix path resolution of alternate node formats
1 parent 7715453 commit 7383a0d

File tree

6 files changed

+185
-40
lines changed

6 files changed

+185
-40
lines changed

go.mod

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,15 @@ require (
4242
github.com/hashicorp/golang-lru v0.5.4 // indirect
4343
github.com/ipfs/bbloom v0.0.4 // indirect
4444
github.com/ipfs/go-bitfield v1.1.0 // indirect
45-
github.com/ipfs/go-block-format v0.1.2 // indirect
45+
github.com/ipfs/go-block-format v0.1.2
46+
github.com/ipfs/go-blockservice v0.5.2 // indirect
4647
github.com/ipfs/go-datastore v0.6.0 // indirect
4748
github.com/ipfs/go-ipfs-util v0.0.3 // indirect
4849
github.com/ipfs/go-ipld-legacy v0.2.1 // indirect
4950
github.com/ipfs/go-log v1.0.5 // indirect
5051
github.com/ipfs/go-log/v2 v2.5.1 // indirect
5152
github.com/ipfs/go-metrics-interface v0.0.1 // indirect
53+
github.com/ipfs/go-unixfsnode v1.7.3
5254
github.com/ipld/go-codec-dagpb v1.6.0 // indirect
5355
github.com/ipld/go-ipld-prime v0.20.0 // indirect
5456
github.com/jbenet/goprocess v0.1.4 // indirect

go.sum

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL
7777
github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY=
7878
github.com/ipfs/go-block-format v0.1.2 h1:GAjkfhVx1f4YTODS6Esrj1wt2HhrtwTnhEr+DyPUaJo=
7979
github.com/ipfs/go-block-format v0.1.2/go.mod h1:mACVcrxarQKstUU3Yf/RdwbC4DzPV6++rO2a3d+a/KE=
80+
github.com/ipfs/go-blockservice v0.5.2 h1:in9Bc+QcXwd1apOVM7Un9t8tixPKdaHQFdLSUM1Xgk8=
81+
github.com/ipfs/go-blockservice v0.5.2/go.mod h1:VpMblFEqG67A/H2sHKAemeH9vlURVavlysbdUI632yk=
8082
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
8183
github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
8284
github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
@@ -85,10 +87,15 @@ github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LK
8587
github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk=
8688
github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8=
8789
github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
90+
github.com/ipfs/go-ipfs-blockstore v1.3.0 h1:m2EXaWgwTzAfsmt5UdJ7Is6l4gJcaM/A12XwJyvYvMM=
8891
github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ=
92+
github.com/ipfs/go-ipfs-chunker v0.0.5 h1:ojCf7HV/m+uS2vhUGWcogIIxiO5ubl5O57Q7NapWLY8=
8993
github.com/ipfs/go-ipfs-cmds v0.9.0 h1:K0VcXg1l1k6aY6sHnoxYcyimyJQbcV1ueXuWgThmK9Q=
9094
github.com/ipfs/go-ipfs-cmds v0.9.0/go.mod h1:SBFHK8WNwC416QWH9Vz1Ql42SSMAOqKpaHUMBu3jpLo=
9195
github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ=
96+
github.com/ipfs/go-ipfs-ds-help v1.1.0 h1:yLE2w9RAsl31LtfMt91tRZcrx+e61O5mDxFRR994w4Q=
97+
github.com/ipfs/go-ipfs-exchange-interface v0.2.0 h1:8lMSJmKogZYNo2jjhUs0izT+dck05pqUw4mWNW9Pw6Y=
98+
github.com/ipfs/go-ipfs-exchange-offline v0.3.0 h1:c/Dg8GDPzixGd0MC8Jh6mjOwU57uYokgWRFidfvEkuA=
9299
github.com/ipfs/go-ipfs-pq v0.0.3 h1:YpoHVJB+jzK15mr/xsWC574tyDLkezVrDNeaalQBsTE=
93100
github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc=
94101
github.com/ipfs/go-ipfs-util v0.0.3 h1:2RFdGez6bu2ZlZdI+rWfIdbQb1KudQp3VGwPtdNCmE0=
@@ -105,11 +112,17 @@ github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JP
105112
github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g=
106113
github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY=
107114
github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI=
115+
github.com/ipfs/go-merkledag v0.10.0 h1:IUQhj/kzTZfam4e+LnaEpoiZ9vZF6ldimVlby+6OXL4=
108116
github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg=
109117
github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY=
110118
github.com/ipfs/go-peertaskqueue v0.8.1 h1:YhxAs1+wxb5jk7RvS0LHdyiILpNmRIRnZVztekOF0pg=
119+
github.com/ipfs/go-unixfs v0.4.5 h1:wj8JhxvV1G6CD7swACwSKYa+NgtdWC1RUit+gFnymDU=
120+
github.com/ipfs/go-unixfsnode v1.7.3 h1:giAxFq7CxAm2Z8h8yFAD7TOQUpf5XG7a2xrR143ci4Y=
121+
github.com/ipfs/go-unixfsnode v1.7.3/go.mod h1:PVfoyZkX1B34qzT3vJO4nsLUpRCyhnMuHBznRcXirlk=
122+
github.com/ipfs/go-verifcid v0.0.2 h1:XPnUv0XmdH+ZIhLGKg6U2vaPaRDXb9urMyNVCE7uvTs=
111123
github.com/ipfs/kubo v0.21.0 h1:1+XKokeyatfI2Mri5iBn8Eplxf2F5ud0K5zLDg4tSSc=
112124
github.com/ipfs/kubo v0.21.0/go.mod h1:LuK5ANXz/UhHp8jdt4mRwE16AHhbRqY68g/uyc5/VqU=
125+
github.com/ipld/go-car/v2 v2.9.1-0.20230325062757-fff0e4397a3d h1:22g+x1tgWSXK34i25qjs+afr7basaneEkHaglBshd2g=
113126
github.com/ipld/go-codec-dagpb v1.6.0 h1:9nYazfyu9B1p3NAgfVdpRco3Fs2nFC72DqVsMj6rOcc=
114127
github.com/ipld/go-codec-dagpb v1.6.0/go.mod h1:ANzFhfP2uMJxRBr8CE+WQWs5UsNa0pYtmKZ+agnUw9s=
115128
github.com/ipld/go-ipld-prime v0.20.0 h1:Ud3VwE9ClxpO2LkCYP7vWPc0Fo+dYdYzgxUJZ3uRG4g=
@@ -223,6 +236,7 @@ github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss=
223236
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
224237
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
225238
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
239+
github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 h1:1/WtZae0yGtPq+TI6+Tv1WTxkukpXeMlviSxvL7SRgk=
226240
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
227241
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
228242
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -270,6 +284,7 @@ github.com/warpfork/go-testmark v0.11.0 h1:J6LnV8KpceDvo7spaNU4+DauH2n1x+6RaO2rJ
270284
github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
271285
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
272286
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
287+
github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIfyDmc1Em5GqlNRzcdtlv4HTNmdpt7XH0=
273288
github.com/whyrusleeping/cbor-gen v0.0.0-20200123233031-1cdf64d27158/go.mod h1:Xj/M2wWU+QdTdRbu/L/1dIZY8/Wb2K9pAhtroQuxJJI=
274289
github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa h1:EyA027ZAkuaCLoxVX4r1TZMPy1d31fM6hbfQ4OU4I5o=
275290
github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=

internal/filesystem/ipfs/ipfs.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,11 @@ func (fsys *IPFS) nodeContext() (context.Context, context.CancelFunc) {
300300
}
301301

302302
func (fsys *IPFS) walkLinks(root cid.Cid, names []string) (cid.Cid, error) {
303-
return walkLinks(root, names, func(c cid.Cid) (ipld.Node, error) {
304-
return fsys.getNode(c)
305-
})
303+
var (
304+
ctx = fsys.ctx
305+
resolver = newPathResolver(fsys.core)
306+
)
307+
return walkLinks(ctx, root, names, resolver)
306308
}
307309

308310
func (fsys *IPFS) Open(name string) (fs.File, error) {

internal/filesystem/ipfs/ipns.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import (
1616
coreiface "github.com/ipfs/boxo/coreiface"
1717
corepath "github.com/ipfs/boxo/coreiface/path"
1818
"github.com/ipfs/go-cid"
19-
ipld "github.com/ipfs/go-ipld-format"
2019
)
2120

2221
type (
@@ -196,11 +195,11 @@ func (fsys *IPNS) toCID(op, goPath string) (cid.Cid, error) {
196195
if ipfs, ok := fsys.ipfs.(*IPFS); ok {
197196
leafCid, err = ipfs.walkLinks(rootCID, names[1:])
198197
} else {
199-
leafCid, err = walkLinks(rootCID, names[1:], func(c cid.Cid) (ipld.Node, error) {
200-
ctx, cancel := fsys.nodeContext()
201-
defer cancel()
202-
return fsys.core.Dag().Get(ctx, c)
203-
})
198+
var (
199+
ctx = fsys.ctx
200+
resolver = newPathResolver(fsys.core)
201+
)
202+
leafCid, err = walkLinks(ctx, rootCID, names[1:], resolver)
204203
}
205204
if err != nil {
206205
kind := resolveErrKind(err)
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package ipfs
2+
3+
import (
4+
"context"
5+
"io"
6+
7+
fserrors "github.com/djdv/go-filesystem-utils/internal/filesystem/errors"
8+
"github.com/ipfs/boxo/blockservice"
9+
coreiface "github.com/ipfs/boxo/coreiface"
10+
ipath "github.com/ipfs/boxo/coreiface/path"
11+
"github.com/ipfs/boxo/exchange"
12+
bsfetcher "github.com/ipfs/boxo/fetcher/impl/blockservice"
13+
"github.com/ipfs/boxo/path/resolver"
14+
blocks "github.com/ipfs/go-block-format"
15+
"github.com/ipfs/go-cid"
16+
"github.com/ipfs/go-unixfsnode"
17+
)
18+
19+
type (
20+
coreBlockStore struct {
21+
blocks coreiface.BlockAPI
22+
validate bool
23+
}
24+
blockFetcher struct {
25+
coreiface.APIDagService
26+
}
27+
)
28+
29+
func newPathResolver(api coreiface.CoreAPI) resolver.Resolver {
30+
var (
31+
blockstore = newCoreBlockStore(api.Block())
32+
fetcher = makeBlockFetcher(api.Dag())
33+
service = blockservice.New(blockstore, fetcher)
34+
config = bsfetcher.NewFetcherConfig(service)
35+
fetcherFactory = config.WithReifier(unixfsnode.Reify)
36+
)
37+
return resolver.NewBasicResolver(fetcherFactory)
38+
}
39+
40+
func newCoreBlockStore(blocks coreiface.BlockAPI) *coreBlockStore {
41+
return &coreBlockStore{blocks: blocks}
42+
}
43+
44+
func makeBlockFetcher(dag coreiface.APIDagService) exchange.Interface {
45+
return blockFetcher{APIDagService: dag}
46+
}
47+
48+
func (bs *coreBlockStore) fetch(ctx context.Context, c cid.Cid) (blocks.Block, error) {
49+
blockReader, err := bs.blocks.Get(ctx, ipath.IpfsPath(c))
50+
if err != nil {
51+
return nil, err
52+
}
53+
blockData, err := io.ReadAll(blockReader)
54+
if err != nil {
55+
return nil, err
56+
}
57+
if bs.validate {
58+
nc, err := c.Prefix().Sum(blockData)
59+
if err != nil {
60+
return nil, blocks.ErrWrongHash
61+
}
62+
if !nc.Equals(c) {
63+
return nil, blocks.ErrWrongHash
64+
}
65+
}
66+
return blocks.NewBlockWithCid(blockData, c)
67+
}
68+
69+
func (bs *coreBlockStore) Has(ctx context.Context, c cid.Cid) (bool, error) {
70+
blk, err := bs.fetch(ctx, c)
71+
if err != nil {
72+
return false, err
73+
}
74+
return blk != nil, nil
75+
}
76+
77+
func (bs *coreBlockStore) Get(ctx context.Context, c cid.Cid) (blocks.Block, error) {
78+
blk, err := bs.fetch(ctx, c)
79+
if err != nil {
80+
return nil, err
81+
}
82+
return blk, nil
83+
}
84+
85+
func (bs *coreBlockStore) GetSize(ctx context.Context, c cid.Cid) (int, error) {
86+
blk, err := bs.fetch(ctx, c)
87+
if err != nil {
88+
return 0, err
89+
}
90+
return len(blk.RawData()), nil
91+
}
92+
93+
func (bs *coreBlockStore) HashOnRead(enabled bool) {
94+
bs.validate = enabled
95+
}
96+
97+
func (*coreBlockStore) Put(context.Context, blocks.Block) error {
98+
return fserrors.ErrUnsupported
99+
}
100+
101+
func (*coreBlockStore) PutMany(context.Context, []blocks.Block) error {
102+
return fserrors.ErrUnsupported
103+
}
104+
105+
func (*coreBlockStore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
106+
return nil, fserrors.ErrUnsupported
107+
}
108+
109+
func (*coreBlockStore) DeleteBlock(context.Context, cid.Cid) error {
110+
return fserrors.ErrUnsupported
111+
}
112+
113+
func (bf blockFetcher) GetBlock(ctx context.Context, c cid.Cid) (blocks.Block, error) {
114+
return bf.APIDagService.Get(ctx, c)
115+
}
116+
117+
func (bf blockFetcher) GetBlocks(ctx context.Context, cids []cid.Cid) (<-chan blocks.Block, error) {
118+
out := make(chan blocks.Block)
119+
go func() {
120+
defer close(out)
121+
for _, c := range cids {
122+
block, err := bf.GetBlock(ctx, c)
123+
if err != nil {
124+
return
125+
}
126+
select {
127+
case out <- block:
128+
case <-ctx.Done():
129+
return
130+
}
131+
}
132+
}()
133+
return out, nil
134+
}
135+
136+
func (blockFetcher) NotifyNewBlocks(ctx context.Context, blocks ...blocks.Block) error {
137+
return nil
138+
}
139+
140+
func (blockFetcher) Close() error {
141+
return nil
142+
}

internal/filesystem/ipfs/shared.go

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ package ipfs
33
import (
44
"context"
55
"errors"
6-
"fmt"
76
"io"
87
"io/fs"
8+
"path"
99
"strings"
1010
"time"
1111

@@ -16,6 +16,8 @@ import (
1616
dag "github.com/ipfs/boxo/ipld/merkledag"
1717
"github.com/ipfs/boxo/ipld/unixfs"
1818
unixpb "github.com/ipfs/boxo/ipld/unixfs/pb"
19+
ipath "github.com/ipfs/boxo/path"
20+
"github.com/ipfs/boxo/path/resolver"
1921
"github.com/ipfs/go-cid"
2022
ipfscmds "github.com/ipfs/go-ipfs-cmds"
2123
cbor "github.com/ipfs/go-ipld-cbor"
@@ -368,37 +370,20 @@ func drainThenSendErr(ch chan filesystem.StreamDirEntry, err error) {
368370
ch <- newErrorEntry(err)
369371
}
370372

371-
func walkLinks(root cid.Cid, names []string, getNodeFn getNodeFunc) (cid.Cid, error) {
372-
node, err := getNodeFn(root)
373-
if err != nil {
374-
return cid.Cid{}, err
375-
}
373+
func walkLinks(ctx context.Context,
374+
root cid.Cid, names []string,
375+
resolver resolver.Resolver,
376+
) (cid.Cid, error) {
376377
var (
377-
leafCid cid.Cid
378-
end = len(names) - 1
378+
iPath = ipath.FromCid(root)
379+
components = append(
380+
[]string{string(iPath)},
381+
names...,
382+
)
383+
nodePath = ipath.FromString(path.Join(components...))
379384
)
380-
for i, name := range names {
381-
object, _, err := node.Resolve([]string{name})
382-
if err != nil {
383-
return cid.Cid{}, err
384-
}
385-
link, ok := object.(*ipld.Link)
386-
if !ok {
387-
return cid.Cid{}, fmt.Errorf(
388-
"expected: `%T` got: `%T`",
389-
link, object,
390-
)
391-
}
392-
leafCid = link.Cid
393-
if i == end {
394-
break
395-
}
396-
node, err = getNodeFn(leafCid)
397-
if err != nil {
398-
return cid.Cid{}, err
399-
}
400-
}
401-
return leafCid, nil
385+
leaf, _, err := resolver.ResolveToLastNode(ctx, nodePath)
386+
return leaf, err
402387
}
403388

404389
func fsTypeName(mode fs.FileMode) string {

0 commit comments

Comments
 (0)