@cryptotaxi247 / kubo / commits / 519ae27dc

feat: expose BlockKeyCacheSize and enable WriteThrough datastore options (#10614)

* feat: expose BlockKeyCacheSize and enable WriteThrough when bloom filter disabled * import/config: add BatchMaxSize and BatchMaxNodes * config: make BlockKeyCacheSize an OptionalInteger * config: add and wire datastore.WriteThrough option * config: omitempty on BlockKeyCacheSize * changelog: rewrite entry about new options for the datastore * config: add docs for BatchMaxNodes and BatchMaxSize * config: make WriteThrough an optional Flag * changelog: improve description of new datastore/import options * refactor: DefaultWriteThrough as bool * chore: boxo v0.26.0 * docs: config and changelog fixes

Hector Sanjuan committed Dec 20, 2024 at 00:12 UTC 519ae27dcec1dac2db695947b529687d88f78ac4
16 files changed +173 -40
config/datastore.go
+19 -4
@@ -4,8 +4,21 @@ import (
4 "encoding/json"
5 )
6
7 -// DefaultDataStoreDirectory is the directory to store all the local IPFS data.
8 -const DefaultDataStoreDirectory = "datastore"
7 +const (
8 + // DefaultDataStoreDirectory is the directory to store all the local IPFS data.
9 + DefaultDataStoreDirectory = "datastore"
10 +
11 + // DefaultBlockKeyCacheSize is the size for the blockstore two-queue
12 + // cache which caches block keys and sizes.
13 + DefaultBlockKeyCacheSize = 64 << 10
14 +
15 + // DefaultWriteThrough specifies whether to use a "write-through"
16 + // Blockstore and Blockservice. This means that they will write
17 + // without performing any reads to check if the incoming blocks are
18 + // already present in the datastore. Enable for datastores with fast
19 + // writes and slower reads.
20 + DefaultWriteThrough bool = true
21 +)
22
23 // Datastore tracks the configuration of the datastore.
24 type Datastore struct {
@@ -21,8 +34,10 @@ type Datastore struct {
34
35 Spec map[string]interface{}
36
24 - HashOnRead bool
25 - BloomFilterSize int
37 + HashOnRead bool
38 + BloomFilterSize int
39 + BlockKeyCacheSize OptionalInteger `json:",omitempty"`
40 + WriteThrough Flag `json:",omitempty"`
41 }
42
43 // DataStorePath returns the default data store path given a configuration root
config/import.go
+11
@@ -5,6 +5,15 @@ const (
5 DefaultUnixFSRawLeaves = false
6 DefaultUnixFSChunker = "size-262144"
7 DefaultHashFunction = "sha2-256"
8 +
9 + // DefaultBatchMaxNodes controls the maximum number of nodes in a
10 + // write-batch. The total size of the batch is limited by
11 + // BatchMaxnodes and BatchMaxSize.
12 + DefaultBatchMaxNodes = 128
13 + // DefaultBatchMaxSize controls the maximum size of a single
14 + // write-batch. The total size of the batch is limited by
15 + // BatchMaxnodes and BatchMaxSize.
16 + DefaultBatchMaxSize = 100 << 20 // 20MiB
17 )
18
19 // Import configures the default options for ingesting data. This affects commands
@@ -14,4 +23,6 @@ type Import struct {
23 UnixFSRawLeaves Flag
24 UnixFSChunker OptionalString
25 HashFunction OptionalString
26 + BatchMaxNodes OptionalInteger
27 + BatchMaxSize OptionalInteger
28 }
core/commands/dag/import.go
+14 -1
@@ -11,6 +11,7 @@ import (
11 cmds "github.com/ipfs/go-ipfs-cmds"
12 ipld "github.com/ipfs/go-ipld-format"
13 ipldlegacy "github.com/ipfs/go-ipld-legacy"
14 + "github.com/ipfs/kubo/config"
15 "github.com/ipfs/kubo/core/coreiface/options"
16 gocarv2 "github.com/ipld/go-car/v2"
17
@@ -24,6 +25,11 @@ func dagImport(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment
25 return err
26 }
27
28 + cfg, err := node.Repo.Config()
29 + if err != nil {
30 + return err
31 + }
32 +
33 api, err := cmdenv.GetApi(env, req)
34 if err != nil {
35 return err
@@ -55,7 +61,14 @@ func dagImport(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment
61 // this is *not* a transaction
62 // it is simply a way to relieve pressure on the blockstore
63 // similar to pinner.Pin/pinner.Flush
58 - batch := ipld.NewBatch(req.Context, api.Dag())
64 + batch := ipld.NewBatch(req.Context, api.Dag(),
65 + // Default: 128. Means 128 file descriptors needed in flatfs
66 + ipld.MaxNodesBatchOption(int(cfg.Import.BatchMaxNodes.WithDefault(config.DefaultBatchMaxNodes))),
67 + // Default 100MiB. When setting block size to 1MiB, we can add
68 + // ~100 nodes maximum. With default 256KiB block-size, we will
69 + // hit the max nodes limit at 32MiB.p
70 + ipld.MaxSizeBatchOption(int(cfg.Import.BatchMaxSize.WithDefault(config.DefaultBatchMaxSize))),
71 + )
72
73 roots := cid.NewSet()
74 var blockCount, blockBytesCount uint64
core/coreapi/coreapi.go
+8 -6
@@ -207,12 +207,12 @@ func (api *CoreAPI) WithOptions(opts ...options.ApiOption) (coreiface.CoreAPI, e
207 return nil
208 }
209
210 - if settings.Offline {
211 - cfg, err := n.Repo.Config()
212 - if err != nil {
213 - return nil, err
214 - }
210 + cfg, err := n.Repo.Config()
211 + if err != nil {
212 + return nil, err
213 + }
214
215 + if settings.Offline {
216 cs := cfg.Ipns.ResolveCacheSize
217 if cs == 0 {
218 cs = node.DefaultIpnsCacheSize
@@ -244,7 +244,9 @@ func (api *CoreAPI) WithOptions(opts ...options.ApiOption) (coreiface.CoreAPI, e
244
245 if settings.Offline || !settings.FetchBlocks {
246 subAPI.exchange = offlinexch.Exchange(subAPI.blockstore)
247 - subAPI.blocks = bserv.New(subAPI.blockstore, subAPI.exchange)
247 + subAPI.blocks = bserv.New(subAPI.blockstore, subAPI.exchange,
248 + bserv.WriteThrough(cfg.Datastore.WriteThrough.WithDefault(config.DefaultWriteThrough)),
249 + )
250 subAPI.dag = dag.NewDAGService(subAPI.blocks)
251 }
252
core/coreapi/unixfs.go
+8 -5
@@ -21,6 +21,7 @@ import (
21 ds "github.com/ipfs/go-datastore"
22 dssync "github.com/ipfs/go-datastore/sync"
23 ipld "github.com/ipfs/go-ipld-format"
24 + "github.com/ipfs/kubo/config"
25 coreiface "github.com/ipfs/kubo/core/coreiface"
26 options "github.com/ipfs/kubo/core/coreiface/options"
27 "github.com/ipfs/kubo/core/coreunix"
@@ -85,13 +86,15 @@ func (api *UnixfsAPI) Add(ctx context.Context, files files.Node, opts ...options
86 if settings.OnlyHash {
87 // setup a /dev/null pipeline to simulate adding the data
88 dstore := dssync.MutexWrap(ds.NewNullDatastore())
88 - bs := bstore.NewBlockstore(dstore, bstore.WriteThrough(true))
89 - addblockstore = bstore.NewGCBlockstore(bs, nil) // gclocker will never be used
90 - exch = nil // exchange will never be used
91 - pinning = nil // pinner will never be used
89 + bs := bstore.NewBlockstore(dstore, bstore.WriteThrough(true)) // we use NewNullDatastore, so ok to always WriteThrough when OnlyHash
90 + addblockstore = bstore.NewGCBlockstore(bs, nil) // gclocker will never be used
91 + exch = nil // exchange will never be used
92 + pinning = nil // pinner will never be used
93 }
94
94 - bserv := blockservice.New(addblockstore, exch) // hash security 001
95 + bserv := blockservice.New(addblockstore, exch,
96 + blockservice.WriteThrough(cfg.Datastore.WriteThrough.WithDefault(config.DefaultWriteThrough)),
97 + ) // hash security 001
98 dserv := merkledag.NewDAGService(bserv)
99
100 // add a sync call to the DagService
core/node/core.go
+15 -10
@@ -24,21 +24,26 @@ import (
24 dagpb "github.com/ipld/go-codec-dagpb"
25 "go.uber.org/fx"
26
27 + "github.com/ipfs/kubo/config"
28 "github.com/ipfs/kubo/core/node/helpers"
29 "github.com/ipfs/kubo/repo"
30 )
31
32 // BlockService creates new blockservice which provides an interface to fetch content-addressable blocks
32 -func BlockService(lc fx.Lifecycle, bs blockstore.Blockstore, rem exchange.Interface) blockservice.BlockService {
33 - bsvc := blockservice.New(bs, rem)
34 -
35 - lc.Append(fx.Hook{
36 - OnStop: func(ctx context.Context) error {
37 - return bsvc.Close()
38 - },
39 - })
40 -
41 - return bsvc
33 +func BlockService(cfg *config.Config) func(lc fx.Lifecycle, bs blockstore.Blockstore, rem exchange.Interface) blockservice.BlockService {
34 + return func(lc fx.Lifecycle, bs blockstore.Blockstore, rem exchange.Interface) blockservice.BlockService {
35 + bsvc := blockservice.New(bs, rem,
36 + blockservice.WriteThrough(cfg.Datastore.WriteThrough.WithDefault(config.DefaultWriteThrough)),
37 + )
38 +
39 + lc.Append(fx.Hook{
40 + OnStop: func(ctx context.Context) error {
41 + return bsvc.Close()
42 + },
43 + })
44 +
45 + return bsvc
46 + }
47 }
48
49 // Pinning creates new pinner which tells GC which blocks should be kept
core/node/groups.go
+3 -3
@@ -189,6 +189,7 @@ func LibP2P(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part
189 func Storage(bcfg *BuildCfg, cfg *config.Config) fx.Option {
190 cacheOpts := blockstore.DefaultCacheOpts()
191 cacheOpts.HasBloomFilterSize = cfg.Datastore.BloomFilterSize
192 + cacheOpts.HasTwoQueueCacheSize = int(cfg.Datastore.BlockKeyCacheSize.WithDefault(config.DefaultBlockKeyCacheSize))
193 if !bcfg.Permanent {
194 cacheOpts.HasBloomFilterSize = 0
195 }
@@ -201,7 +202,7 @@ func Storage(bcfg *BuildCfg, cfg *config.Config) fx.Option {
202 return fx.Options(
203 fx.Provide(RepoConfig),
204 fx.Provide(Datastore),
204 - fx.Provide(BaseBlockstoreCtor(cacheOpts, cfg.Datastore.HashOnRead)),
205 + fx.Provide(BaseBlockstoreCtor(cacheOpts, cfg.Datastore.HashOnRead, cfg.Datastore.WriteThrough.WithDefault(config.DefaultWriteThrough))),
206 finalBstore,
207 )
208 }
@@ -332,7 +333,6 @@ func Offline(cfg *config.Config) fx.Option {
333
334 // Core groups basic IPFS services
335 var Core = fx.Options(
335 - fx.Provide(BlockService),
336 fx.Provide(Dag),
337 fx.Provide(FetcherConfig),
338 fx.Provide(PathResolverConfig),
@@ -387,7 +387,7 @@ func IPFS(ctx context.Context, bcfg *BuildCfg) fx.Option {
387 Identity(cfg),
388 IPNS,
389 Networked(bcfg, cfg, userResourceOverrides),
390 -
390 + fx.Provide(BlockService(cfg)),
391 Core,
392 )
393 }
core/node/storage.go
+4 -2
@@ -27,10 +27,12 @@ func Datastore(repo repo.Repo) datastore.Datastore {
27 type BaseBlocks blockstore.Blockstore
28
29 // BaseBlockstoreCtor creates cached blockstore backed by the provided datastore
30 -func BaseBlockstoreCtor(cacheOpts blockstore.CacheOpts, hashOnRead bool) func(mctx helpers.MetricsCtx, repo repo.Repo, lc fx.Lifecycle) (bs BaseBlocks, err error) {
30 +func BaseBlockstoreCtor(cacheOpts blockstore.CacheOpts, hashOnRead bool, writeThrough bool) func(mctx helpers.MetricsCtx, repo repo.Repo, lc fx.Lifecycle) (bs BaseBlocks, err error) {
31 return func(mctx helpers.MetricsCtx, repo repo.Repo, lc fx.Lifecycle) (bs BaseBlocks, err error) {
32 // hash security
33 - bs = blockstore.NewBlockstore(repo.Datastore())
33 + bs = blockstore.NewBlockstore(repo.Datastore(),
34 + blockstore.WriteThrough(writeThrough),
35 + )
36 bs = &verifbs.VerifBS{Blockstore: bs}
37 bs, err = blockstore.CachedBlockstore(helpers.LifecycleCtx(mctx, lc), bs, cacheOpts)
38 if err != nil {
docs/changelogs/v0.33.md
+20
@@ -9,6 +9,8 @@
9 - [Bitswap improvements from Boxo](#bitswap-improvements-from-boxo)
10 - [Using default `libp2p_rcmgr` metrics](#using-default-libp2p_rcmgr--metrics)
11 - [`ipfs add --to-files` no longer works with `--wrap`](#ipfs-add---to-files-no-longer-works-with---wrap)
12 + - [New options for faster writes: `WriteThrough`, `BlockKeyCacheSize`, `BatchMaxNodes`, `BatchMaxSize`](#new-options-for-faster-writes-writethrough-blockkeycachesize-batchmaxnodes-batchmaxsize)
13 + - [MFS stability with large number of writes](#mfs-stability-with-large-number-of-writes)
14 - [📦️ Dependency updates](#-dependency-updates)
15 - [📝 Changelog](#-changelog)
16 - [👨‍👩‍👧‍👦 Contributors](#-contributors)
@@ -31,6 +33,24 @@ If you depended on removed ones, please fill an issue to add them to the upstrea
33
34 Onboarding files and directories with `ipfs add --to-files` now requires non-empty names. due to this, The `--to-files` and `--wrap` options are now mutually exclusive ([#10612](https://github.com/ipfs/kubo/issues/10612)).
35
36 +#### New options for faster writes: `WriteThrough`, `BlockKeyCacheSize`, `BatchMaxNodes`, `BatchMaxSize`
37 +
38 +Now that Kubo supports [`pebble`](https://github.com/ipfs/kubo/blob/master/docs/datastores.md#pebbleds) as a datastore backend, it becomes very useful to expose some additional configuration options for how the blockservice/blockstore/datastore combo behaves.
39 +
40 +Usually, LSM-tree based datastore like Pebble or Badger have very fast write performance (blocks are streamed to disk) while incurring in read-amplification penalties (blocks need to be looked up in the index to know where they are on disk), specially noticiable on spinning disks.
41 +
42 +Prior to this version, `BlockService` and `Blockstore` implementations performed a `Has(cid)` for every block that was going to be written, skipping the writes altogether if the block was already present in the datastore. The performance impact of this `Has()` call can vary. The `Datastore` implementation itself might include block-caching and things like bloom-filters to speed up lookups and mitigate read-penalties. Our `Blockstore` implementation also supports a bloom-filter (controlled by `BloomFilterSize` and disabled by default), and a two-queue cache for keys and block sizes. If we assume that most of the blocks added to Kubo are new blocks, not already present in the datastore, or that the datastore itself includes mechanisms to optimize writes and avoid writing the same data twice, the calls to `Has()` at both BlockService and Blockstore layers seem superflous to they point they even harm write performance.
43 +
44 +For these reasons, from now on, the default is to use a "write-through" mode for the Blockservice and the Blockstore. We have added a new option `Datastore.WriteThrough`, which defaults to `true`. Previous behaviour can be obtained by manually setting it to `false`.
45 +
46 +We have also made the size of the two-queue blockstore cache configurable with another option: `Datastore.BlockKeyCacheSize`, which defaults to `65536` (64KiB). Additionally, this caching layer can be disabled altogether by setting it to `0`. In particular, this option controls the size of a blockstore caching layer that records whether the blockstore has certain block and their sizes (but does not cache the contents, so it stays relativey small in general).
47 +
48 +Finally, we have added two new options to the `Import` section to control the maximum size of write-batches: `BatchMaxNodes` and `BatchMaxSize`. These are set by default to `128` nodes and `20MiB`. Increasing them will batch more items together when importing data with `ipfs dag import`, which can speed things up. It is importance to find a balance between available memory (used to hold the batch), disk latencies (when writing the batch) and processing power (when preparing the batch, as nodes are sorted and duplicates removed).
49 +
50 +As a reminder, details from all the options are explained in the [configuration documentation](https://github.com/ipfs/kubo/blob/master/docs/config.md).
51 +
52 +We recommend users trying Pebble as a datastore backend to disable both blockstore bloom-filter and key caching layers and enable write through as a way to evaluate the raw performance of the underlying datastore, which includes its own bloom-filter and caching layers (default cache size is `8MiB` and can be configured in the [options](https://github.com/ipfs/kubo/blob/master/docs/datastores.md#pebbleds).
53 +
54 #### MFS stability with large number of writes
55
56 We have fixed a number of issues that were triggered by writing or copying many files onto an MFS folder: increased memory usage first, then CPU, disk usage, and eventually a deadlock on write operations. The details of the fixes can be read at [#10630](https://github.com/ipfs/kubo/pull/10630) and [#10623](https://github.com/ipfs/kubo/pull/10623). The result is that writing large amounts of files to an MFS folder should now be possible without major issues. It is possible, as before, to speed up the operations using the `ipfs files --flush=false <op> ...` flag, but it is recommended to switch to `ipfs files --flush=true <op> ...` regularly, or call `ipfs files flush` on the working directory regularly, as this will flush, clear the directory cache and speed up reads.
docs/config.md
+62
@@ -40,6 +40,8 @@ config file at runtime.
40 - [`Datastore.GCPeriod`](#datastoregcperiod)
41 - [`Datastore.HashOnRead`](#datastorehashonread)
42 - [`Datastore.BloomFilterSize`](#datastorebloomfiltersize)
43 + - [`Datastore.WriteThrough`](#datastorewritethrough)
44 + - [`Datastore.BlockKeyCacheSize`](#datastoreblockkeycachesize)
45 - [`Datastore.Spec`](#datastorespec)
46 - [`Discovery`](#discovery)
47 - [`Discovery.MDNS`](#discoverymdns)
@@ -176,6 +178,8 @@ config file at runtime.
178 - [`Import.UnixFSRawLeaves`](#importunixfsrawleaves)
179 - [`Import.UnixFSChunker`](#importunixfschunker)
180 - [`Import.HashFunction`](#importhashfunction)
181 + - [`Import.BatchMaxNodes`](#importbatchmaxnodes)
182 + - [`Import.BatchMaxSize`](#importbatchmaxsize)
183 - [`Version`](#version)
184 - [`Version.AgentSuffix`](#versionagentsuffix)
185 - [`Version.SwarmCheckEnabled`](#versionswarmcheckenabled)
@@ -629,10 +633,48 @@ we'd want to use 1199120 bytes. As of writing, [7 hash
633 functions](https://github.com/ipfs/go-ipfs-blockstore/blob/547442836ade055cc114b562a3cc193d4e57c884/caching.go#L22)
634 are used, so the constant `k` is 7 in the formula.
635
636 +Enabling the BloomFilter can provide performance improvements specially when
637 +responding to many requests for inexistant blocks. It however requires a full
638 +sweep of all the datastore keys on daemon start. On very large datastores this
639 +can be a very taxing operation, particulary if the datastore does not support
640 +querying existing keys without reading their values at the same time (blocks).
641 +
642 Default: `0` (disabled)
643
644 Type: `integer` (non-negative, bytes)
645
646 +### `Datastore.WriteThrough`
647 +
648 +This option controls whether a block that already exist in the datastore
649 +should be written to it. When set to `false`, a `Has()` call is performed
650 +against the datastore prior to writing every block. If the block is already
651 +stored, the write is skipped. This check happens both on the Blockservice and
652 +the Blockstore layers and this setting affects both.
653 +
654 +When set to `true`, no checks are performed and blocks are written to the
655 +datastore, which depending on the implementation may perform its own checks.
656 +
657 +This option can affect performance and the strategy should be taken in
658 +conjunction with [`BlockKeyCacheSize`](#datastoreblockkeycachesize) and
659 +[`BloomFilterSize`](#datastoreboomfiltersize`).
660 +
661 +Default: `true`
662 +
663 +Type: `bool`
664 +
665 +### `Datastore.BlockKeyCacheSize`
666 +
667 +A number representing the maximum size in bytes of the blockstore's Two-Queue
668 +cache, which caches block-cids and their block-sizes. Use `0` to disable.
669 +
670 +This cache, once primed, can greatly speed up operations like `ipfs repo stat`
671 +as there is no need to read full blocks to know their sizes. Size should be
672 +adjusted depending on the number of CIDs on disk (`NumObjects in `ipfs repo stat`).
673 +
674 +Default: `65536` (64KiB)
675 +
676 +Type: `optionalInteger` (non-negative, bytes)
677 +
678 ### `Datastore.Spec`
679
680 Spec defines the structure of the ipfs datastore. It is a composable structure,
@@ -2421,6 +2463,26 @@ Default: `sha2-256`
2463
2464 Type: `optionalString`
2465
2466 +### `Import.BatchMaxNodes`
2467 +
2468 +The maximum number of nodes in a write-batch. The total size of the batch is limited by `BatchMaxnodes` and `BatchMaxSize`.
2469 +
2470 +Increasing this will batch more items together when importing data with `ipfs dag import`, which can speed things up.
2471 +
2472 +Default: `128`
2473 +
2474 +Type: `optionalInteger`
2475 +
2476 +### `Import.BatchMaxSize`
2477 +
2478 +The maximum size of a single write-batch (computed as the sum of the sizes of the blocks). The total size of the batch is limited by `BatchMaxnodes` and `BatchMaxSize`.
2479 +
2480 +Increasing this will batch more items together when importing data with `ipfs dag import`, which can speed things up.
2481 +
2482 +Default: `20971520` (20MiB)
2483 +
2484 +Type: `optionalInteger`
2485 +
2486 ## `Version`
2487
2488 Options to configure agent version announced to the swarm, and leveraging
docs/examples/kubo-as-a-library/go.mod
+1 -1
@@ -75,7 +75,7 @@ require (
75 github.com/hashicorp/golang-lru v1.0.2 // indirect
76 github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
77 github.com/huin/goupnp v1.3.0 // indirect
78 - github.com/ipfs-shipyard/nopfs v0.0.13 // indirect
78 + github.com/ipfs-shipyard/nopfs v0.0.14 // indirect
79 github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 // indirect
80 github.com/ipfs/bbloom v0.0.4 // indirect
81 github.com/ipfs/go-bitfield v1.1.0 // indirect
docs/examples/kubo-as-a-library/go.sum
+2 -2
@@ -298,8 +298,8 @@ github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFck
298 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
299 github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
300 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
301 -github.com/ipfs-shipyard/nopfs v0.0.13 h1:eXyI5x0+Y/dgjHl3RgSrVqg+1YwwybhEuRgo3BjNazM=
302 -github.com/ipfs-shipyard/nopfs v0.0.13/go.mod h1:mQyd0BElYI2gB/kq/Oue97obP4B3os4eBmgfPZ+hnrE=
301 +github.com/ipfs-shipyard/nopfs v0.0.14 h1:HFepJt/MxhZ3/GsLZkkAPzIPdNYKaLO1Qb7YmPbWIKk=
302 +github.com/ipfs-shipyard/nopfs v0.0.14/go.mod h1:mQyd0BElYI2gB/kq/Oue97obP4B3os4eBmgfPZ+hnrE=
303 github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 h1:OqNqsGZPX8zh3eFMO8Lf8EHRRnSGBMqcdHUd7SDsUOY=
304 github.com/ipfs-shipyard/nopfs/ipfs v0.25.0/go.mod h1:BxhUdtBgOXg1B+gAPEplkg/GpyTZY+kCMSfsJvvydqU=
305 github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
go.mod
+1 -1
@@ -20,7 +20,7 @@ require (
20 github.com/google/uuid v1.6.0
21 github.com/hashicorp/go-multierror v1.1.1
22 github.com/hashicorp/go-version v1.7.0
23 - github.com/ipfs-shipyard/nopfs v0.0.13
23 + github.com/ipfs-shipyard/nopfs v0.0.14
24 github.com/ipfs-shipyard/nopfs/ipfs v0.25.0
25 github.com/ipfs/boxo v0.26.0
26 github.com/ipfs/go-block-format v0.2.0
go.sum
+2 -2
@@ -362,8 +362,8 @@ github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFck
362 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
363 github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
364 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
365 -github.com/ipfs-shipyard/nopfs v0.0.13 h1:eXyI5x0+Y/dgjHl3RgSrVqg+1YwwybhEuRgo3BjNazM=
366 -github.com/ipfs-shipyard/nopfs v0.0.13/go.mod h1:mQyd0BElYI2gB/kq/Oue97obP4B3os4eBmgfPZ+hnrE=
365 +github.com/ipfs-shipyard/nopfs v0.0.14 h1:HFepJt/MxhZ3/GsLZkkAPzIPdNYKaLO1Qb7YmPbWIKk=
366 +github.com/ipfs-shipyard/nopfs v0.0.14/go.mod h1:mQyd0BElYI2gB/kq/Oue97obP4B3os4eBmgfPZ+hnrE=
367 github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 h1:OqNqsGZPX8zh3eFMO8Lf8EHRRnSGBMqcdHUd7SDsUOY=
368 github.com/ipfs-shipyard/nopfs/ipfs v0.25.0/go.mod h1:BxhUdtBgOXg1B+gAPEplkg/GpyTZY+kCMSfsJvvydqU=
369 github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
test/dependencies/go.mod
+1 -1
@@ -297,7 +297,7 @@ require (
297 go.uber.org/zap v1.27.0 // indirect
298 golang.org/x/crypto v0.31.0 // indirect
299 golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 // indirect
300 - golang.org/x/exp/typeparams v0.0.0-20240613232115-7f521ea00fb8 // indirect
300 + golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f // indirect
301 golang.org/x/mod v0.22.0 // indirect
302 golang.org/x/net v0.33.0 // indirect
303 golang.org/x/sync v0.10.0 // indirect
test/dependencies/go.sum
+2 -2
@@ -890,8 +890,8 @@ golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/
890 golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
891 golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
892 golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
893 -golang.org/x/exp/typeparams v0.0.0-20240613232115-7f521ea00fb8 h1:+ZJmEdDFzH5H0CnzOrwgbH3elHctfTecW9X0k2tkn5M=
894 -golang.org/x/exp/typeparams v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
893 +golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f h1:phY1HzDcf18Aq9A8KkmRtY9WvOFIxN8wgfvy6Zm1DV8=
894 +golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
895 golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
896 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
897 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=