From 385e2aa85a2758690cd49115b67f6e9e36e8aae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Fri, 3 Mar 2023 13:36:53 +0100 Subject: [PATCH] pin: follow async pinner changes, use directly CoreApi.Pin.Verify --- core/commands/pin/pin.go | 132 ++++++++----------------- core/coreapi/pin.go | 204 ++++++++++++++++++++++++++------------- gc/gc.go | 55 +++++++---- go.mod | 7 ++ go.sum | 14 +-- 5 files changed, 225 insertions(+), 187 deletions(-) diff --git a/core/commands/pin/pin.go b/core/commands/pin/pin.go index 89e56f687ff1..50c84eb3f153 100644 --- a/core/commands/pin/pin.go +++ b/core/commands/pin/pin.go @@ -8,18 +8,13 @@ import ( "os" "time" - bserv "github.com/ipfs/go-blockservice" - cid "github.com/ipfs/go-cid" cidenc "github.com/ipfs/go-cidutil/cidenc" cmds "github.com/ipfs/go-ipfs-cmds" - offline "github.com/ipfs/go-ipfs-exchange-offline" dag "github.com/ipfs/go-merkledag" - verifcid "github.com/ipfs/go-verifcid" coreiface "github.com/ipfs/interface-go-ipfs-core" options "github.com/ipfs/interface-go-ipfs-core/options" "github.com/ipfs/interface-go-ipfs-core/path" - core "github.com/ipfs/kubo/core" cmdenv "github.com/ipfs/kubo/core/commands/cmdenv" e "github.com/ipfs/kubo/core/commands/e" ) @@ -502,13 +497,14 @@ func pinLsAll(req *cmds.Request, typeStr string, api coreiface.CoreAPI, emit fun panic("unhandled pin type") } - pins, err := api.Pin().Ls(req.Context, opt) - if err != nil { - return err - } + pins := api.Pin().Ls(req.Context, opt) - for p := range pins { - if err := p.Err(); err != nil { + for { + p, err := pins.ReadContext(req.Context) + if err == io.EOF { + break + } + if err != nil { return err } err = emit(&PinLsOutputWrapper{ @@ -603,7 +599,7 @@ var verifyPinCmd = &cmds.Command{ cmds.BoolOption(pinQuietOptionName, "q", "Write just hashes of broken pins."), }, Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { - n, err := cmdenv.GetNode(env) + api, err := cmdenv.GetApi(env, req) if err != nil { return err } @@ -620,15 +616,38 @@ var verifyPinCmd = &cmds.Command{ return err } - opts := pinVerifyOpts{ - explain: !quiet, - includeOk: verbose, - } - out, err := pinVerify(req.Context, n, opts, enc) - if err != nil { - return err + out := api.Pin().Verify(req.Context, options.Pin.Verify.Explain(!quiet), options.Pin.Verify.IncludeOk(verbose)) + + for { + s, err := out.Read() + if err == io.EOF { + break + } + if err != nil { + return err + } + status := PinStatus{ + Ok: s.Ok(), + } + badNodes := s.BadNodes() + if len(badNodes) > 0 { + status.BadNodes = make([]BadNode, len(badNodes)) + for i, node := range s.BadNodes() { + status.BadNodes[i] = BadNode{ + Cid: enc.Encode(node.Path().Cid()), + Err: node.Err().Error(), + } + } + } + err = res.Emit(PinVerifyRes{ + Cid: enc.Encode(s.Cid()), + PinStatus: PinStatus{}, + }) + if err != nil { + return err + } } - return res.Emit(out) + return nil }, Type: PinVerifyRes{}, Encoders: cmds.EncoderMap{ @@ -664,79 +683,6 @@ type BadNode struct { Err string } -type pinVerifyOpts struct { - explain bool - includeOk bool -} - -func pinVerify(ctx context.Context, n *core.IpfsNode, opts pinVerifyOpts, enc cidenc.Encoder) (<-chan interface{}, error) { - visited := make(map[cid.Cid]PinStatus) - - bs := n.Blocks.Blockstore() - DAG := dag.NewDAGService(bserv.New(bs, offline.Exchange(bs))) - getLinks := dag.GetLinksWithDAG(DAG) - recPins, err := n.Pinning.RecursiveKeys(ctx) - if err != nil { - return nil, err - } - - var checkPin func(root cid.Cid) PinStatus - checkPin = func(root cid.Cid) PinStatus { - key := root - if status, ok := visited[key]; ok { - return status - } - - if err := verifcid.ValidateCid(root); err != nil { - status := PinStatus{Ok: false} - if opts.explain { - status.BadNodes = []BadNode{{Cid: enc.Encode(key), Err: err.Error()}} - } - visited[key] = status - return status - } - - links, err := getLinks(ctx, root) - if err != nil { - status := PinStatus{Ok: false} - if opts.explain { - status.BadNodes = []BadNode{{Cid: enc.Encode(key), Err: err.Error()}} - } - visited[key] = status - return status - } - - status := PinStatus{Ok: true} - for _, lnk := range links { - res := checkPin(lnk.Cid) - if !res.Ok { - status.Ok = false - status.BadNodes = append(status.BadNodes, res.BadNodes...) - } - } - - visited[key] = status - return status - } - - out := make(chan interface{}) - go func() { - defer close(out) - for _, cid := range recPins { - pinStatus := checkPin(cid) - if !pinStatus.Ok || opts.includeOk { - select { - case out <- &PinVerifyRes{enc.Encode(cid), pinStatus}: - case <-ctx.Done(): - return - } - } - } - }() - - return out, nil -} - // Format formats PinVerifyRes func (r PinVerifyRes) Format(out io.Writer) { if r.Ok { diff --git a/core/coreapi/pin.go b/core/coreapi/pin.go index 41327c8c328b..619a96876999 100644 --- a/core/coreapi/pin.go +++ b/core/coreapi/pin.go @@ -3,18 +3,22 @@ package coreapi import ( "context" "fmt" + "io" + "github.com/Jorropo/channel" bserv "github.com/ipfs/go-blockservice" "github.com/ipfs/go-cid" offline "github.com/ipfs/go-ipfs-exchange-offline" pin "github.com/ipfs/go-ipfs-pinner" "github.com/ipfs/go-merkledag" + "github.com/ipfs/go-verifcid" coreiface "github.com/ipfs/interface-go-ipfs-core" caopts "github.com/ipfs/interface-go-ipfs-core/options" "github.com/ipfs/interface-go-ipfs-core/path" - "github.com/ipfs/kubo/tracing" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" + + "github.com/ipfs/kubo/tracing" ) type PinAPI CoreAPI @@ -49,13 +53,13 @@ func (api *PinAPI) Add(ctx context.Context, p path.Path, opts ...caopts.PinAddOp return api.pinning.Flush(ctx) } -func (api *PinAPI) Ls(ctx context.Context, opts ...caopts.PinLsOption) (<-chan coreiface.Pin, error) { +func (api *PinAPI) Ls(ctx context.Context, opts ...caopts.PinLsOption) channel.ReadOnly[coreiface.Pin] { ctx, span := tracing.Span(ctx, "CoreAPI.PinAPI", "Ls") defer span.End() settings, err := caopts.PinLsOptions(opts...) if err != nil { - return nil, err + return channel.NewWithError[coreiface.Pin](err).ReadOnly() } span.SetAttributes(attribute.String("type", settings.Type)) @@ -63,10 +67,11 @@ func (api *PinAPI) Ls(ctx context.Context, opts ...caopts.PinLsOption) (<-chan c switch settings.Type { case "all", "direct", "indirect", "recursive": default: - return nil, fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", settings.Type) + err := fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", settings.Type) + return channel.NewWithError[coreiface.Pin](err).ReadOnly() } - return api.pinLsAll(ctx, settings.Type), nil + return api.pinLsAll(ctx, settings.Type) } func (api *PinAPI) IsPinned(ctx context.Context, p path.Path, opts ...caopts.PinIsPinnedOption) (string, bool, error) { @@ -167,6 +172,10 @@ type badNode struct { err error } +func (s *pinStatus) Cid() cid.Cid { + return s.cid +} + func (s *pinStatus) Ok() bool { return s.ok } @@ -183,18 +192,19 @@ func (n *badNode) Err() error { return n.err } -func (api *PinAPI) Verify(ctx context.Context) (<-chan coreiface.PinStatus, error) { +func (api *PinAPI) Verify(ctx context.Context, opts ...caopts.PinVerifyOption) channel.ReadOnly[coreiface.PinStatus] { ctx, span := tracing.Span(ctx, "CoreAPI.PinAPI", "Verify") defer span.End() + settings, err := caopts.PinVerifyOptions(opts...) + if err != nil { + return channel.NewWithError[coreiface.PinStatus](err).ReadOnly() + } + visited := make(map[cid.Cid]*pinStatus) bs := api.blockstore DAG := merkledag.NewDAGService(bserv.New(bs, offline.Exchange(bs))) getLinks := merkledag.GetLinksWithDAG(DAG) - recPins, err := api.pinning.RecursiveKeys(ctx) - if err != nil { - return nil, err - } var checkPin func(root cid.Cid) *pinStatus checkPin = func(root cid.Cid) *pinStatus { @@ -205,20 +215,33 @@ func (api *PinAPI) Verify(ctx context.Context) (<-chan coreiface.PinStatus, erro return status } + if err := verifcid.ValidateCid(root); err != nil { + status := &pinStatus{ok: false, cid: root} + if settings.Explain { + status.badNodes = []coreiface.BadPinNode{&badNode{path: path.IpldPath(root), err: err}} + } + visited[root] = status + return status + } + 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}} + if settings.Explain { + status.badNodes = []coreiface.BadPinNode{&badNode{path: path.IpldPath(root), err: err}} + } visited[root] = status return status } - status := &pinStatus{ok: true, cid: root} + status := &pinStatus{cid: root} for _, lnk := range links { res := checkPin(lnk.Cid) - if !res.ok { - status.ok = false - status.badNodes = append(status.badNodes, res.badNodes...) + if !res.ok || settings.IncludeOk { + status.ok = res.ok + if settings.Explain { + status.badNodes = append(status.badNodes, res.badNodes...) + } } } @@ -226,15 +249,28 @@ func (api *PinAPI) Verify(ctx context.Context) (<-chan coreiface.PinStatus, erro return status } - out := make(chan coreiface.PinStatus) + recPins := api.pinning.RecursiveKeys(ctx) + + out := channel.New[coreiface.PinStatus]() go func() { - defer close(out) - for _, c := range recPins { - out <- checkPin(c) + defer out.Close() + for { + c, err := recPins.ReadContext(ctx) + if err == io.EOF { + break + } + if err != nil { + out.SetError(err) + break + } + err = out.WriteContext(ctx, checkPin(c)) + if err != nil { + break + } } }() - return out, nil + return out.ReadOnly() } type pinInfo struct { @@ -259,58 +295,82 @@ func (p *pinInfo) Err() error { // // The caller must keep reading results until the channel is closed to prevent // leaking the goroutine that is fetching pins. -func (api *PinAPI) pinLsAll(ctx context.Context, typeStr string) <-chan coreiface.Pin { - out := make(chan coreiface.Pin, 1) - - keys := cid.NewSet() - - AddToResultKeys := func(keyList []cid.Cid, typeStr string) error { - for _, c := range keyList { - if keys.Visit(c) { - select { - case out <- &pinInfo{ - pinType: typeStr, - path: path.IpldPath(c), - }: - case <-ctx.Done(): - return ctx.Err() - } +func (api *PinAPI) pinLsAll(ctx context.Context, typeStr string) channel.ReadOnly[coreiface.Pin] { + out := channel.NewWithSize[coreiface.Pin](1) + + keySet := cid.NewSet() + + AddToResultKeys := func(c cid.Cid, typeStr string) error { + if keySet.Visit(c) { + err := out.WriteContext(ctx, &pinInfo{ + pinType: typeStr, + path: path.IpldPath(c), + }) + if err != nil { + return err } } return nil } - VisitKeys := func(keyList []cid.Cid) { - for _, c := range keyList { - keys.Visit(c) + VisitKeys := func(keyCh channel.ReadOnly[cid.Cid]) error { + for { + c, err := keyCh.Read() + if err == io.EOF { + return nil + } + if err != nil { + return err + } + keySet.Visit(c) } } go func() { - defer close(out) + defer out.Close() var dkeys, rkeys []cid.Cid var err error if typeStr == "recursive" || typeStr == "all" { - rkeys, err = api.pinning.RecursiveKeys(ctx) - if err != nil { - out <- &pinInfo{err: err} - return - } - if err = AddToResultKeys(rkeys, "recursive"); err != nil { - out <- &pinInfo{err: err} - return + rch := api.pinning.RecursiveKeys(ctx) + for { + k, err := rch.ReadContext(ctx) + if err == io.EOF { + return + } + if err != nil { + out.SetError(err) + return + } + if typeStr == "all" { + rkeys = append(rkeys, k) + } + err = AddToResultKeys(k, "recursive") + if err != nil { + out.SetError(err) + return + } } } if typeStr == "direct" || typeStr == "all" { - dkeys, err = api.pinning.DirectKeys(ctx) - if err != nil { - out <- &pinInfo{err: err} - return - } - if err = AddToResultKeys(dkeys, "direct"); err != nil { - out <- &pinInfo{err: err} - return + dch := api.pinning.DirectKeys(ctx) + for { + k, err := dch.ReadContext(ctx) + if err == io.EOF { + return + } + if err != nil { + out.SetError(err) + return + } + if typeStr == "all" { + rkeys = append(dkeys, k) + } + err = AddToResultKeys(k, "direct") + if err != nil { + out.SetError(err) + return + } } } if typeStr == "all" { @@ -322,12 +382,15 @@ func (api *PinAPI) pinLsAll(ctx context.Context, typeStr string) <-chan coreifac merkledag.SkipRoot(), merkledag.Concurrent(), ) if err != nil { - out <- &pinInfo{err: err} + out.SetError(err) return } } - if err = AddToResultKeys(set.Keys(), "indirect"); err != nil { - out <- &pinInfo{err: err} + err = set.ForEach(func(c cid.Cid) error { + return AddToResultKeys(c, "indirect") + }) + if err != nil { + out.SetError(err) return } } @@ -335,19 +398,19 @@ func (api *PinAPI) pinLsAll(ctx context.Context, typeStr string) <-chan coreifac // We need to first visit the direct pins that have priority // without emitting them - dkeys, err = api.pinning.DirectKeys(ctx) + dch := api.pinning.DirectKeys(ctx) + err = VisitKeys(dch) if err != nil { - out <- &pinInfo{err: err} + out.SetError(err) return } - VisitKeys(dkeys) - rkeys, err = api.pinning.RecursiveKeys(ctx) + rch := api.pinning.RecursiveKeys(ctx) + err = VisitKeys(rch) if err != nil { - out <- &pinInfo{err: err} + out.SetError(err) return } - VisitKeys(rkeys) set := cid.NewSet() for _, k := range rkeys { @@ -357,18 +420,21 @@ func (api *PinAPI) pinLsAll(ctx context.Context, typeStr string) <-chan coreifac merkledag.SkipRoot(), merkledag.Concurrent(), ) if err != nil { - out <- &pinInfo{err: err} + out.SetError(err) return } } - if err = AddToResultKeys(set.Keys(), "indirect"); err != nil { - out <- &pinInfo{err: err} + err = set.ForEach(func(c cid.Cid) error { + return AddToResultKeys(c, "indirect") + }) + if err != nil { + out.SetError(err) return } } }() - return out + return out.ReadOnly() } func (api *PinAPI) core() coreiface.CoreAPI { diff --git a/gc/gc.go b/gc/gc.go index 851b42d3b32e..6f3306287dd6 100644 --- a/gc/gc.go +++ b/gc/gc.go @@ -5,8 +5,10 @@ import ( "context" "errors" "fmt" + "io" "strings" + "github.com/Jorropo/channel" bserv "github.com/ipfs/go-blockservice" cid "github.com/ipfs/go-cid" dstore "github.com/ipfs/go-datastore" @@ -154,7 +156,7 @@ func GC(ctx context.Context, bs bstore.GCBlockstore, dstor dstore.Datastore, pn // Descendants recursively finds all the descendants of the given roots and // adds them to the given cid.Set, using the provided dag.GetLinks function // to walk the tree. -func Descendants(ctx context.Context, getLinks dag.GetLinks, set *cid.Set, roots []cid.Cid) error { +func Descendants(ctx context.Context, getLinks dag.GetLinks, set *cid.Set, roots channel.ReadOnly[cid.Cid]) error { verifyGetLinks := func(ctx context.Context, c cid.Cid) ([]*ipld.Link, error) { err := verifcid.ValidateCid(c) if err != nil { @@ -167,7 +169,7 @@ func Descendants(ctx context.Context, getLinks dag.GetLinks, set *cid.Set, roots verboseCidError := func(err error) error { if strings.Contains(err.Error(), verifcid.ErrBelowMinimumHashLength.Error()) || strings.Contains(err.Error(), verifcid.ErrPossiblyInsecureHashFunction.Error()) { - err = fmt.Errorf("\"%s\"\nPlease run 'ipfs pin verify'"+ //nolint + err = fmt.Errorf("\"%s\"\nPlease run 'ipfs pin verify'"+ // nolint " to list insecure hashes. If you want to read them,"+ " please downgrade your go-ipfs to 0.4.13\n", err) log.Error(err) @@ -175,9 +177,16 @@ func Descendants(ctx context.Context, getLinks dag.GetLinks, set *cid.Set, roots return err } - for _, c := range roots { + for { + r, err := roots.ReadContext(ctx) + if err == io.EOF { + break + } + if err != nil { + return err + } // Walk recursively walks the dag and adds the keys to the given set - err := dag.Walk(ctx, verifyGetLinks, c, func(k cid.Cid) bool { + err = dag.Walk(ctx, verifyGetLinks, r, func(k cid.Cid) bool { return set.Visit(toCidV1(k)) }, dag.Concurrent()) @@ -217,11 +226,8 @@ func ColoredSet(ctx context.Context, pn pin.Pinner, ng ipld.NodeGetter, bestEffo } return links, nil } - rkeys, err := pn.RecursiveKeys(ctx) - if err != nil { - return nil, err - } - err = Descendants(ctx, getLinks, gcs, rkeys) + rkeys := pn.RecursiveKeys(ctx) + err := Descendants(ctx, getLinks, gcs, rkeys) if err != nil { errors = true select { @@ -243,7 +249,17 @@ func ColoredSet(ctx context.Context, pn pin.Pinner, ng ipld.NodeGetter, bestEffo } return links, nil } - err = Descendants(ctx, bestEffortGetLinks, gcs, bestEffortRoots) + bestEffortRootsChan := channel.New[cid.Cid]() + go func() { + defer bestEffortRootsChan.Close() + for _, root := range bestEffortRoots { + err := bestEffortRootsChan.WriteContext(ctx, root) + if err != nil { + return + } + } + }() + err = Descendants(ctx, bestEffortGetLinks, gcs, bestEffortRootsChan.ReadOnly()) if err != nil { errors = true select { @@ -253,18 +269,19 @@ func ColoredSet(ctx context.Context, pn pin.Pinner, ng ipld.NodeGetter, bestEffo } } - dkeys, err := pn.DirectKeys(ctx) - if err != nil { - return nil, err - } - for _, k := range dkeys { + dkeys := pn.DirectKeys(ctx) + for { + k, err := dkeys.ReadContext(ctx) + if err == io.EOF { + break + } + if err != nil { + return nil, err + } gcs.Add(toCidV1(k)) } - ikeys, err := pn.InternalPins(ctx) - if err != nil { - return nil, err - } + ikeys := pn.InternalPins(ctx) err = Descendants(ctx, getLinks, gcs, ikeys) if err != nil { errors = true diff --git a/go.mod b/go.mod index 2892d37401eb..e0eddb20ee2e 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/ipfs/kubo require ( bazil.org/fuse v0.0.0-20200117225306-7b5117fecadc contrib.go.opencensus.io/exporter/prometheus v0.4.0 + github.com/Jorropo/channel v0.0.0-20230303124104-2821e25e07ff github.com/benbjohnson/clock v1.3.0 github.com/blang/semver/v4 v4.0.0 github.com/cenkalti/backoff/v4 v4.1.3 @@ -112,6 +113,12 @@ require ( golang.org/x/sys v0.5.0 ) +replace github.com/ipfs/go-ipfs-pinner => github.com/MichaelMure/go-ipfs-pinner v0.0.0-20230303124704-e9bb7525f460 + +replace github.com/ipfs/go-ipfs-provider => github.com/MichaelMure/go-ipfs-provider v0.2.2-0.20230303124815-ff76035d5f80 + +replace github.com/ipfs/interface-go-ipfs-core => github.com/MichaelMure/interface-go-ipfs-core v0.2.6-0.20230303124916-a0039ef4e30d + require ( github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect github.com/Kubuxu/go-os-helper v0.0.1 // indirect diff --git a/go.sum b/go.sum index 6f7800a2e2ae..84fa4f6f0d24 100644 --- a/go.sum +++ b/go.sum @@ -48,9 +48,17 @@ github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIo github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Jorropo/channel v0.0.0-20230303124104-2821e25e07ff h1:esIsTO+B4ChRmGN1F2NQXe3y1zV6+VtW5q2NfiKKptc= +github.com/Jorropo/channel v0.0.0-20230303124104-2821e25e07ff/go.mod h1:mI95Zfa5HM2woyGuaxl2tTnfZKKzPAyjwcbvmMk7hwI= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Kubuxu/go-os-helper v0.0.1 h1:EJiD2VUQyh5A9hWJLmc6iWg6yIcJ7jpBcwC8GMGXfDk= github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= +github.com/MichaelMure/go-ipfs-pinner v0.0.0-20230303124704-e9bb7525f460 h1:FByV+AP8xLpdpbO4ebcB2Uex6aPWbwMX/Mg2S9/h5Jc= +github.com/MichaelMure/go-ipfs-pinner v0.0.0-20230303124704-e9bb7525f460/go.mod h1:3E+m0syzciBIH+s1hM8G73wFtLaYe9sunobxkAk96po= +github.com/MichaelMure/go-ipfs-provider v0.2.2-0.20230303124815-ff76035d5f80 h1:Jab/EkbgStSfpRoJ0R3N1uVuL/3A3rHaEOciZo0eDEU= +github.com/MichaelMure/go-ipfs-provider v0.2.2-0.20230303124815-ff76035d5f80/go.mod h1:GBFM+yN++2u8CWBZ0MFv9c8kiLYJncY7RhtG3z0bNGI= +github.com/MichaelMure/interface-go-ipfs-core v0.2.6-0.20230303124916-a0039ef4e30d h1:loKosVDzj1qevU5XLhF+RklGEwaC1KclagPTigXgk04= +github.com/MichaelMure/interface-go-ipfs-core v0.2.6-0.20230303124916-a0039ef4e30d/go.mod h1:wBTLIe1NNdZdsuwXXJlANYzxwWcVXIon4a+WAObsoy0= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= @@ -554,16 +562,12 @@ github.com/ipfs/go-ipfs-exchange-offline v0.3.0/go.mod h1:MOdJ9DChbb5u37M1IcbrRB github.com/ipfs/go-ipfs-files v0.0.3/go.mod h1:INEFm0LL2LWXBhNJ2PMIIb2w45hpXgPjNoE7yA8Y1d4= github.com/ipfs/go-ipfs-keystore v0.1.0 h1:gfuQUO/cyGZgZIHE6OrJas4OnwuxXCqJG7tI0lrB5Qc= github.com/ipfs/go-ipfs-keystore v0.1.0/go.mod h1:LvLw7Qhnb0RlMOfCzK6OmyWxICip6lQ06CCmdbee75U= -github.com/ipfs/go-ipfs-pinner v0.3.0 h1:jwe5ViX3BON3KgOAYrrhav2+1ONB0QzFAWQd7HUlbuM= -github.com/ipfs/go-ipfs-pinner v0.3.0/go.mod h1:oX0I0nC6zlNIh0LslSrUnjfNKPq8ufoFtqV1/wcJvyo= github.com/ipfs/go-ipfs-posinfo v0.0.1 h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6OtpRs= github.com/ipfs/go-ipfs-posinfo v0.0.1/go.mod h1:SwyeVP+jCwiDu0C313l/8jg6ZxM0qqtlt2a0vILTc1A= github.com/ipfs/go-ipfs-pq v0.0.1/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= github.com/ipfs/go-ipfs-pq v0.0.2/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY= github.com/ipfs/go-ipfs-pq v0.0.3 h1:YpoHVJB+jzK15mr/xsWC574tyDLkezVrDNeaalQBsTE= github.com/ipfs/go-ipfs-pq v0.0.3/go.mod h1:btNw5hsHBpRcSSgZtiNm/SLj5gYIZ18AKtv3kERkRb4= -github.com/ipfs/go-ipfs-provider v0.8.1 h1:qt670pYmcNH3BCjyXDgg07o2WsTRsOdMwYc25ukCdjQ= -github.com/ipfs/go-ipfs-provider v0.8.1/go.mod h1:qCpwpoohIRVXvNzkygzsM3qdqP/sXlrogtA5I45tClc= github.com/ipfs/go-ipfs-redirects-file v0.1.1 h1:Io++k0Vf/wK+tfnhEh63Yte1oQK5VGT2hIEYpD0Rzx8= github.com/ipfs/go-ipfs-redirects-file v0.1.1/go.mod h1:tAwRjCV0RjLTjH8DR/AU7VYvfQECg+lpUy2Mdzv7gyk= github.com/ipfs/go-ipfs-routing v0.1.0/go.mod h1:hYoUkJLyAUKhF58tysKpids8RNDPO42BVMgK5dNsoqY= @@ -640,8 +644,6 @@ github.com/ipfs/go-unixfsnode v1.5.2/go.mod h1:NlOebRwYx8lMCNMdhAhEspYPBD3obp7TE github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0= github.com/ipfs/go-verifcid v0.0.2 h1:XPnUv0XmdH+ZIhLGKg6U2vaPaRDXb9urMyNVCE7uvTs= github.com/ipfs/go-verifcid v0.0.2/go.mod h1:40cD9x1y4OWnFXbLNJYRe7MpNvWlMn3LZAG5Wb4xnPU= -github.com/ipfs/interface-go-ipfs-core v0.11.0 h1:n1tplrwsz7oZXkpkZM5a3MDBxksMfSQ103ej4e+l7NA= -github.com/ipfs/interface-go-ipfs-core v0.11.0/go.mod h1:xmnoccUXY7N/Q8AIx0vFqgW926/FAZ8+do/1NTEHKsU= github.com/ipld/edelweiss v0.2.0 h1:KfAZBP8eeJtrLxLhi7r3N0cBCo7JmwSRhOJp3WSpNjk= github.com/ipld/edelweiss v0.2.0/go.mod h1:FJAzJRCep4iI8FOFlRriN9n0b7OuX3T/S9++NpBDmA4= github.com/ipld/go-car v0.5.0 h1:kcCEa3CvYMs0iE5BzD5sV7O2EwMiCIp3uF8tA6APQT8=