@cryptotaxi247 / kubo / commits / 006f9dc70

feat: opt-in new Sweep provide system (#10834)

* reprovide sweep draft * update reprovider dep * go mod tidy * fix provider type * change router type * dual reprovider * revert to provider.System * back to start * SweepingReprovider test * fix nil pointer deref * noop provider for nil dht * disabled initial network estimation * another iteration * suppress missing self addrs err * silence empty rt err on lan dht * comments * new attempt at integrating * reverting changes in core/node/libp2p/routing.go * removing SweepingProvider * make reprovider optional * add noop reprovider * update KeyChanFunc type alias * restore boxo KeyChanFunc * fix missing KeyChanFunc * test(sharness): PARALLEL=1 and timeout 30m running sequentially to see where timeout occurs * initialize MHStore * revert workflow debug * config * config docs * merged IpfsNode provider and reprovider * move Provider interface to from kad-dht to node * moved Provider interface from kad-dht to kubo/core/node * mod_tidy * Add Clear to Provider interface * use latest kad-dht commit * make linter happy * updated boxo provide interface * boxo PR fix * using latest kad-dht commit * use latest boxo release * fix fx * fx cyclic deps * fix merge issues * extended tests * don't provide LAN DHT * docs * restore dual dht provider * don't start provider before it is online * address linter * dual/provider fix * add delay in provider tests for dht bootstrap * add OfflineDelay parameter to config * remove increase number of workers in test * improved keystore gc process * fix: replace incorrect logger import in coreapi replaced github.com/labstack/gommon/log with the standard github.com/ipfs/go-log/v2 logger used throughout kubo. removed unused labstack dependency from go.mod files. * fix: remove duplicate WithDefault call in provider config * fix: use correct option method for burst workers * fix: improve error messages for experimental sweeping provider updated error messages to clearly indicate when commands are unavailable due to experimental sweeping provider being enabled via Reprovider.Sweep.Enabled=true * docs: remove obsolete KeyStoreGCInterval config removed from config.md as option no longer exists (removed in b540fba1a) updated keystore description to reflect gc happens at reprovide interval * docs: add TODO placeholder changelog for experimental sweeping DHT provider using v0.38-TODO.md name to avoid merge conflicts with master branch and allow CI tests to run. will be renamed to v0.38.md once config migration is added to the PR * fix: provideKeysRec go routine * clear keystore on close * fix: datastore prefix * fix: improve error handling in provideKeysRec - close errCh channel to distinguish between nil and pending errors - check for pending errors when provided.New closes - handle context cancellation during error send - prevent race condition where errors could be silently lost this ensures DAG walk errors are always propagated correctly * address gammazero's review * rename BurstProvider to LegacyProvider * use latest provider/keystore * boxo: make mfs StartProviding async * bump boxo * chore: update boxo to f2b4e12fb9a8ac138ccb82aae3b51ec51d9f631c - updated boxo dependency to specified commit - updated go.mod and go.sum files across all modules * use latest kad-dht/boxo * Buffered SweepingProvider wrapper * use latest kad-dht commit * allow no DHT router * use latest kad-dht & boxo --------- Co-authored-by: Marcin Rataj <lidel@lidel.org> Co-authored-by: gammazero <11790789+gammazero@users.noreply.github.com>

Guillaume Michel committed Sep 18, 2025 at 17:22 UTC 006f9dc70452742bd3184c252008f003e530f577
21 files changed +1190 -566
.github/workflows/sharness.yml
+2 -2
@@ -4,10 +4,10 @@ on:
4 workflow_dispatch:
5 pull_request:
6 paths-ignore:
7 - - '**/*.md'
7 + - "**/*.md"
8 push:
9 branches:
10 - - 'master'
10 + - "master"
11
12 concurrency:
13 group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'push' && github.sha || github.ref }}
config/reprovider.go
+25
@@ -8,6 +8,14 @@ import (
8 const (
9 DefaultReproviderInterval = time.Hour * 22 // https://github.com/ipfs/kubo/pull/9326
10 DefaultReproviderStrategy = "all"
11 +
12 + DefaultReproviderSweepEnabled = false
13 + DefaultReproviderSweepMaxWorkers = 4
14 + DefaultReproviderSweepDedicatedPeriodicWorkers = 2
15 + DefaultReproviderSweepDedicatedBurstWorkers = 1
16 + DefaultReproviderSweepMaxProvideConnsPerWorker = 16
17 + DefaultReproviderSweepKeyStoreBatchSize = 1 << 14 // ~544 KiB per batch (1 multihash = 34 bytes)
18 + DefaultReproviderSweepOfflineDelay = 2 * time.Hour
19 )
20
21 type ReproviderStrategy int
@@ -24,6 +32,23 @@ const (
32 type Reprovider struct {
33 Interval *OptionalDuration `json:",omitempty"` // Time period to reprovide locally stored objects to the network
34 Strategy *OptionalString `json:",omitempty"` // Which keys to announce
35 +
36 + Sweep Sweep
37 +}
38 +
39 +// Sweep configuration describes how the Sweeping Reprovider is configured if enabled.
40 +type Sweep struct {
41 + Enabled Flag `json:",omitempty"`
42 +
43 + MaxWorkers *OptionalInteger // Max number of concurrent workers performing a provide operation.
44 + DedicatedPeriodicWorkers *OptionalInteger // Number of workers dedicated to periodic reprovides.
45 + DedicatedBurstWorkers *OptionalInteger // Number of workers dedicated to initial provides or burst reproviding keyspace regions after a period of inactivity.
46 + MaxProvideConnsPerWorker *OptionalInteger // Number of connections that a worker is able to open to send provider records during a (re)provide operation.
47 +
48 + KeyStoreGCInterval *OptionalDuration // Interval for garbage collection in KeyStore.
49 + KeyStoreBatchSize *OptionalInteger // Number of multihashes to keep in memory when gc'ing the KeyStore.
50 +
51 + OfflineDelay *OptionalDuration // Delay after which the provides changes state from Disconnected to Offline.
52 }
53
54 func ParseReproviderStrategy(s string) ReproviderStrategy {
core/commands/provide.go
+7 -1
@@ -1,6 +1,7 @@
1 package commands
2
3 import (
4 + "errors"
5 "fmt"
6 "io"
7 "text/tabwriter"
@@ -118,7 +119,12 @@ This interface is not stable and may change from release to release.
119 return ErrNotOnline
120 }
121
121 - stats, err := nd.Provider.Stat()
122 + provideSys, ok := nd.Provider.(provider.System)
123 + if !ok {
124 + return errors.New("stats not available with experimental sweeping provider (Reprovider.Sweep.Enabled=true)")
125 + }
126 +
127 + stats, err := provideSys.Stat()
128 if err != nil {
129 return err
130 }
core/commands/routing.go
+17 -25
@@ -11,6 +11,8 @@ import (
11
12 "github.com/ipfs/kubo/config"
13 cmdenv "github.com/ipfs/kubo/core/commands/cmdenv"
14 + "github.com/ipfs/kubo/core/node"
15 + mh "github.com/multiformats/go-multihash"
16
17 dag "github.com/ipfs/boxo/ipld/merkledag"
18 "github.com/ipfs/boxo/ipns"
@@ -207,9 +209,9 @@ var provideRefRoutingCmd = &cmds.Command{
209 go func() {
210 defer cancel()
211 if rec {
210 - provideErr = provideKeysRec(ctx, nd.Routing, nd.DAG, cids)
212 + provideErr = provideCidsRec(ctx, nd.Provider, nd.DAG, cids)
213 } else {
212 - provideErr = provideKeys(ctx, nd.Routing, cids)
214 + provideErr = provideCids(nd.Provider, cids)
215 }
216 if provideErr != nil {
217 routing.PublishQueryEvent(ctx, &routing.QueryEvent{
@@ -274,8 +276,12 @@ Trigger reprovider to announce our data to network.
276 if cfg.Reprovider.Interval.WithDefault(config.DefaultReproviderInterval) == 0 {
277 return errors.New("invalid configuration: Reprovider.Interval is set to '0'")
278 }
279 + provideSys, ok := nd.Provider.(*node.LegacyProvider)
280 + if !ok {
281 + return errors.New("manual reprovide not available with experimental sweeping provider (Reprovider.Sweep.Enabled=true)")
282 + }
283
278 - err = nd.Provider.Reprovide(req.Context)
284 + err = provideSys.Reprovide(req.Context)
285 if err != nil {
286 return err
287 }
@@ -284,39 +290,25 @@ Trigger reprovider to announce our data to network.
290 },
291 }
292
287 -func provideKeys(ctx context.Context, r routing.Routing, cids []cid.Cid) error {
288 - for _, c := range cids {
289 - err := r.Provide(ctx, c, true)
290 - if err != nil {
291 - return err
292 - }
293 +func provideCids(prov node.DHTProvider, cids []cid.Cid) error {
294 + mhs := make([]mh.Multihash, len(cids))
295 + for i, c := range cids {
296 + mhs[i] = c.Hash()
297 }
294 - return nil
298 + return prov.StartProviding(true, mhs...)
299 }
300
297 -func provideKeysRec(ctx context.Context, r routing.Routing, dserv ipld.DAGService, cids []cid.Cid) error {
298 - provided := cid.NewSet()
301 +func provideCidsRec(ctx context.Context, prov node.DHTProvider, dserv ipld.DAGService, cids []cid.Cid) error {
302 for _, c := range cids {
303 kset := cid.NewSet()
301 -
304 err := dag.Walk(ctx, dag.GetLinksDirect(dserv), c, kset.Visit)
305 if err != nil {
306 return err
307 }
306 -
307 - for _, k := range kset.Keys() {
308 - if provided.Has(k) {
309 - continue
310 - }
311 -
312 - err = r.Provide(ctx, k, true)
313 - if err != nil {
314 - return err
315 - }
316 - provided.Add(k)
308 + if err = provideCids(prov, kset.Keys()); err != nil {
309 + return err
310 }
311 }
319 -
312 return nil
313 }
314
core/core.go
+21 -21
@@ -92,31 +92,31 @@ type IpfsNode struct {
92 RecordValidator record.Validator
93
94 // Online
95 - PeerHost p2phost.Host `optional:"true"` // the network host (server+client)
96 - Peering *peering.PeeringService `optional:"true"`
97 - Filters *ma.Filters `optional:"true"`
98 - Bootstrapper io.Closer `optional:"true"` // the periodic bootstrapper
99 - Routing irouting.ProvideManyRouter `optional:"true"` // the routing system. recommend ipfs-dht
100 - ContentDiscovery routing.ContentDiscovery `optional:"true"` // the discovery part of the routing system
101 - DNSResolver *madns.Resolver // the DNS resolver
102 - IPLDPathResolver pathresolver.Resolver `name:"ipldPathResolver"` // The IPLD path resolver
103 - UnixFSPathResolver pathresolver.Resolver `name:"unixFSPathResolver"` // The UnixFS path resolver
104 - OfflineIPLDPathResolver pathresolver.Resolver `name:"offlineIpldPathResolver"` // The IPLD path resolver that uses only locally available blocks
105 - OfflineUnixFSPathResolver pathresolver.Resolver `name:"offlineUnixFSPathResolver"` // The UnixFS path resolver that uses only locally available blocks
106 - Exchange exchange.Interface // the block exchange + strategy
107 - Bitswap *bitswap.Bitswap `optional:"true"` // The Bitswap instance
108 - Namesys namesys.NameSystem // the name system, resolves paths to hashes
109 - Provider provider.System // the value provider system
110 - ProvidingStrategy config.ReproviderStrategy `optional:"true"`
111 - ProvidingKeyChanFunc provider.KeyChanFunc `optional:"true"`
112 - IpnsRepub *ipnsrp.Republisher `optional:"true"`
113 - ResourceManager network.ResourceManager `optional:"true"`
95 + PeerHost p2phost.Host `optional:"true"` // the network host (server+client)
96 + Peering *peering.PeeringService `optional:"true"`
97 + Filters *ma.Filters `optional:"true"`
98 + Bootstrapper io.Closer `optional:"true"` // the periodic bootstrapper
99 + ContentDiscovery routing.ContentDiscovery `optional:"true"` // the discovery part of the routing system
100 + DNSResolver *madns.Resolver // the DNS resolver
101 + IPLDPathResolver pathresolver.Resolver `name:"ipldPathResolver"` // The IPLD path resolver
102 + UnixFSPathResolver pathresolver.Resolver `name:"unixFSPathResolver"` // The UnixFS path resolver
103 + OfflineIPLDPathResolver pathresolver.Resolver `name:"offlineIpldPathResolver"` // The IPLD path resolver that uses only locally available blocks
104 + OfflineUnixFSPathResolver pathresolver.Resolver `name:"offlineUnixFSPathResolver"` // The UnixFS path resolver that uses only locally available blocks
105 + Exchange exchange.Interface // the block exchange + strategy
106 + Bitswap *bitswap.Bitswap `optional:"true"` // The Bitswap instance
107 + Namesys namesys.NameSystem // the name system, resolves paths to hashes
108 + ProvidingStrategy config.ReproviderStrategy `optional:"true"`
109 + ProvidingKeyChanFunc provider.KeyChanFunc `optional:"true"`
110 + IpnsRepub *ipnsrp.Republisher `optional:"true"`
111 + ResourceManager network.ResourceManager `optional:"true"`
112
113 PubSub *pubsub.PubSub `optional:"true"`
114 PSRouter *psrouter.PubsubValueStore `optional:"true"`
115
118 - DHT *ddht.DHT `optional:"true"`
119 - DHTClient routing.Routing `name:"dhtc" optional:"true"`
116 + Routing irouting.ProvideManyRouter `optional:"true"` // the routing system. recommend ipfs-dht
117 + Provider node.DHTProvider // the value provider system
118 + DHT *ddht.DHT `optional:"true"`
119 + DHTClient routing.Routing `name:"dhtc" optional:"true"`
120
121 P2P *p2p.P2P `optional:"true"`
122
core/coreapi/coreapi.go
+1 -5
@@ -23,10 +23,8 @@ import (
23 dag "github.com/ipfs/boxo/ipld/merkledag"
24 pathresolver "github.com/ipfs/boxo/path/resolver"
25 pin "github.com/ipfs/boxo/pinning/pinner"
26 - provider "github.com/ipfs/boxo/provider"
26 offlineroute "github.com/ipfs/boxo/routing/offline"
27 ipld "github.com/ipfs/go-ipld-format"
29 - logging "github.com/ipfs/go-log/v2"
28 "github.com/ipfs/kubo/config"
29 coreiface "github.com/ipfs/kubo/core/coreiface"
30 "github.com/ipfs/kubo/core/coreiface/options"
@@ -45,8 +43,6 @@ import (
43 "github.com/ipfs/kubo/repo"
44 )
45
48 -var log = logging.Logger("coreapi")
49 -
46 type CoreAPI struct {
47 nctx context.Context
48
@@ -73,7 +69,7 @@ type CoreAPI struct {
69 ipldPathResolver pathresolver.Resolver
70 unixFSPathResolver pathresolver.Resolver
71
76 - provider provider.System
72 + provider node.DHTProvider
73 providingStrategy config.ReproviderStrategy
74
75 pubSub *pubsub.PubSub
core/coreapi/routing.go
+49 -25
@@ -15,9 +15,10 @@ import (
15 cidutil "github.com/ipfs/go-cidutil"
16 coreiface "github.com/ipfs/kubo/core/coreiface"
17 caopts "github.com/ipfs/kubo/core/coreiface/options"
18 + "github.com/ipfs/kubo/core/node"
19 "github.com/ipfs/kubo/tracing"
20 peer "github.com/libp2p/go-libp2p/core/peer"
20 - routing "github.com/libp2p/go-libp2p/core/routing"
21 + mh "github.com/multiformats/go-multihash"
22 "go.opentelemetry.io/otel/attribute"
23 "go.opentelemetry.io/otel/trace"
24 )
@@ -148,9 +149,9 @@ func (api *RoutingAPI) Provide(ctx context.Context, path path.Path, opts ...caop
149 }
150
151 if settings.Recursive {
151 - err = provideKeysRec(ctx, api.routing, api.blockstore, []cid.Cid{c})
152 + err = provideKeysRec(ctx, api.provider, api.blockstore, []cid.Cid{c})
153 } else {
153 - err = provideKeys(ctx, api.routing, []cid.Cid{c})
154 + err = api.provider.StartProviding(false, c.Hash())
155 }
156 if err != nil {
157 return err
@@ -159,41 +160,64 @@ func (api *RoutingAPI) Provide(ctx context.Context, path path.Path, opts ...caop
160 return nil
161 }
162
162 -func provideKeys(ctx context.Context, r routing.Routing, cids []cid.Cid) error {
163 - for _, c := range cids {
164 - err := r.Provide(ctx, c, true)
165 - if err != nil {
166 - return err
167 - }
168 - }
169 - return nil
170 -}
171 -
172 -func provideKeysRec(ctx context.Context, r routing.Routing, bs blockstore.Blockstore, cids []cid.Cid) error {
163 +func provideKeysRec(ctx context.Context, prov node.DHTProvider, bs blockstore.Blockstore, cids []cid.Cid) error {
164 provided := cidutil.NewStreamingSet()
165
175 - errCh := make(chan error)
166 + // Error channel with buffer size 1 to avoid blocking the goroutine
167 + errCh := make(chan error, 1)
168 go func() {
169 + // Always close provided.New to signal completion
170 + defer close(provided.New)
171 + // Also close error channel to distinguish between "no error" and "pending error"
172 + defer close(errCh)
173 +
174 dserv := dag.NewDAGService(blockservice.New(bs, offline.Exchange(bs)))
175 for _, c := range cids {
179 - err := dag.Walk(ctx, dag.GetLinksDirect(dserv), c, provided.Visitor(ctx))
180 - if err != nil {
181 - errCh <- err
176 + if err := dag.Walk(ctx, dag.GetLinksDirect(dserv), c, provided.Visitor(ctx)); err != nil {
177 + // Send error to channel. If context is cancelled while trying to send,
178 + // exit immediately as the main loop will return ctx.Err()
179 + select {
180 + case errCh <- err:
181 + // Error sent successfully, exit goroutine
182 + case <-ctx.Done():
183 + // Context cancelled, exit without sending error
184 + return
185 + }
186 + return
187 }
188 }
189 + // All CIDs walked successfully, goroutine will exit and channels will close
190 }()
191
192 + keys := make([]mh.Multihash, 0)
193 for {
194 select {
188 - case k := <-provided.New:
189 - err := r.Provide(ctx, k, true)
190 - if err != nil {
191 - return err
192 - }
193 - case err := <-errCh:
194 - return err
195 case <-ctx.Done():
196 + // Context cancelled, return immediately
197 return ctx.Err()
198 + case err := <-errCh:
199 + // Received error from DAG walk, return it
200 + return err
201 + case c, ok := <-provided.New:
202 + if !ok {
203 + // Channel closed means goroutine finished.
204 + // CRITICAL: Check for any error that was sent just before channel closure.
205 + // This handles the race where error is sent to errCh but main loop
206 + // sees provided.New close first.
207 + select {
208 + case err := <-errCh:
209 + if err != nil {
210 + return err
211 + }
212 + // errCh closed with nil, meaning success
213 + default:
214 + // No pending error in errCh
215 + }
216 + // All CIDs successfully processed, start providing
217 + return prov.StartProviding(true, keys...)
218 + }
219 + // Accumulate the CID for providing
220 + keys = append(keys, c.Hash())
221 }
222 }
223 }
core/coreapi/unixfs.go
+14 -11
@@ -16,21 +16,25 @@ import (
16 uio "github.com/ipfs/boxo/ipld/unixfs/io"
17 "github.com/ipfs/boxo/mfs"
18 "github.com/ipfs/boxo/path"
19 - provider "github.com/ipfs/boxo/provider"
19 + "github.com/ipfs/boxo/provider"
20 cid "github.com/ipfs/go-cid"
21 cidutil "github.com/ipfs/go-cidutil"
22 ds "github.com/ipfs/go-datastore"
23 dssync "github.com/ipfs/go-datastore/sync"
24 ipld "github.com/ipfs/go-ipld-format"
25 + logging "github.com/ipfs/go-log/v2"
26 "github.com/ipfs/kubo/config"
27 coreiface "github.com/ipfs/kubo/core/coreiface"
28 options "github.com/ipfs/kubo/core/coreiface/options"
29 "github.com/ipfs/kubo/core/coreunix"
30 "github.com/ipfs/kubo/tracing"
31 + mh "github.com/multiformats/go-multihash"
32 "go.opentelemetry.io/otel/attribute"
33 "go.opentelemetry.io/otel/trace"
34 )
35
36 +var log = logging.Logger("coreapi")
37 +
38 type UnixfsAPI CoreAPI
39
40 // Add builds a merkledag node from a reader, adds it to the blockstore,
@@ -386,7 +390,7 @@ func (s *syncDagService) Sync() error {
390
391 type providingDagService struct {
392 ipld.DAGService
389 - provider provider.System
393 + provider.MultihashProvider
394 }
395
396 func (pds *providingDagService) Add(ctx context.Context, n ipld.Node) error {
@@ -397,8 +401,8 @@ func (pds *providingDagService) Add(ctx context.Context, n ipld.Node) error {
401 // We don't want DAG operations to fail due to providing issues.
402 // The user's data is still stored successfully even if the
403 // announcement to the routing system fails temporarily.
400 - if err := pds.provider.Provide(ctx, n.Cid(), true); err != nil {
401 - log.Error(err)
404 + if err := pds.StartProviding(false, n.Cid().Hash()); err != nil {
405 + log.Errorf("failed to provide new block: %s", err)
406 }
407 return nil
408 }
@@ -407,14 +411,13 @@ func (pds *providingDagService) AddMany(ctx context.Context, nds []ipld.Node) er
411 if err := pds.DAGService.AddMany(ctx, nds); err != nil {
412 return err
413 }
414 + keys := make([]mh.Multihash, len(nds))
415 + for i, n := range nds {
416 + keys[i] = n.Cid().Hash()
417 + }
418 // Same error handling philosophy as Add(): log but don't fail.
411 - // Note: Provide calls are intentionally blocking here - the Provider
412 - // implementation should handle concurrency/queuing internally.
413 - for _, n := range nds {
414 - if err := pds.provider.Provide(ctx, n.Cid(), true); err != nil {
415 - log.Error(err)
416 - break
417 - }
419 + if err := pds.StartProviding(false, keys...); err != nil {
420 + log.Errorf("failed to provide new blocks: %s", err)
421 }
422 return nil
423 }
core/node/core.go
+11 -11
@@ -18,7 +18,6 @@ import (
18 pathresolver "github.com/ipfs/boxo/path/resolver"
19 pin "github.com/ipfs/boxo/pinning/pinner"
20 "github.com/ipfs/boxo/pinning/pinner/dspinner"
21 - provider "github.com/ipfs/boxo/provider"
21 "github.com/ipfs/go-cid"
22 "github.com/ipfs/go-datastore"
23 format "github.com/ipfs/go-ipld-format"
@@ -49,7 +48,7 @@ func BlockService(cfg *config.Config) func(lc fx.Lifecycle, bs blockstore.Blocks
48 }
49
50 // Pinning creates new pinner which tells GC which blocks should be kept
52 -func Pinning(strategy string) func(bstore blockstore.Blockstore, ds format.DAGService, repo repo.Repo, prov provider.System) (pin.Pinner, error) {
51 +func Pinning(strategy string) func(bstore blockstore.Blockstore, ds format.DAGService, repo repo.Repo, prov DHTProvider) (pin.Pinner, error) {
52 // Parse strategy at function creation time (not inside the returned function)
53 // This happens before the provider is created, which is why we pass the strategy
54 // string and parse it here, rather than using fx-provided ProvidingStrategy.
@@ -58,7 +57,8 @@ func Pinning(strategy string) func(bstore blockstore.Blockstore, ds format.DAGSe
57 return func(bstore blockstore.Blockstore,
58 ds format.DAGService,
59 repo repo.Repo,
61 - prov provider.System) (pin.Pinner, error) {
60 + prov DHTProvider,
61 + ) (pin.Pinner, error) {
62 rootDS := repo.Datastore()
63
64 syncFn := func(ctx context.Context) error {
@@ -179,8 +179,8 @@ func Dag(bs blockservice.BlockService) format.DAGService {
179 }
180
181 // Files loads persisted MFS root
182 -func Files(strategy string) func(mctx helpers.MetricsCtx, lc fx.Lifecycle, repo repo.Repo, dag format.DAGService, bs blockstore.Blockstore, prov provider.System) (*mfs.Root, error) {
183 - return func(mctx helpers.MetricsCtx, lc fx.Lifecycle, repo repo.Repo, dag format.DAGService, bs blockstore.Blockstore, prov provider.System) (*mfs.Root, error) {
182 +func Files(strategy string) func(mctx helpers.MetricsCtx, lc fx.Lifecycle, repo repo.Repo, dag format.DAGService, bs blockstore.Blockstore, prov DHTProvider) (*mfs.Root, error) {
183 + return func(mctx helpers.MetricsCtx, lc fx.Lifecycle, repo repo.Repo, dag format.DAGService, bs blockstore.Blockstore, prov DHTProvider) (*mfs.Root, error) {
184 dsk := datastore.NewKey("/local/filesroot")
185 pf := func(ctx context.Context, c cid.Cid) error {
186 rootDS := repo.Datastore()
@@ -230,12 +230,12 @@ func Files(strategy string) func(mctx helpers.MetricsCtx, lc fx.Lifecycle, repo
230 return nil, err
231 }
232
233 - // MFS (Mutable File System) provider integration:
234 - // Only pass the provider to MFS when the strategy includes "mfs".
235 - // MFS will call Provide() on every DAGService.Add() operation,
236 - // which is sufficient for the "mfs" strategy - it ensures all
237 - // MFS content gets announced as it's added or modified.
238 - // For non-mfs strategies, we set provider to nil to avoid unnecessary providing.
233 + // MFS (Mutable File System) provider integration: Only pass the provider
234 + // to MFS when the strategy includes "mfs". MFS will call StartProviding()
235 + // on every DAGService.Add() operation, which is sufficient for the "mfs"
236 + // strategy - it ensures all MFS content gets announced as it's added or
237 + // modified. For non-mfs strategies, we set provider to nil to avoid
238 + // unnecessary providing.
239 strategyFlag := config.ParseReproviderStrategy(strategy)
240 if strategyFlag&config.ReproviderStrategyMFS == 0 {
241 prov = nil
core/node/groups.go
+1 -7
@@ -365,13 +365,7 @@ func Online(bcfg *BuildCfg, cfg *config.Config, userResourceOverrides rcmgr.Part
365 fx.Provide(p2p.New),
366
367 LibP2P(bcfg, cfg, userResourceOverrides),
368 - OnlineProviders(
369 - isProviderEnabled,
370 - cfg.Reprovider.Strategy.WithDefault(config.DefaultReproviderStrategy),
371 - cfg.Reprovider.Interval.WithDefault(config.DefaultReproviderInterval),
372 - cfg.Routing.AcceleratedDHTClient.WithDefault(config.DefaultAcceleratedDHTClient),
373 - int(cfg.Provider.WorkerCount.WithDefault(config.DefaultProviderWorkerCount)),
374 - ),
368 + OnlineProviders(isProviderEnabled, cfg),
369 )
370 }
371
core/node/provider.go
+425 -90
@@ -11,13 +11,28 @@ import (
11 "github.com/ipfs/boxo/mfs"
12 pin "github.com/ipfs/boxo/pinning/pinner"
13 "github.com/ipfs/boxo/pinning/pinner/dspinner"
14 - provider "github.com/ipfs/boxo/provider"
14 + "github.com/ipfs/boxo/provider"
15 "github.com/ipfs/go-cid"
16 "github.com/ipfs/go-datastore"
17 "github.com/ipfs/go-datastore/query"
18 "github.com/ipfs/kubo/config"
19 "github.com/ipfs/kubo/repo"
20 irouting "github.com/ipfs/kubo/routing"
21 + dht "github.com/libp2p/go-libp2p-kad-dht"
22 + "github.com/libp2p/go-libp2p-kad-dht/amino"
23 + "github.com/libp2p/go-libp2p-kad-dht/dual"
24 + "github.com/libp2p/go-libp2p-kad-dht/fullrt"
25 + dht_pb "github.com/libp2p/go-libp2p-kad-dht/pb"
26 + dhtprovider "github.com/libp2p/go-libp2p-kad-dht/provider"
27 + "github.com/libp2p/go-libp2p-kad-dht/provider/buffered"
28 + ddhtprovider "github.com/libp2p/go-libp2p-kad-dht/provider/dual"
29 + "github.com/libp2p/go-libp2p-kad-dht/provider/keystore"
30 + routinghelpers "github.com/libp2p/go-libp2p-routing-helpers"
31 + "github.com/libp2p/go-libp2p/core/host"
32 + peer "github.com/libp2p/go-libp2p/core/peer"
33 + "github.com/libp2p/go-libp2p/core/routing"
34 + ma "github.com/multiformats/go-multiaddr"
35 + mh "github.com/multiformats/go-multihash"
36 "go.uber.org/fx"
37 )
38
@@ -29,59 +44,163 @@ const sampledBatchSize = 1000
44 // Datastore key used to store previous reprovide strategy.
45 const reprovideStrategyKey = "/reprovideStrategy"
46
32 -func ProviderSys(reprovideInterval time.Duration, acceleratedDHTClient bool, provideWorkerCount int) fx.Option {
33 - return fx.Provide(func(lc fx.Lifecycle, cr irouting.ProvideManyRouter, repo repo.Repo) (provider.System, error) {
34 - // Initialize provider.System first, before pinner/blockstore/etc.
35 - // The KeyChanFunc will be set later via SetKeyProvider() once we have
36 - // created the pinner, blockstore and other dependencies.
37 - opts := []provider.Option{
38 - provider.Online(cr),
39 - provider.ReproviderInterval(reprovideInterval),
40 - provider.ProvideWorkerCount(provideWorkerCount),
47 +// DHTProvider is an interface for providing keys to a DHT swarm. It holds a
48 +// state of keys to be advertised, and is responsible for periodically
49 +// publishing provider records for these keys to the DHT swarm before the
50 +// records expire.
51 +type DHTProvider interface {
52 + // StartProviding ensures keys are periodically advertised to the DHT swarm.
53 + //
54 + // If the `keys` aren't currently being reprovided, they are added to the
55 + // queue to be provided to the DHT swarm as soon as possible, and scheduled
56 + // to be reprovided periodically. If `force` is set to true, all keys are
57 + // provided to the DHT swarm, regardless of whether they were already being
58 + // reprovided in the past. `keys` keep being reprovided until `StopProviding`
59 + // is called.
60 + //
61 + // This operation is asynchronous, it returns as soon as the `keys` are added
62 + // to the provide queue, and provides happens asynchronously.
63 + //
64 + // Returns an error if the keys couldn't be added to the provide queue. This
65 + // can happen if the provider is closed or if the node is currently Offline
66 + // (either never bootstrapped, or disconnected since more than `OfflineDelay`).
67 + // The schedule and provide queue depend on the network size, hence recent
68 + // network connectivity is essential.
69 + StartProviding(force bool, keys ...mh.Multihash) error
70 + // ProvideOnce sends provider records for the specified keys to the DHT swarm
71 + // only once. It does not automatically reprovide those keys afterward.
72 + //
73 + // Add the supplied multihashes to the provide queue, and return immediately.
74 + // The provide operation happens asynchronously.
75 + //
76 + // Returns an error if the keys couldn't be added to the provide queue. This
77 + // can happen if the provider is closed or if the node is currently Offline
78 + // (either never bootstrapped, or disconnected since more than `OfflineDelay`).
79 + // The schedule and provide queue depend on the network size, hence recent
80 + // network connectivity is essential.
81 + ProvideOnce(keys ...mh.Multihash) error
82 + // Clear clears the all the keys from the provide queue and returns the number
83 + // of keys that were cleared.
84 + //
85 + // The keys are not deleted from the keystore, so they will continue to be
86 + // reprovided as scheduled.
87 + Clear() int
88 + // RefreshSchedule scans the Keystore for any keys that are not currently
89 + // scheduled for reproviding. If such keys are found, it schedules their
90 + // associated keyspace region to be reprovided.
91 + //
92 + // This function doesn't remove prefixes that have no keys from the schedule.
93 + // This is done automatically during the reprovide operation if a region has no
94 + // keys.
95 + //
96 + // Returns an error if the provider is closed or if the node is currently
97 + // Offline (either never bootstrapped, or disconnected since more than
98 + // `OfflineDelay`). The schedule depends on the network size, hence recent
99 + // network connectivity is essential.
100 + RefreshSchedule() error
101 +}
102 +
103 +var (
104 + _ DHTProvider = &ddhtprovider.SweepingProvider{}
105 + _ DHTProvider = &dhtprovider.SweepingProvider{}
106 + _ DHTProvider = &NoopProvider{}
107 + _ DHTProvider = &LegacyProvider{}
108 +)
109 +
110 +type NoopProvider struct{}
111 +
112 +func (r *NoopProvider) StartProviding(bool, ...mh.Multihash) error { return nil }
113 +func (r *NoopProvider) ProvideOnce(...mh.Multihash) error { return nil }
114 +func (r *NoopProvider) Clear() int { return 0 }
115 +func (r *NoopProvider) RefreshSchedule() error { return nil }
116 +
117 +// LegacyProvider is a wrapper around the boxo/provider.System. This DHT
118 +// provide system manages reprovides by bursts where it sequentially reprovides
119 +// all keys.
120 +type LegacyProvider struct {
121 + provider.System
122 +}
123 +
124 +func (r *LegacyProvider) StartProviding(force bool, keys ...mh.Multihash) error {
125 + return r.ProvideOnce(keys...)
126 +}
127 +
128 +func (r *LegacyProvider) ProvideOnce(keys ...mh.Multihash) error {
129 + if many, ok := r.System.(routinghelpers.ProvideManyRouter); ok {
130 + return many.ProvideMany(context.Background(), keys)
131 + }
132 +
133 + for _, k := range keys {
134 + if err := r.Provide(context.Background(), cid.NewCidV1(cid.Raw, k), true); err != nil {
135 + return err
136 }
42 - if !acceleratedDHTClient && reprovideInterval > 0 {
43 - // The estimation kinda suck if you are running with accelerated DHT client,
44 - // given this message is just trying to push people to use the acceleratedDHTClient
45 - // let's not report on through if it's in use
46 - opts = append(opts,
47 - provider.ThroughputReport(func(reprovide bool, complete bool, keysProvided uint, duration time.Duration) bool {
48 - avgProvideSpeed := duration / time.Duration(keysProvided)
49 - count := uint64(keysProvided)
50 -
51 - if !reprovide || !complete {
52 - // We don't know how many CIDs we have to provide, try to fetch it from the blockstore.
53 - // But don't try for too long as this might be very expensive if you have a huge datastore.
54 - ctx, cancel := context.WithTimeout(context.Background(), time.Minute*5)
55 - defer cancel()
56 -
57 - // FIXME: I want a running counter of blocks so size of blockstore can be an O(1) lookup.
58 - // Note: talk to datastore directly, as to not depend on Blockstore here.
59 - qr, err := repo.Datastore().Query(ctx, query.Query{
60 - Prefix: blockstore.BlockPrefix.String(),
61 - KeysOnly: true})
62 - if err != nil {
63 - logger.Errorf("fetching AllKeysChain in provider ThroughputReport: %v", err)
64 - return false
65 - }
66 - defer qr.Close()
67 - count = 0
68 - countLoop:
69 - for {
70 - select {
71 - case _, ok := <-qr.Next():
72 - if !ok {
73 - break countLoop
74 - }
75 - count++
76 - case <-ctx.Done():
77 - // really big blockstore mode
78 -
79 - // how many blocks would be in a 10TiB blockstore with 128KiB blocks.
80 - const probableBigBlockstore = (10 * 1024 * 1024 * 1024 * 1024) / (128 * 1024)
81 - // How long per block that lasts us.
82 - expectedProvideSpeed := reprovideInterval / probableBigBlockstore
83 - if avgProvideSpeed > expectedProvideSpeed {
84 - logger.Errorf(`
137 + }
138 + return nil
139 +}
140 +
141 +func (r *LegacyProvider) Clear() int {
142 + return r.System.Clear()
143 +}
144 +
145 +func (r *LegacyProvider) RefreshSchedule() error { return nil }
146 +
147 +// LegacyProviderOpt creates a LegacyProvider to be used as provider in the
148 +// IpfsNode
149 +func LegacyProviderOpt(reprovideInterval time.Duration, strategy string, acceleratedDHTClient bool, provideWorkerCount int) fx.Option {
150 + system := fx.Provide(
151 + fx.Annotate(func(lc fx.Lifecycle, cr irouting.ProvideManyRouter, repo repo.Repo) (*LegacyProvider, error) {
152 + // Initialize provider.System first, before pinner/blockstore/etc.
153 + // The KeyChanFunc will be set later via SetKeyProvider() once we have
154 + // created the pinner, blockstore and other dependencies.
155 + opts := []provider.Option{
156 + provider.Online(cr),
157 + provider.ReproviderInterval(reprovideInterval),
158 + provider.ProvideWorkerCount(provideWorkerCount),
159 + }
160 + if !acceleratedDHTClient && reprovideInterval > 0 {
161 + // The estimation kinda suck if you are running with accelerated DHT client,
162 + // given this message is just trying to push people to use the acceleratedDHTClient
163 + // let's not report on through if it's in use
164 + opts = append(opts,
165 + provider.ThroughputReport(func(reprovide bool, complete bool, keysProvided uint, duration time.Duration) bool {
166 + avgProvideSpeed := duration / time.Duration(keysProvided)
167 + count := uint64(keysProvided)
168 +
169 + if !reprovide || !complete {
170 + // We don't know how many CIDs we have to provide, try to fetch it from the blockstore.
171 + // But don't try for too long as this might be very expensive if you have a huge datastore.
172 + ctx, cancel := context.WithTimeout(context.Background(), time.Minute*5)
173 + defer cancel()
174 +
175 + // FIXME: I want a running counter of blocks so size of blockstore can be an O(1) lookup.
176 + // Note: talk to datastore directly, as to not depend on Blockstore here.
177 + qr, err := repo.Datastore().Query(ctx, query.Query{
178 + Prefix: blockstore.BlockPrefix.String(),
179 + KeysOnly: true,
180 + })
181 + if err != nil {
182 + logger.Errorf("fetching AllKeysChain in provider ThroughputReport: %v", err)
183 + return false
184 + }
185 + defer qr.Close()
186 + count = 0
187 + countLoop:
188 + for {
189 + select {
190 + case _, ok := <-qr.Next():
191 + if !ok {
192 + break countLoop
193 + }
194 + count++
195 + case <-ctx.Done():
196 + // really big blockstore mode
197 +
198 + // how many blocks would be in a 10TiB blockstore with 128KiB blocks.
199 + const probableBigBlockstore = (10 * 1024 * 1024 * 1024 * 1024) / (128 * 1024)
200 + // How long per block that lasts us.
201 + expectedProvideSpeed := reprovideInterval / probableBigBlockstore
202 + if avgProvideSpeed > expectedProvideSpeed {
203 + logger.Errorf(`
204 🔔🔔🔔 YOU MAY BE FALLING BEHIND DHT REPROVIDES! 🔔🔔🔔
205
206 ⚠️ Your system might be struggling to keep up with DHT reprovides!
@@ -96,21 +215,21 @@ size of 10TiB, it would take %v to provide the complete set.
215
216 💡 Consider enabling the Accelerated DHT to enhance your system performance. See:
217 https://github.com/ipfs/kubo/blob/master/docs/config.md#routingaccelerateddhtclient`,
99 - keysProvided, avgProvideSpeed, avgProvideSpeed*probableBigBlockstore, reprovideInterval)
100 - return false
218 + keysProvided, avgProvideSpeed, avgProvideSpeed*probableBigBlockstore, reprovideInterval)
219 + return false
220 + }
221 }
222 }
223 }
104 - }
224
106 - // How long per block that lasts us.
107 - expectedProvideSpeed := reprovideInterval
108 - if count > 0 {
109 - expectedProvideSpeed = reprovideInterval / time.Duration(count)
110 - }
225 + // How long per block that lasts us.
226 + expectedProvideSpeed := reprovideInterval
227 + if count > 0 {
228 + expectedProvideSpeed = reprovideInterval / time.Duration(count)
229 + }
230
112 - if avgProvideSpeed > expectedProvideSpeed {
113 - logger.Errorf(`
231 + if avgProvideSpeed > expectedProvideSpeed {
232 + logger.Errorf(`
233 🔔🔔🔔 YOU ARE FALLING BEHIND DHT REPROVIDES! 🔔🔔🔔
234
235 ⚠️ Your system is struggling to keep up with DHT reprovides!
@@ -123,49 +242,277 @@ We observed that you recently provided %d keys at an average rate of %v per key.
242
243 💡 Consider enabling the Accelerated DHT to enhance your reprovide throughput. See:
244 https://github.com/ipfs/kubo/blob/master/docs/config.md#routingaccelerateddhtclient`,
126 - keysProvided, avgProvideSpeed, count, avgProvideSpeed*time.Duration(count), reprovideInterval)
127 - }
128 - return false
129 - }, sampledBatchSize))
245 + keysProvided, avgProvideSpeed, count, avgProvideSpeed*time.Duration(count), reprovideInterval)
246 + }
247 + return false
248 + }, sampledBatchSize))
249 + }
250 +
251 + sys, err := provider.New(repo.Datastore(), opts...)
252 + if err != nil {
253 + return nil, err
254 + }
255 + lc.Append(fx.Hook{
256 + OnStop: func(ctx context.Context) error {
257 + return sys.Close()
258 + },
259 + })
260 +
261 + prov := &LegacyProvider{sys}
262 + handleStrategyChange(strategy, prov, repo.Datastore())
263 +
264 + return prov, nil
265 + },
266 + fx.As(new(provider.System)),
267 + fx.As(new(DHTProvider)),
268 + ),
269 + )
270 + setKeyProvider := fx.Invoke(func(lc fx.Lifecycle, system provider.System, keyProvider provider.KeyChanFunc) {
271 + lc.Append(fx.Hook{
272 + OnStart: func(ctx context.Context) error {
273 + // SetKeyProvider breaks the circular dependency between provider, blockstore, and pinner.
274 + // We cannot create the blockstore without the provider (it needs to provide blocks),
275 + // and we cannot determine the reproviding strategy without the pinner/blockstore.
276 + // This deferred initialization allows us to create provider.System first,
277 + // then set the actual key provider function after all dependencies are ready.
278 + system.SetKeyProvider(keyProvider)
279 + return nil
280 + },
281 + })
282 + })
283 + return fx.Options(
284 + system,
285 + setKeyProvider,
286 + )
287 +}
288 +
289 +type dhtImpl interface {
290 + routing.Routing
291 + GetClosestPeers(context.Context, string) ([]peer.ID, error)
292 + Host() host.Host
293 + MessageSender() dht_pb.MessageSender
294 +}
295 +type addrsFilter interface {
296 + FilteredAddrs() []ma.Multiaddr
297 +}
298 +
299 +func SweepingProviderOpt(cfg *config.Config) fx.Option {
300 + reprovideInterval := cfg.Reprovider.Interval.WithDefault(config.DefaultReproviderInterval)
301 + type providerInput struct {
302 + fx.In
303 + DHT routing.Routing `name:"dhtc"`
304 + Repo repo.Repo
305 + }
306 + sweepingReprovider := fx.Provide(func(in providerInput) (DHTProvider, *keystore.ResettableKeystore, error) {
307 + ds := in.Repo.Datastore()
308 + ks, err := keystore.NewResettableKeystore(ds,
309 + keystore.WithPrefixBits(16),
310 + keystore.WithDatastorePath("/provider/keystore"),
311 + keystore.WithBatchSize(int(cfg.Reprovider.Sweep.KeyStoreBatchSize.WithDefault(config.DefaultReproviderSweepKeyStoreBatchSize))),
312 + )
313 + if err != nil {
314 + return &NoopProvider{}, nil, err
315 + }
316 +
317 + bufferedProviderOpts := []buffered.Option{
318 + buffered.WithBatchSize(1 << 10),
319 + buffered.WithDsName("bprov"),
320 + buffered.WithIdleWriteTime(time.Minute),
321 + }
322 +
323 + var impl dhtImpl
324 + switch inDht := in.DHT.(type) {
325 + case *dht.IpfsDHT:
326 + if inDht != nil {
327 + impl = inDht
328 + }
329 + case *dual.DHT:
330 + if inDht != nil {
331 + prov, err := ddhtprovider.New(inDht,
332 + ddhtprovider.WithKeystore(ks),
333 +
334 + ddhtprovider.WithReprovideInterval(reprovideInterval),
335 + ddhtprovider.WithMaxReprovideDelay(time.Hour),
336 + ddhtprovider.WithOfflineDelay(cfg.Reprovider.Sweep.OfflineDelay.WithDefault(config.DefaultReproviderSweepOfflineDelay)),
337 + ddhtprovider.WithConnectivityCheckOnlineInterval(1*time.Minute),
338 +
339 + ddhtprovider.WithMaxWorkers(int(cfg.Reprovider.Sweep.MaxWorkers.WithDefault(config.DefaultReproviderSweepMaxWorkers))),
340 + ddhtprovider.WithDedicatedPeriodicWorkers(int(cfg.Reprovider.Sweep.DedicatedPeriodicWorkers.WithDefault(config.DefaultReproviderSweepDedicatedPeriodicWorkers))),
341 + ddhtprovider.WithDedicatedBurstWorkers(int(cfg.Reprovider.Sweep.DedicatedBurstWorkers.WithDefault(config.DefaultReproviderSweepDedicatedBurstWorkers))),
342 + ddhtprovider.WithMaxProvideConnsPerWorker(int(cfg.Reprovider.Sweep.MaxProvideConnsPerWorker.WithDefault(config.DefaultReproviderSweepMaxProvideConnsPerWorker))),
343 + )
344 + if err != nil {
345 + return nil, nil, err
346 + }
347 + return buffered.New(prov, ds, bufferedProviderOpts...), ks, nil
348 + }
349 + case *fullrt.FullRT:
350 + if inDht != nil {
351 + impl = inDht
352 + }
353 + }
354 + if impl == nil {
355 + return &NoopProvider{}, nil, nil
356 }
357
132 - sys, err := provider.New(repo.Datastore(), opts...)
358 + var selfAddrsFunc func() []ma.Multiaddr
359 + if imlpFilter, ok := impl.(addrsFilter); ok {
360 + selfAddrsFunc = imlpFilter.FilteredAddrs
361 + } else {
362 + selfAddrsFunc = func() []ma.Multiaddr { return impl.Host().Addrs() }
363 + }
364 + opts := []dhtprovider.Option{
365 + dhtprovider.WithKeystore(ks),
366 + dhtprovider.WithPeerID(impl.Host().ID()),
367 + dhtprovider.WithRouter(impl),
368 + dhtprovider.WithMessageSender(impl.MessageSender()),
369 + dhtprovider.WithSelfAddrs(selfAddrsFunc),
370 + dhtprovider.WithAddLocalRecord(func(h mh.Multihash) error {
371 + return impl.Provide(context.Background(), cid.NewCidV1(cid.Raw, h), false)
372 + }),
373 +
374 + dhtprovider.WithReplicationFactor(amino.DefaultBucketSize),
375 + dhtprovider.WithReprovideInterval(reprovideInterval),
376 + dhtprovider.WithMaxReprovideDelay(time.Hour),
377 + dhtprovider.WithOfflineDelay(cfg.Reprovider.Sweep.OfflineDelay.WithDefault(config.DefaultReproviderSweepOfflineDelay)),
378 + dhtprovider.WithConnectivityCheckOnlineInterval(1 * time.Minute),
379 +
380 + dhtprovider.WithMaxWorkers(int(cfg.Reprovider.Sweep.MaxWorkers.WithDefault(config.DefaultReproviderSweepMaxWorkers))),
381 + dhtprovider.WithDedicatedPeriodicWorkers(int(cfg.Reprovider.Sweep.DedicatedPeriodicWorkers.WithDefault(config.DefaultReproviderSweepDedicatedPeriodicWorkers))),
382 + dhtprovider.WithDedicatedBurstWorkers(int(cfg.Reprovider.Sweep.DedicatedBurstWorkers.WithDefault(config.DefaultReproviderSweepDedicatedBurstWorkers))),
383 + dhtprovider.WithMaxProvideConnsPerWorker(int(cfg.Reprovider.Sweep.MaxProvideConnsPerWorker.WithDefault(config.DefaultReproviderSweepMaxProvideConnsPerWorker))),
384 + }
385 +
386 + prov, err := dhtprovider.New(opts...)
387 if err != nil {
134 - return nil, err
388 + return &NoopProvider{}, nil, err
389 + }
390 + return buffered.New(prov, ds, bufferedProviderOpts...), ks, nil
391 + })
392 +
393 + type keystoreInput struct {
394 + fx.In
395 + Provider DHTProvider
396 + Keystore *keystore.ResettableKeystore
397 + KeyProvider provider.KeyChanFunc
398 + }
399 + initKeystore := fx.Invoke(func(lc fx.Lifecycle, in keystoreInput) {
400 + var (
401 + cancel context.CancelFunc
402 + done = make(chan struct{})
403 + )
404 +
405 + syncKeystore := func(ctx context.Context) error {
406 + kcf, err := in.KeyProvider(ctx)
407 + if err != nil {
408 + return err
409 + }
410 + if err := in.Keystore.ResetCids(ctx, kcf); err != nil {
411 + return err
412 + }
413 + if err := in.Provider.RefreshSchedule(); err != nil {
414 + logger.Infow("refreshing provider schedule", "err", err)
415 + }
416 + return nil
417 }
418
419 lc.Append(fx.Hook{
420 + OnStart: func(ctx context.Context) error {
421 + if in.Provider == nil || in.Keystore == nil {
422 + return nil
423 + }
424 + // Set the KeyProvider as a garbage collection function for the
425 + // keystore. Periodically purge the Keystore from all its keys and
426 + // replace them with the keys that needs to be reprovided, coming from
427 + // the KeyChanFunc. So far, this is the less worse way to remove CIDs
428 + // that shouldn't be reprovided from the provider's state.
429 + if err := syncKeystore(ctx); err != nil {
430 + return err
431 + }
432 +
433 + gcCtx, c := context.WithCancel(context.Background())
434 + cancel = c
435 +
436 + go func() { // garbage collection loop for cids to reprovide
437 + defer close(done)
438 + ticker := time.NewTicker(reprovideInterval)
439 + defer ticker.Stop()
440 +
441 + for {
442 + select {
443 + case <-gcCtx.Done():
444 + return
445 + case <-ticker.C:
446 + if err := syncKeystore(gcCtx); err != nil {
447 + logger.Errorw("provider keystore sync", "err", err)
448 + }
449 + }
450 + }
451 + }()
452 + return nil
453 + },
454 OnStop: func(ctx context.Context) error {
139 - return sys.Close()
455 + if in.Provider == nil || in.Keystore == nil {
456 + return nil
457 + }
458 + if cancel != nil {
459 + // Cancel Keystore garbage collection loop
460 + cancel()
461 + }
462 + select {
463 + case <-done:
464 + case <-ctx.Done():
465 + return ctx.Err()
466 + }
467 +
468 + // Keystore state isn't be persisted across restarts.
469 + return in.Keystore.Empty(ctx)
470 },
471 })
142 -
143 - return sys, nil
472 })
473 +
474 + return fx.Options(
475 + sweepingReprovider,
476 + initKeystore,
477 + )
478 }
479
480 // ONLINE/OFFLINE
481
482 // OnlineProviders groups units managing provider routing records online
150 -func OnlineProviders(provide bool, providerStrategy string, reprovideInterval time.Duration, acceleratedDHTClient bool, provideWorkerCount int) fx.Option {
483 +func OnlineProviders(provide bool, cfg *config.Config) fx.Option {
484 if !provide {
485 return OfflineProviders()
486 }
487
488 + providerStrategy := cfg.Reprovider.Strategy.WithDefault(config.DefaultReproviderStrategy)
489 +
490 strategyFlag := config.ParseReproviderStrategy(providerStrategy)
491 if strategyFlag == 0 {
492 return fx.Error(fmt.Errorf("unknown reprovider strategy %q", providerStrategy))
493 }
494
160 - return fx.Options(
495 + opts := []fx.Option{
496 fx.Provide(setReproviderKeyProvider(providerStrategy)),
162 - ProviderSys(reprovideInterval, acceleratedDHTClient, provideWorkerCount),
163 - )
497 + }
498 + if cfg.Reprovider.Sweep.Enabled.WithDefault(config.DefaultReproviderSweepEnabled) {
499 + opts = append(opts, SweepingProviderOpt(cfg))
500 + } else {
501 + reprovideInterval := cfg.Reprovider.Interval.WithDefault(config.DefaultReproviderInterval)
502 + acceleratedDHTClient := cfg.Routing.AcceleratedDHTClient.WithDefault(config.DefaultAcceleratedDHTClient)
503 + provideWorkerCount := int(cfg.Provider.WorkerCount.WithDefault(config.DefaultProviderWorkerCount))
504 +
505 + opts = append(opts, LegacyProviderOpt(reprovideInterval, providerStrategy, acceleratedDHTClient, provideWorkerCount))
506 + }
507 +
508 + return fx.Options(opts...)
509 }
510
511 // OfflineProviders groups units managing provider routing records offline
512 func OfflineProviders() fx.Option {
168 - return fx.Provide(provider.NewNoopProvider)
513 + return fx.Provide(func() DHTProvider {
514 + return &NoopProvider{}
515 + })
516 }
517
518 func mfsProvider(mfsRoot *mfs.Root, fetcher fetcher.Factory) provider.KeyChanFunc {
@@ -191,7 +538,6 @@ type provStrategyIn struct {
538 OfflineIPLDFetcher fetcher.Factory `name:"offlineIpldFetcher"`
539 OfflineUnixFSFetcher fetcher.Factory `name:"offlineUnixfsFetcher"`
540 MFSRoot *mfs.Root
194 - Provider provider.System
541 Repo repo.Repo
542 }
543
@@ -257,7 +603,7 @@ func persistStrategy(ctx context.Context, strategy string, ds datastore.Datastor
603 // Strategy change detection: when the reproviding strategy changes,
604 // we clear the provide queue to avoid unexpected behavior from mixing
605 // strategies. This ensures a clean transition between different providing modes.
260 -func handleStrategyChange(strategy string, provider provider.System, ds datastore.Datastore) {
606 +func handleStrategyChange(strategy string, provider DHTProvider, ds datastore.Datastore) {
607 ctx := context.Background()
608
609 previous, changed, err := detectStrategyChange(ctx, strategy, ds)
@@ -284,17 +630,6 @@ func setReproviderKeyProvider(strategy string) func(in provStrategyIn) provStrat
630 return func(in provStrategyIn) provStrategyOut {
631 // Create the appropriate key provider based on strategy
632 kcf := createKeyProvider(strategyFlag, in)
287 -
288 - // SetKeyProvider breaks the circular dependency between provider, blockstore, and pinner.
289 - // We cannot create the blockstore without the provider (it needs to provide blocks),
290 - // and we cannot determine the reproviding strategy without the pinner/blockstore.
291 - // This deferred initialization allows us to create provider.System first,
292 - // then set the actual key provider function after all dependencies are ready.
293 - in.Provider.SetKeyProvider(kcf)
294 -
295 - // Handle strategy changes (detection, queue clearing, persistence)
296 - handleStrategyChange(strategy, in.Provider, in.Repo.Datastore())
297 -
633 return provStrategyOut{
634 ProvidingStrategy: strategyFlag,
635 ProvidingKeyChanFunc: kcf,
core/node/storage.go
+2 -4
@@ -2,7 +2,6 @@ package node
2
3 import (
4 blockstore "github.com/ipfs/boxo/blockstore"
5 - provider "github.com/ipfs/boxo/provider"
5 "github.com/ipfs/go-datastore"
6 config "github.com/ipfs/kubo/config"
7 "go.uber.org/fx"
@@ -33,9 +32,8 @@ func BaseBlockstoreCtor(
32 hashOnRead bool,
33 writeThrough bool,
34 providingStrategy string,
36 -
37 -) func(mctx helpers.MetricsCtx, repo repo.Repo, prov provider.System, lc fx.Lifecycle) (bs BaseBlocks, err error) {
38 - return func(mctx helpers.MetricsCtx, repo repo.Repo, prov provider.System, lc fx.Lifecycle) (bs BaseBlocks, err error) {
35 +) func(mctx helpers.MetricsCtx, repo repo.Repo, prov DHTProvider, lc fx.Lifecycle) (bs BaseBlocks, err error) {
36 + return func(mctx helpers.MetricsCtx, repo repo.Repo, prov DHTProvider, lc fx.Lifecycle) (bs BaseBlocks, err error) {
37 opts := []blockstore.Option{blockstore.WriteThrough(writeThrough)}
38
39 // Blockstore providing integration:
docs/changelogs/v0.38.md
+11
@@ -10,6 +10,7 @@ This release was brought to you by the [Shipyard](https://ipshipyard.com/) team.
10
11 - [Overview](#overview)
12 - [🔦 Highlights](#-highlights)
13 + - [🧹 Experimental Sweeping DHT Provider](#-experimental-sweeping-dht-provider)
14 - [📦️ Important dependency updates](#-important-dependency-updates)
15 - [📝 Changelog](#-changelog)
16 - [👨‍👩‍👧‍👦 Contributors](#-contributors)
@@ -18,6 +19,16 @@ This release was brought to you by the [Shipyard](https://ipshipyard.com/) team.
19
20 ### 🔦 Highlights
21
22 +#### 🧹 Experimental Sweeping DHT Provider
23 +
24 +An experimental alternative to both the default DHT provider and the resource-intensive [accelerated DHT client](https://github.com/ipfs/kubo/blob/master/docs/config.md#routingaccelerateddhtclient) is now available. When enabled via [`Reprovider.Sweep.Enabled`](https://github.com/ipfs/kubo/blob/master/docs/config.md#reprovidersweep), this sweeping DHT provider explores keyspace regions instead of providing keys one-by-one.
25 +
26 +This aims to help both large and small storage providers efficiently advertise hundreds of thousands of CIDs by batching operations and spreading work evenly over time.
27 +
28 +**Note:** While this feature is experimental, some commands like `ipfs stats provide` and manual reprovide (`ipfs routing provide`) are not available. Run `ipfs provide --help` for alternative commands.
29 +
30 +For configuration options and more details, see [`Reprovider.Sweep`](https://github.com/ipfs/kubo/blob/master/docs/config.md#reprovidersweep) in the config documentation.
31 +
32 #### 🚨 Improved gateway error pages with diagnostic tools
33
34 Gateway error pages now provide more actionable information during content retrieval failures. When a 504 Gateway Timeout occurs, users see detailed retrieval state information including which phase failed and a sample of providers that were attempted:
docs/config.md
+156
@@ -140,6 +140,7 @@ config file at runtime.
140 - [`Reprovider`](#reprovider)
141 - [`Reprovider.Interval`](#reproviderinterval)
142 - [`Reprovider.Strategy`](#reproviderstrategy)
143 + - [`Reprovider.Sweep`](#reprovidersweep)
144 - [`Routing`](#routing)
145 - [`Routing.Type`](#routingtype)
146 - [`Routing.AcceleratedDHTClient`](#routingaccelerateddhtclient)
@@ -2100,6 +2101,161 @@ Default: `"all"`
2101
2102 Type: `optionalString` (unset for the default)
2103
2104 +### Reprovider.Sweep
2105 +
2106 +Reprovider Sweep is a resource efficient technique for advertising content to
2107 +the Amino DHT swarm.
2108 +
2109 +The Reprovider module tracks the keys that should be periodically reprovided in
2110 +the `KeyStore`. It splits the keys into DHT keyspace regions by proximity (XOR
2111 +distance), and schedules when reprovides should happen in order to spread the
2112 +reprovide operation over time to avoid a spike in resource utilization. It
2113 +basically sweeps the keyspace _from left to right_ over the
2114 +[`Reprovider.Interval`](#reproviderinterval) time period, and reprovides keys
2115 +matching to the visited keyspace region.
2116 +
2117 +Reprovider Sweep aims at replacing the inefficient legacy `boxo/provider`
2118 +module, and is currently opt-in.
2119 +
2120 +Whenever new keys should be advertised to the Amino DHT, `kubo` calls
2121 +`StartProviding()`, triggering an initial `provide` operation for the given
2122 +keys. The keys will be added to the `KeyStore` tracking which keys should be
2123 +reprovided and when they should be reprovided. Calling `StopProviding()`
2124 +removes the keys from the `KeyStore`. However, it is currently tricky for
2125 +`kubo` to detect when a key should stop being advertised. Hence, `kubo` will
2126 +periodically refresh the `KeyStore` at each [`Reprovider.Interval`](#reproviderinterval)
2127 +by providing it a channel of all the keys it is expected to contain according
2128 +to the [`Reprovider.Strategy`](#reproviderstrategy). During this operation,
2129 +all keys in the `Keystore` are purged, and only the given ones remain scheduled.
2130 +
2131 +#### Reprovider.Sweep.Enabled
2132 +
2133 +Whether Reprovider Sweep is enabled. If not enabled, the
2134 +[`boxo/provider`](https://github.com/ipfs/boxo/tree/main/provider) is used for
2135 +both provides and reprovides.
2136 +
2137 +Default: `false`
2138 +
2139 +Type: `flag`
2140 +
2141 +#### Reprovider.Sweep.MaxWorkers
2142 +
2143 +The maximum number of workers used by the `SweepingReprovider` to provide and
2144 +reprovide CIDs to the DHT swarm.
2145 +
2146 +A worker performs Kademlia `GetClosestPeers` operations (max 1 at a time) to
2147 +explore a region of the DHT keyspace, and then sends provider records to the
2148 +nodes from that keyspace region. `GetClosestPeers` is capped to `10` concurrent
2149 +connections [`amino` DHT
2150 +defaults](https://github.com/libp2p/go-libp2p-kad-dht/blob/master/amino/defaults.go).
2151 +The number of simultaneous connections used to send provider records is defined
2152 +by
2153 +[`Reprovider.Sweep.MaxProvideConnsPerWorker`](#reprovidersweepmaxprovideconnsperworker).
2154 +
2155 +The workers are split between two tasks categories:
2156 +
2157 +1. Periodic reprovides (see
2158 + [`Reprovider.Sweep.DedicatedPeriodicWorkers`](#reprovidersweepdedicatedperiodicworkers))
2159 +2. Burst provides (see
2160 + [`Reprovider.Sweep.DedicatedBurstWorkers`](#reprovidersweepdedicatedburstworkers))
2161 +
2162 +[`Reprovider.Sweep.DedicatedPeriodicWorkers`](#reprovidersweepdedicatedperiodicworkers)
2163 +workers are allocated to the periodic reprovides only,
2164 +[`Reprovider.Sweep.DedicatedBurstWorkers`](#reprovidersweepdedicatedburstworkers)
2165 +workers are allocated to burst provides only, and the rest of
2166 +[`Reprovider.Sweep.MaxWorkers`](#reprovidersweepmaxworkers) can be used for
2167 +either task (first come, first served).
2168 +
2169 +Default: `4`
2170 +
2171 +Type: `optionalInteger` (non-negative)
2172 +
2173 +#### Reprovider.Sweep.DedicatedPeriodicWorkers
2174 +
2175 +Number of workers dedicated to periodic keyspace region reprovides.
2176 +
2177 +Among the [`Reprovider.Sweep.MaxWorkers`](#reprovidersweepmaxworkers), this
2178 +number of workers will be dedicated to the periodic region reprovide only. In
2179 +addition to these, if there are available workers in the pool, they can also be
2180 +used for periodic reprovides.
2181 +
2182 +Default: `2`
2183 +
2184 +Type: `optionalInteger` (`0` means there are no dedicated workers, but the
2185 +operation can be performed by free non-dedicated workers)
2186 +
2187 +#### Reprovider.Sweep.DedicatedBurstWorkers
2188 +
2189 +Number of workers dedicated to burst provides.
2190 +
2191 +Burst provides are triggered when a new keys must be advertised to the DHT
2192 +immediately, or when a node comes back online and must catch up the reprovides
2193 +that should have happened while it was offline.
2194 +
2195 +Among the [`Reprovider.Sweep.MaxWorkers`](#reprovidersweepmaxworkers), this
2196 +number of workers will be dedicated to burst provides only. In addition to
2197 +these, if there are available workers in the pool, they can also be used for
2198 +burst provides.
2199 +
2200 +Default: `1`
2201 +
2202 +Type: `optionalInteger` (`0` means there are no dedicated workers, but the
2203 +operation can be performed by free non-dedicated workers)
2204 +
2205 +#### Reprovider.Sweep.MaxProvideConnsPerWorker
2206 +
2207 +Maximum number of connections that a single worker can use to send provider
2208 +records over the network.
2209 +
2210 +When reproviding CIDs corresponding to a keyspace region, the reprovider must
2211 +send a provider record to the 20 closest peers to the CID (in XOR distance) for
2212 +each CID belonging to this keyspace region.
2213 +
2214 +The reprovider opens a connection to a peer from that region, send it all its
2215 +allocated provider records. Once done, it opens a connection to the next peer
2216 +from that keyspace region until all provider records are assigned.
2217 +
2218 +This option defines how many such connections can be open concurrently by a
2219 +single worker.
2220 +
2221 +Default: `16`
2222 +
2223 +Type: `optionalInteger` (non-negative)
2224 +
2225 +#### Reprovider.Sweep.KeyStoreBatchSize
2226 +
2227 +During the garbage collection, all keys stored in the KeyStore are removed, and
2228 +the keys are streamed from a channel to fill the KeyStore again with up-to-date
2229 +keys. Since a high number of CIDs to reprovide can easily fill up the memory,
2230 +keys are read and written in batches to optimize for memory usage.
2231 +
2232 +This option defines how many multihashes should be contained within a batch. A
2233 +multihash is usually represented by 34 bytes.
2234 +
2235 +Default: `16384` (~544 KiB per batch)
2236 +
2237 +Type: `optionalInteger` (non-negative)
2238 +
2239 +#### Reprovider.Sweep.OfflineDelay
2240 +
2241 +The `SweepingProvider` has 3 states: `ONLINE`, `DISCONNECTED` and `OFFLINE`. It
2242 +starts `OFFLINE`, and as the node bootstraps, it changes its state to `ONLINE`.
2243 +
2244 +When the provider loses connection to all DHT peers, it switches to the
2245 +`DISCONNECTED` state. In this state, new provides will be added to the provide
2246 +queue, and provided as soon as the node comes back online.
2247 +
2248 +After a node has been `DISCONNECTED` for `OfflineDelay`, it goes to `OFFLINE`
2249 +state. When `OFFLINE`, the provider drops the provide queue, and returns errors
2250 +to new provide requests. However, when `OFFLINE` the provide still adds the
2251 +keys to its state, so keys will eventually be provided in the
2252 +[`Reprovider.Interval`](#reproviderinterval) after the provider comes back
2253 +`ONLINE`.
2254 +
2255 +Default: `2h`
2256 +
2257 +Type: `optionalDuration`
2258 +
2259 ## `Routing`
2260
2261 Contains options for content, peer, and IPNS routing mechanisms.
docs/examples/kubo-as-a-library/go.mod
+35 -30
@@ -7,7 +7,7 @@ go 1.25
7 replace github.com/ipfs/kubo => ./../../..
8
9 require (
10 - github.com/ipfs/boxo v0.34.1-0.20250909170220-e69f67e94c11
10 + github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3
11 github.com/ipfs/kubo v0.0.0-00010101000000-000000000000
12 github.com/libp2p/go-libp2p v0.43.0
13 github.com/multiformats/go-multiaddr v0.16.1
@@ -26,7 +26,7 @@ require (
26 github.com/caddyserver/certmagic v0.23.0 // indirect
27 github.com/caddyserver/zerossl v0.1.3 // indirect
28 github.com/cenkalti/backoff/v4 v4.3.0 // indirect
29 - github.com/cenkalti/backoff/v5 v5.0.2 // indirect
29 + github.com/cenkalti/backoff/v5 v5.0.3 // indirect
30 github.com/ceramicnetwork/go-dag-jose v0.1.1 // indirect
31 github.com/cespare/xxhash/v2 v2.3.0 // indirect
32 github.com/cockroachdb/crlib v0.0.0-20241015224233-894974b3ad94 // indirect
@@ -50,21 +50,22 @@ require (
50 github.com/flynn/noise v1.1.0 // indirect
51 github.com/francoispqt/gojay v1.2.13 // indirect
52 github.com/fsnotify/fsnotify v1.7.0 // indirect
53 - github.com/gabriel-vasile/mimetype v1.4.9 // indirect
53 + github.com/gabriel-vasile/mimetype v1.4.10 // indirect
54 github.com/gammazero/chanqueue v1.1.1 // indirect
55 github.com/gammazero/deque v1.1.0 // indirect
56 github.com/getsentry/sentry-go v0.27.0 // indirect
57 - github.com/go-jose/go-jose/v4 v4.0.5 // indirect
57 + github.com/go-jose/go-jose/v4 v4.1.1 // indirect
58 github.com/go-logr/logr v1.4.3 // indirect
59 github.com/go-logr/stdr v1.2.2 // indirect
60 github.com/gogo/protobuf v1.3.2 // indirect
61 - github.com/golang/glog v1.2.4 // indirect
61 + github.com/golang/glog v1.2.5 // indirect
62 github.com/golang/protobuf v1.5.4 // indirect
63 github.com/golang/snappy v0.0.5-0.20231225225746-43d5d4cd4e0e // indirect
64 github.com/google/gopacket v1.1.19 // indirect
65 github.com/google/uuid v1.6.0 // indirect
66 github.com/gorilla/websocket v1.5.3 // indirect
67 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 // indirect
67 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
68 + github.com/guillaumemichel/reservedpool v0.2.0 // indirect
69 github.com/hashicorp/golang-lru v1.0.2 // indirect
70 github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
71 github.com/huin/goupnp v1.3.0 // indirect
@@ -75,12 +76,13 @@ require (
76 github.com/ipfs/go-block-format v0.2.2 // indirect
77 github.com/ipfs/go-cid v0.5.0 // indirect
78 github.com/ipfs/go-cidutil v0.1.0 // indirect
78 - github.com/ipfs/go-datastore v0.8.3 // indirect
79 + github.com/ipfs/go-datastore v0.8.4 // indirect
80 github.com/ipfs/go-ds-badger v0.3.4 // indirect
81 github.com/ipfs/go-ds-flatfs v0.5.5 // indirect
82 github.com/ipfs/go-ds-leveldb v0.5.2 // indirect
83 github.com/ipfs/go-ds-measure v0.2.2 // indirect
84 github.com/ipfs/go-ds-pebble v0.5.1 // indirect
85 + github.com/ipfs/go-dsqueue v0.0.5 // indirect
86 github.com/ipfs/go-fs-lock v0.1.1 // indirect
87 github.com/ipfs/go-ipfs-ds-help v1.1.1 // indirect
88 github.com/ipfs/go-ipfs-pq v0.0.3 // indirect
@@ -92,8 +94,9 @@ require (
94 github.com/ipfs/go-log/v2 v2.8.1 // indirect
95 github.com/ipfs/go-metrics-interface v0.3.0 // indirect
96 github.com/ipfs/go-peertaskqueue v0.8.2 // indirect
97 + github.com/ipfs/go-test v0.2.3 // indirect
98 github.com/ipfs/go-unixfsnode v1.10.1 // indirect
96 - github.com/ipld/go-car/v2 v2.14.3 // indirect
99 + github.com/ipld/go-car/v2 v2.15.0 // indirect
100 github.com/ipld/go-codec-dagpb v1.7.0 // indirect
101 github.com/ipld/go-ipld-prime v0.21.0 // indirect
102 github.com/ipshipyard/p2p-forge v0.6.1 // indirect
@@ -110,8 +113,8 @@ require (
113 github.com/libp2p/go-doh-resolver v0.5.0 // indirect
114 github.com/libp2p/go-flow-metrics v0.3.0 // indirect
115 github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
113 - github.com/libp2p/go-libp2p-kad-dht v0.34.0 // indirect
114 - github.com/libp2p/go-libp2p-kbucket v0.7.0 // indirect
116 + github.com/libp2p/go-libp2p-kad-dht v0.34.1-0.20250918150625-2e3cea182b63 // indirect
117 + github.com/libp2p/go-libp2p-kbucket v0.8.0 // indirect
118 github.com/libp2p/go-libp2p-pubsub v0.14.2 // indirect
119 github.com/libp2p/go-libp2p-pubsub-router v0.6.0 // indirect
120 github.com/libp2p/go-libp2p-record v0.3.1 // indirect
@@ -165,9 +168,10 @@ require (
168 github.com/pion/webrtc/v4 v4.1.2 // indirect
169 github.com/pkg/errors v0.9.1 // indirect
170 github.com/polydawn/refmt v0.89.0 // indirect
168 - github.com/prometheus/client_golang v1.23.0 // indirect
171 + github.com/probe-lab/go-libdht v0.2.1 // indirect
172 + github.com/prometheus/client_golang v1.23.2 // indirect
173 github.com/prometheus/client_model v0.6.2 // indirect
170 - github.com/prometheus/common v0.65.0 // indirect
174 + github.com/prometheus/common v0.66.1 // indirect
175 github.com/prometheus/procfs v0.17.0 // indirect
176 github.com/quic-go/qpack v0.5.1 // indirect
177 github.com/quic-go/quic-go v0.54.0 // indirect
@@ -186,39 +190,40 @@ require (
190 github.com/zeebo/blake3 v0.2.4 // indirect
191 go.opencensus.io v0.24.0 // indirect
192 go.opentelemetry.io/auto/sdk v1.1.0 // indirect
189 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 // indirect
190 - go.opentelemetry.io/otel v1.37.0 // indirect
191 - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 // indirect
192 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0 // indirect
193 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 // indirect
194 - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 // indirect
195 - go.opentelemetry.io/otel/exporters/zipkin v1.37.0 // indirect
196 - go.opentelemetry.io/otel/metric v1.37.0 // indirect
197 - go.opentelemetry.io/otel/sdk v1.37.0 // indirect
198 - go.opentelemetry.io/otel/trace v1.37.0 // indirect
199 - go.opentelemetry.io/proto/otlp v1.7.0 // indirect
193 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect
194 + go.opentelemetry.io/otel v1.38.0 // indirect
195 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect
196 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 // indirect
197 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 // indirect
198 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0 // indirect
199 + go.opentelemetry.io/otel/exporters/zipkin v1.38.0 // indirect
200 + go.opentelemetry.io/otel/metric v1.38.0 // indirect
201 + go.opentelemetry.io/otel/sdk v1.38.0 // indirect
202 + go.opentelemetry.io/otel/trace v1.38.0 // indirect
203 + go.opentelemetry.io/proto/otlp v1.7.1 // indirect
204 go.uber.org/dig v1.19.0 // indirect
205 go.uber.org/fx v1.24.0 // indirect
206 go.uber.org/mock v0.5.2 // indirect
207 go.uber.org/multierr v1.11.0 // indirect
208 go.uber.org/zap v1.27.0 // indirect
209 go.uber.org/zap/exp v0.3.0 // indirect
210 + go.yaml.in/yaml/v2 v2.4.2 // indirect
211 go4.org v0.0.0-20230225012048-214862532bf5 // indirect
212 golang.org/x/crypto v0.41.0 // indirect
208 - golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 // indirect
213 + golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b // indirect
214 golang.org/x/mod v0.27.0 // indirect
215 golang.org/x/net v0.43.0 // indirect
211 - golang.org/x/sync v0.16.0 // indirect
212 - golang.org/x/sys v0.35.0 // indirect
216 + golang.org/x/sync v0.17.0 // indirect
217 + golang.org/x/sys v0.36.0 // indirect
218 golang.org/x/text v0.28.0 // indirect
219 golang.org/x/time v0.12.0 // indirect
220 golang.org/x/tools v0.36.0 // indirect
221 golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
222 gonum.org/v1/gonum v0.16.0 // indirect
218 - google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
219 - google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
220 - google.golang.org/grpc v1.73.0 // indirect
221 - google.golang.org/protobuf v1.36.7 // indirect
223 + google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
224 + google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect
225 + google.golang.org/grpc v1.75.0 // indirect
226 + google.golang.org/protobuf v1.36.9 // indirect
227 gopkg.in/yaml.v3 v3.0.1 // indirect
228 lukechampine.com/blake3 v1.4.1 // indirect
229 )
docs/examples/kubo-as-a-library/go.sum
+72 -64
@@ -67,8 +67,8 @@ github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+Y
67 github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
68 github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
69 github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
70 -github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8=
71 -github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
70 +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
71 +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
72 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
73 github.com/ceramicnetwork/go-dag-jose v0.1.1 h1:7pObs22egc14vSS3AfCFfS1VmaL4lQUsAK7OGC3PlKk=
74 github.com/ceramicnetwork/go-dag-jose v0.1.1/go.mod h1:8ptnYwY2Z2y/s5oJnNBn/UCxLg6CpramNJ2ZXF/5aNY=
@@ -159,8 +159,8 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4
159 github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
160 github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
161 github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
162 -github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
163 -github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
162 +github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
163 +github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
164 github.com/gammazero/chanqueue v1.1.1 h1:n9Y+zbBxw2f7uUE9wpgs0rOSkP/I/yhDLiNuhyVjojQ=
165 github.com/gammazero/chanqueue v1.1.1/go.mod h1:fMwpwEiuUgpab0sH4VHiVcEoji1pSi+EIzeG4TPeKPc=
166 github.com/gammazero/deque v1.1.0 h1:OyiyReBbnEG2PP0Bnv1AASLIYvyKqIFN5xfl1t8oGLo=
@@ -177,8 +177,8 @@ github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxI
177 github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
178 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
179 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
180 -github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
181 -github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
180 +github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI=
181 +github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA=
182 github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
183 github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
184 github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@@ -193,8 +193,8 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP
193 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
194 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
195 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
196 -github.com/golang/glog v1.2.4 h1:CNNw5U8lSiiBk7druxtSHHTsRWcxKoac6kZKm2peBBc=
197 -github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
196 +github.com/golang/glog v1.2.5 h1:DrW6hGnjIhtvhOIiAKT6Psh/Kd/ldepEa81DKeiRJ5I=
197 +github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
198 github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
199 github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
200 github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -264,8 +264,10 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN
264 github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
265 github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
266 github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
267 -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww=
268 -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90=
267 +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
268 +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
269 +github.com/guillaumemichel/reservedpool v0.2.0 h1:q73gtdMFJHtW+dDJ/fwtk34p7JprQv8fJSK7dEjf8Sw=
270 +github.com/guillaumemichel/reservedpool v0.2.0/go.mod h1:sXSDIaef81TFdAJglsCFCMfgF5E5Z5xK1tFhjDhvbUc=
271 github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU=
272 github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48=
273 github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
@@ -287,8 +289,8 @@ github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 h1:OqNqsGZPX8zh3eFMO8Lf8EHRRnSGBMqcd
289 github.com/ipfs-shipyard/nopfs/ipfs v0.25.0/go.mod h1:BxhUdtBgOXg1B+gAPEplkg/GpyTZY+kCMSfsJvvydqU=
290 github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
291 github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
290 -github.com/ipfs/boxo v0.34.1-0.20250909170220-e69f67e94c11 h1:EsCbOKE+giLtrFTysnbTzIRQENOiLdcpOY3kV3y6wlU=
291 -github.com/ipfs/boxo v0.34.1-0.20250909170220-e69f67e94c11/go.mod h1:rXql6ncaLZZfLqDG3Cuw9ZYQKd3rMU5bk1TGXF0+ZL0=
292 +github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3 h1:qp8w52Rf5eEOrNFZ1VdLSOU3kA5N2EGMNv0xZAACSfs=
293 +github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3/go.mod h1:YbQ2GM5GolkfJ8qB29RL+cXgFEa/HsDrHeHSB+fOrlY=
294 github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
295 github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
296 github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk=
@@ -303,8 +305,8 @@ github.com/ipfs/go-cidutil v0.1.0 h1:RW5hO7Vcf16dplUU60Hs0AKDkQAVPVplr7lk97CFL+Q
305 github.com/ipfs/go-cidutil v0.1.0/go.mod h1:e7OEVBMIv9JaOxt9zaGEmAoSlXW9jdFZ5lP/0PwcfpA=
306 github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE=
307 github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw=
306 -github.com/ipfs/go-datastore v0.8.3 h1:z391GsQyGKUIUof2tPoaZVeDknbt7fNHs6Gqjcw5Jo4=
307 -github.com/ipfs/go-datastore v0.8.3/go.mod h1:raxQ/CreIy9L6MxT71ItfMX12/ASN6EhXJoUFjICQ2M=
308 +github.com/ipfs/go-datastore v0.8.4 h1:vXEsd76T3KIOSKXizjhmS3ICGMl+oOSjpLSxE3v8/Wc=
309 +github.com/ipfs/go-datastore v0.8.4/go.mod h1:uT77w/XEGrvJWwHgdrMr8bqCN6ZTW9gzmi+3uK+ouHg=
310 github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
311 github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
312 github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk=
@@ -319,6 +321,8 @@ github.com/ipfs/go-ds-measure v0.2.2 h1:4kwvBGbbSXNYe4ANlg7qTIYoZU6mNlqzQHdVqICk
321 github.com/ipfs/go-ds-measure v0.2.2/go.mod h1:b/87ak0jMgH9Ylt7oH0+XGy4P8jHx9KG09Qz+pOeTIs=
322 github.com/ipfs/go-ds-pebble v0.5.1 h1:p0FAE0zw9J/3T1VkGB9s98jWmfKmw2t0iEwfMUv8iSQ=
323 github.com/ipfs/go-ds-pebble v0.5.1/go.mod h1:LsmQx4w+0o9znl4hTxYo1Y2lnBTzNCwc4kNpD3wWXM0=
324 +github.com/ipfs/go-dsqueue v0.0.5 h1:TUOk15TlCJ/NKV8Yk2W5wgkEjDa44Nem7a7FGIjsMNU=
325 +github.com/ipfs/go-dsqueue v0.0.5/go.mod h1:i/jAlpZjBbQJLioN+XKbFgnd+u9eAhGZs9IrqIzTd9g=
326 github.com/ipfs/go-fs-lock v0.1.1 h1:TecsP/Uc7WqYYatasreZQiP9EGRy4ZnKoG4yXxR33nw=
327 github.com/ipfs/go-fs-lock v0.1.1/go.mod h1:2goSXMCw7QfscHmSe09oXiR34DQeUdm+ei+dhonqly0=
328 github.com/ipfs/go-ipfs-blockstore v1.3.1 h1:cEI9ci7V0sRNivqaOr0elDsamxXFxJMMMy7PTTDQNsQ=
@@ -355,8 +359,8 @@ github.com/ipfs/go-test v0.2.3 h1:Z/jXNAReQFtCYyn7bsv/ZqUwS6E7iIcSpJ2CuzCvnrc=
359 github.com/ipfs/go-test v0.2.3/go.mod h1:QW8vSKkwYvWFwIZQLGQXdkt9Ud76eQXRQ9Ao2H+cA1o=
360 github.com/ipfs/go-unixfsnode v1.10.1 h1:hGKhzuH6NSzZ4y621wGuDspkjXRNG3B+HqhlyTjSwSM=
361 github.com/ipfs/go-unixfsnode v1.10.1/go.mod h1:eguv/otvacjmfSbYvmamc9ssNAzLvRk0+YN30EYeOOY=
358 -github.com/ipld/go-car/v2 v2.14.3 h1:1Mhl82/ny8MVP+w1M4LXbj4j99oK3gnuZG2GmG1IhC8=
359 -github.com/ipld/go-car/v2 v2.14.3/go.mod h1:/vpSvPngOX8UnvmdFJ3o/mDgXa9LuyXsn7wxOzHDYQE=
362 +github.com/ipld/go-car/v2 v2.15.0 h1:RxtZcGXFx72zFESl+UUsCNQV2YMcy3gEMYx9M3uio24=
363 +github.com/ipld/go-car/v2 v2.15.0/go.mod h1:ovlq/n3xlVJDmoiN3Kd/Z7kIzQbdTIFSwltfOP+qIgk=
364 github.com/ipld/go-codec-dagpb v1.7.0 h1:hpuvQjCSVSLnTnHXn+QAMR0mLmb1gA6wl10LExo2Ts0=
365 github.com/ipld/go-codec-dagpb v1.7.0/go.mod h1:rD3Zg+zub9ZnxcLwfol/OTQRVjaLzXypgy4UqHQvilM=
366 github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8=
@@ -426,11 +430,11 @@ github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl9
430 github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8=
431 github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g=
432 github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw=
429 -github.com/libp2p/go-libp2p-kad-dht v0.34.0 h1:yvJ/Vrt36GVjsqPxiGcuuwOloKuZLV9Aa7awIKyNXy0=
430 -github.com/libp2p/go-libp2p-kad-dht v0.34.0/go.mod h1:JNbkES4W5tajS6uYivw6MPs0842cPHAwhgaPw8sQG4o=
433 +github.com/libp2p/go-libp2p-kad-dht v0.34.1-0.20250918150625-2e3cea182b63 h1:XQSASQ9N5haD/uYmop/633tYMZNsM+lKKI8/Is30w4o=
434 +github.com/libp2p/go-libp2p-kad-dht v0.34.1-0.20250918150625-2e3cea182b63/go.mod h1:HbI1rUTFF87WHklzKTGZC8Oys9+1rkKyqvmSZcAW55Y=
435 github.com/libp2p/go-libp2p-kbucket v0.3.1/go.mod h1:oyjT5O7tS9CQurok++ERgc46YLwEpuGoFq9ubvoUOio=
432 -github.com/libp2p/go-libp2p-kbucket v0.7.0 h1:vYDvRjkyJPeWunQXqcW2Z6E93Ywx7fX0jgzb/dGOKCs=
433 -github.com/libp2p/go-libp2p-kbucket v0.7.0/go.mod h1:blOINGIj1yiPYlVEX0Rj9QwEkmVnz3EP8LK1dRKBC6g=
436 +github.com/libp2p/go-libp2p-kbucket v0.8.0 h1:QAK7RzKJpYe+EuSEATAaaHYMYLkPDGC18m9jxPLnU8s=
437 +github.com/libp2p/go-libp2p-kbucket v0.8.0/go.mod h1:JMlxqcEyKwO6ox716eyC0hmiduSWZZl6JY93mGaaqc4=
438 github.com/libp2p/go-libp2p-peerstore v0.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVdLxvqh7hXOujessqdzs=
439 github.com/libp2p/go-libp2p-pubsub v0.14.2 h1:nT5lFHPQOFJcp9CW8hpKtvbpQNdl2udJuzLQWbgRum8=
440 github.com/libp2p/go-libp2p-pubsub v0.14.2/go.mod h1:MKPU5vMI8RRFyTP0HfdsF9cLmL1nHAeJm44AxJGJx44=
@@ -622,16 +626,18 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH
626 github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o=
627 github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4=
628 github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw=
629 +github.com/probe-lab/go-libdht v0.2.1 h1:oBCsKBvS/OVirTO5+BT6/AOocWjdqwpfSfkTfBjUPJE=
630 +github.com/probe-lab/go-libdht v0.2.1/go.mod h1:q+WlGiqs/UIRfdhw9Gmc+fPoAYlOim7VvXTjOI6KJmQ=
631 github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
626 -github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
627 -github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=
632 +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
633 +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
634 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
635 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
636 github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
637 github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
638 github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
633 -github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
634 -github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
639 +github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
640 +github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
641 github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
642 github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
643 github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
@@ -712,8 +718,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
718 github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
719 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
720 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
715 -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
716 -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
721 +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
722 +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
723 github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
724 github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs=
725 github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48=
@@ -769,30 +775,30 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
775 go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
776 go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
777 go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
772 -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 h1:Hf9xI/XLML9ElpiHVDNwvqI0hIFlzV8dgIr35kV1kRU=
773 -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0/go.mod h1:NfchwuyNoMcZ5MLHwPrODwUF1HWCXWrL31s8gSAdIKY=
774 -go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
775 -go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
776 -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 h1:Ahq7pZmv87yiyn3jeFz/LekZmPLLdKejuO3NcK9MssM=
777 -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0/go.mod h1:MJTqhM0im3mRLw1i8uGHnCvUEeS7VwRyxlLC78PA18M=
778 -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0 h1:EtFWSnwW9hGObjkIdmlnWSydO+Qs8OwzfzXLUPg4xOc=
779 -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0/go.mod h1:QjUEoiGCPkvFZ/MjK6ZZfNOS6mfVEVKYE99dFhuN2LI=
780 -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 h1:bDMKF3RUSxshZ5OjOTi8rsHGaPKsAt76FaqgvIUySLc=
781 -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0/go.mod h1:dDT67G/IkA46Mr2l9Uj7HsQVwsjASyV9SjGofsiUZDA=
782 -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 h1:SNhVp/9q4Go/XHBkQ1/d5u9P/U+L1yaGPoi0x+mStaI=
783 -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0/go.mod h1:tx8OOlGH6R4kLV67YaYO44GFXloEjGPZuMjEkaaqIp4=
784 -go.opentelemetry.io/otel/exporters/zipkin v1.37.0 h1:Z2apuaRnHEjzDAkpbWNPiksz1R0/FCIrJSjiMA43zwI=
785 -go.opentelemetry.io/otel/exporters/zipkin v1.37.0/go.mod h1:ofGu/7fG+bpmjZoiPUUmYDJ4vXWxMT57HmGoegx49uw=
786 -go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
787 -go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
788 -go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
789 -go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
790 -go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
791 -go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
792 -go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
793 -go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
794 -go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os=
795 -go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo=
778 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18=
779 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg=
780 +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
781 +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
782 +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24=
783 +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU=
784 +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 h1:lwI4Dc5leUqENgGuQImwLo4WnuXFPetmPpkLi2IrX54=
785 +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0/go.mod h1:Kz/oCE7z5wuyhPxsXDuaPteSWqjSBD5YaSdbxZYGbGk=
786 +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 h1:aTL7F04bJHUlztTsNGJ2l+6he8c+y/b//eR0jjjemT4=
787 +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4=
788 +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0 h1:kJxSDN4SgWWTjG/hPp3O7LCGLcHXFlvS2/FFOrwL+SE=
789 +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0/go.mod h1:mgIOzS7iZeKJdeB8/NYHrJ48fdGc71Llo5bJ1J4DWUE=
790 +go.opentelemetry.io/otel/exporters/zipkin v1.38.0 h1:0rJ2TmzpHDG+Ib9gPmu3J3cE0zXirumQcKS4wCoZUa0=
791 +go.opentelemetry.io/otel/exporters/zipkin v1.38.0/go.mod h1:Su/nq/K5zRjDKKC3Il0xbViE3juWgG3JDoqLumFx5G0=
792 +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
793 +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
794 +go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
795 +go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
796 +go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
797 +go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
798 +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
799 +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
800 +go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4=
801 +go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE=
802 go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
803 go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
804 go.uber.org/dig v1.19.0 h1:BACLhebsYdpQ7IROQ1AGPjrXcP5dF80U3gKoFzbaq/4=
@@ -809,6 +815,8 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
815 go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
816 go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U=
817 go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ=
818 +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
819 +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
820 go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
821 go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc=
822 go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU=
@@ -842,8 +850,8 @@ golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE
850 golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
851 golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
852 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
845 -golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 h1:SbTAbRFnd5kjQXbczszQ0hdk3ctwYf3qBNH9jIsGclE=
846 -golang.org/x/exp v0.0.0-20250813145105-42675adae3e6/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
853 +golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0=
854 +golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
855 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
856 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
857 golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -923,8 +931,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
931 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
932 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
933 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
926 -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
927 -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
934 +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
935 +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
936 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
937 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
938 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -971,8 +979,8 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
979 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
980 golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
981 golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
974 -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
975 -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
982 +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
983 +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
984 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
985 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
986 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -1081,10 +1089,10 @@ google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvx
1089 google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
1090 google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
1091 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
1084 -google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY=
1085 -google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc=
1086 -google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE=
1087 -google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
1092 +google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY=
1093 +google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE=
1094 +google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE=
1095 +google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc=
1096 google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
1097 google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
1098 google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
@@ -1097,8 +1105,8 @@ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
1105 google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
1106 google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
1107 google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
1100 -google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
1101 -google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
1108 +google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4=
1109 +google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
1110 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
1111 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
1112 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -1110,8 +1118,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
1118 google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
1119 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
1120 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
1113 -google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A=
1114 -google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
1121 +google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
1122 +google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
1123 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
1124 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
1125 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
go.mod
+35 -31
@@ -22,11 +22,11 @@ require (
22 github.com/hashicorp/go-version v1.7.0
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.34.1-0.20250909170220-e69f67e94c11
25 + github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3
26 github.com/ipfs/go-block-format v0.2.2
27 github.com/ipfs/go-cid v0.5.0
28 github.com/ipfs/go-cidutil v0.1.0
29 - github.com/ipfs/go-datastore v0.8.3
29 + github.com/ipfs/go-datastore v0.8.4
30 github.com/ipfs/go-detect-race v0.0.1
31 github.com/ipfs/go-ds-badger v0.3.4
32 github.com/ipfs/go-ds-flatfs v0.5.5
@@ -44,7 +44,7 @@ require (
44 github.com/ipfs/go-metrics-prometheus v0.1.0
45 github.com/ipfs/go-test v0.2.3
46 github.com/ipfs/go-unixfsnode v1.10.1
47 - github.com/ipld/go-car/v2 v2.14.3
47 + github.com/ipld/go-car/v2 v2.15.0
48 github.com/ipld/go-codec-dagpb v1.7.0
49 github.com/ipld/go-ipld-prime v0.21.0
50 github.com/ipshipyard/p2p-forge v0.6.1
@@ -53,8 +53,8 @@ require (
53 github.com/libp2p/go-doh-resolver v0.5.0
54 github.com/libp2p/go-libp2p v0.43.0
55 github.com/libp2p/go-libp2p-http v0.5.0
56 - github.com/libp2p/go-libp2p-kad-dht v0.34.0
57 - github.com/libp2p/go-libp2p-kbucket v0.7.0
56 + github.com/libp2p/go-libp2p-kad-dht v0.34.1-0.20250918150625-2e3cea182b63
57 + github.com/libp2p/go-libp2p-kbucket v0.8.0
58 github.com/libp2p/go-libp2p-pubsub v0.14.2
59 github.com/libp2p/go-libp2p-pubsub-router v0.6.0
60 github.com/libp2p/go-libp2p-record v0.3.1
@@ -69,28 +69,28 @@ require (
69 github.com/multiformats/go-multihash v0.2.3
70 github.com/opentracing/opentracing-go v1.2.0
71 github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58
72 - github.com/prometheus/client_golang v1.23.0
73 - github.com/stretchr/testify v1.10.0
72 + github.com/prometheus/client_golang v1.23.2
73 + github.com/stretchr/testify v1.11.1
74 github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d
75 github.com/tidwall/gjson v1.16.0
76 github.com/tidwall/sjson v1.2.5
77 github.com/whyrusleeping/go-sysinfo v0.0.0-20190219211824-4a357d4b90b1
78 github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7
79 go.opencensus.io v0.24.0
80 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0
80 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0
81 go.opentelemetry.io/contrib/propagators/autoprop v0.46.1
82 - go.opentelemetry.io/otel v1.37.0
83 - go.opentelemetry.io/otel/sdk v1.37.0
84 - go.opentelemetry.io/otel/trace v1.37.0
82 + go.opentelemetry.io/otel v1.38.0
83 + go.opentelemetry.io/otel/sdk v1.38.0
84 + go.opentelemetry.io/otel/trace v1.38.0
85 go.uber.org/dig v1.19.0
86 go.uber.org/fx v1.24.0
87 go.uber.org/zap v1.27.0
88 golang.org/x/crypto v0.41.0
89 - golang.org/x/exp v0.0.0-20250813145105-42675adae3e6
89 + golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b
90 golang.org/x/mod v0.27.0
91 - golang.org/x/sync v0.16.0
92 - golang.org/x/sys v0.35.0
93 - google.golang.org/protobuf v1.36.7
91 + golang.org/x/sync v0.17.0
92 + golang.org/x/sys v0.36.0
93 + google.golang.org/protobuf v1.36.9
94 )
95
96 require (
@@ -102,7 +102,7 @@ require (
102 github.com/benbjohnson/clock v1.3.5 // indirect
103 github.com/beorn7/perks v1.0.1 // indirect
104 github.com/caddyserver/zerossl v0.1.3 // indirect
105 - github.com/cenkalti/backoff/v5 v5.0.2 // indirect
105 + github.com/cenkalti/backoff/v5 v5.0.3 // indirect
106 github.com/cespare/xxhash v1.1.0 // indirect
107 github.com/cespare/xxhash/v2 v2.3.0 // indirect
108 github.com/cockroachdb/crlib v0.0.0-20241015224233-894974b3ad94 // indirect
@@ -124,11 +124,11 @@ require (
124 github.com/felixge/httpsnoop v1.0.4 // indirect
125 github.com/flynn/noise v1.1.0 // indirect
126 github.com/francoispqt/gojay v1.2.13 // indirect
127 - github.com/gabriel-vasile/mimetype v1.4.9 // indirect
127 + github.com/gabriel-vasile/mimetype v1.4.10 // indirect
128 github.com/gammazero/chanqueue v1.1.1 // indirect
129 github.com/gammazero/deque v1.1.0 // indirect
130 github.com/getsentry/sentry-go v0.27.0 // indirect
131 - github.com/go-jose/go-jose/v4 v4.0.5 // indirect
131 + github.com/go-jose/go-jose/v4 v4.1.1 // indirect
132 github.com/go-kit/log v0.2.1 // indirect
133 github.com/go-logfmt/logfmt v0.6.0 // indirect
134 github.com/go-logr/logr v1.4.3 // indirect
@@ -140,12 +140,14 @@ require (
140 github.com/google/gopacket v1.1.19 // indirect
141 github.com/gorilla/mux v1.8.1 // indirect
142 github.com/gorilla/websocket v1.5.3 // indirect
143 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 // indirect
143 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
144 + github.com/guillaumemichel/reservedpool v0.2.0 // indirect
145 github.com/hashicorp/golang-lru v1.0.2 // indirect
146 github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
147 github.com/huin/goupnp v1.3.0 // indirect
148 github.com/ipfs/bbloom v0.0.4 // indirect
149 github.com/ipfs/go-bitfield v1.1.0 // indirect
150 + github.com/ipfs/go-dsqueue v0.0.5 // indirect
151 github.com/ipfs/go-ipfs-ds-help v1.1.1 // indirect
152 github.com/ipfs/go-ipfs-pq v0.0.3 // indirect
153 github.com/ipfs/go-ipfs-redirects-file v0.1.2 // indirect
@@ -209,8 +211,9 @@ require (
211 github.com/pkg/errors v0.9.1 // indirect
212 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
213 github.com/polydawn/refmt v0.89.0 // indirect
214 + github.com/probe-lab/go-libdht v0.2.1 // indirect
215 github.com/prometheus/client_model v0.6.2 // indirect
213 - github.com/prometheus/common v0.65.0 // indirect
216 + github.com/prometheus/common v0.66.1 // indirect
217 github.com/prometheus/procfs v0.17.0 // indirect
218 github.com/prometheus/statsd_exporter v0.27.1 // indirect
219 github.com/quic-go/qpack v0.5.1 // indirect
@@ -237,28 +240,29 @@ require (
240 go.opentelemetry.io/contrib/propagators/b3 v1.21.1 // indirect
241 go.opentelemetry.io/contrib/propagators/jaeger v1.21.1 // indirect
242 go.opentelemetry.io/contrib/propagators/ot v1.21.1 // indirect
240 - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 // indirect
241 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0 // indirect
242 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 // indirect
243 - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 // indirect
244 - go.opentelemetry.io/otel/exporters/zipkin v1.37.0 // indirect
245 - go.opentelemetry.io/otel/metric v1.37.0 // indirect
246 - go.opentelemetry.io/proto/otlp v1.7.0 // indirect
243 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect
244 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 // indirect
245 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 // indirect
246 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0 // indirect
247 + go.opentelemetry.io/otel/exporters/zipkin v1.38.0 // indirect
248 + go.opentelemetry.io/otel/metric v1.38.0 // indirect
249 + go.opentelemetry.io/proto/otlp v1.7.1 // indirect
250 go.uber.org/mock v0.5.2 // indirect
251 go.uber.org/multierr v1.11.0 // indirect
252 go.uber.org/zap/exp v0.3.0 // indirect
253 + go.yaml.in/yaml/v2 v2.4.2 // indirect
254 go4.org v0.0.0-20230225012048-214862532bf5 // indirect
255 golang.org/x/net v0.43.0 // indirect
252 - golang.org/x/oauth2 v0.30.0 // indirect
256 + golang.org/x/oauth2 v0.31.0 // indirect
257 golang.org/x/term v0.34.0 // indirect
258 golang.org/x/text v0.28.0 // indirect
259 golang.org/x/time v0.12.0 // indirect
260 golang.org/x/tools v0.36.0 // indirect
261 golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
262 gonum.org/v1/gonum v0.16.0 // indirect
259 - google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
260 - google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
261 - google.golang.org/grpc v1.73.0 // indirect
263 + google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
264 + google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect
265 + google.golang.org/grpc v1.75.0 // indirect
266 gopkg.in/yaml.v2 v2.4.0 // indirect
267 gopkg.in/yaml.v3 v3.0.1 // indirect
268 lukechampine.com/blake3 v1.4.1 // indirect
go.sum
+72 -64
@@ -94,8 +94,8 @@ github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+Y
94 github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
95 github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
96 github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
97 -github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8=
98 -github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
97 +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
98 +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
99 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
100 github.com/ceramicnetwork/go-dag-jose v0.1.1 h1:7pObs22egc14vSS3AfCFfS1VmaL4lQUsAK7OGC3PlKk=
101 github.com/ceramicnetwork/go-dag-jose v0.1.1/go.mod h1:8ptnYwY2Z2y/s5oJnNBn/UCxLg6CpramNJ2ZXF/5aNY=
@@ -197,8 +197,8 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4
197 github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
198 github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
199 github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
200 -github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
201 -github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
200 +github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
201 +github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
202 github.com/gammazero/chanqueue v1.1.1 h1:n9Y+zbBxw2f7uUE9wpgs0rOSkP/I/yhDLiNuhyVjojQ=
203 github.com/gammazero/chanqueue v1.1.1/go.mod h1:fMwpwEiuUgpab0sH4VHiVcEoji1pSi+EIzeG4TPeKPc=
204 github.com/gammazero/deque v1.1.0 h1:OyiyReBbnEG2PP0Bnv1AASLIYvyKqIFN5xfl1t8oGLo=
@@ -216,8 +216,8 @@ github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3Bop
216 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
217 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
218 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
219 -github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
220 -github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
219 +github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI=
220 +github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA=
221 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
222 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
223 github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
@@ -329,8 +329,10 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN
329 github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
330 github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
331 github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
332 -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww=
333 -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90=
332 +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
333 +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
334 +github.com/guillaumemichel/reservedpool v0.2.0 h1:q73gtdMFJHtW+dDJ/fwtk34p7JprQv8fJSK7dEjf8Sw=
335 +github.com/guillaumemichel/reservedpool v0.2.0/go.mod h1:sXSDIaef81TFdAJglsCFCMfgF5E5Z5xK1tFhjDhvbUc=
336 github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU=
337 github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48=
338 github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
@@ -354,8 +356,8 @@ github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 h1:OqNqsGZPX8zh3eFMO8Lf8EHRRnSGBMqcd
356 github.com/ipfs-shipyard/nopfs/ipfs v0.25.0/go.mod h1:BxhUdtBgOXg1B+gAPEplkg/GpyTZY+kCMSfsJvvydqU=
357 github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
358 github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
357 -github.com/ipfs/boxo v0.34.1-0.20250909170220-e69f67e94c11 h1:EsCbOKE+giLtrFTysnbTzIRQENOiLdcpOY3kV3y6wlU=
358 -github.com/ipfs/boxo v0.34.1-0.20250909170220-e69f67e94c11/go.mod h1:rXql6ncaLZZfLqDG3Cuw9ZYQKd3rMU5bk1TGXF0+ZL0=
359 +github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3 h1:qp8w52Rf5eEOrNFZ1VdLSOU3kA5N2EGMNv0xZAACSfs=
360 +github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3/go.mod h1:YbQ2GM5GolkfJ8qB29RL+cXgFEa/HsDrHeHSB+fOrlY=
361 github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
362 github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
363 github.com/ipfs/go-block-format v0.0.3/go.mod h1:4LmD4ZUw0mhO+JSKdpWwrzATiEfM7WWgQ8H5l6P8MVk=
@@ -370,8 +372,8 @@ github.com/ipfs/go-cidutil v0.1.0 h1:RW5hO7Vcf16dplUU60Hs0AKDkQAVPVplr7lk97CFL+Q
372 github.com/ipfs/go-cidutil v0.1.0/go.mod h1:e7OEVBMIv9JaOxt9zaGEmAoSlXW9jdFZ5lP/0PwcfpA=
373 github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE=
374 github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw=
373 -github.com/ipfs/go-datastore v0.8.3 h1:z391GsQyGKUIUof2tPoaZVeDknbt7fNHs6Gqjcw5Jo4=
374 -github.com/ipfs/go-datastore v0.8.3/go.mod h1:raxQ/CreIy9L6MxT71ItfMX12/ASN6EhXJoUFjICQ2M=
375 +github.com/ipfs/go-datastore v0.8.4 h1:vXEsd76T3KIOSKXizjhmS3ICGMl+oOSjpLSxE3v8/Wc=
376 +github.com/ipfs/go-datastore v0.8.4/go.mod h1:uT77w/XEGrvJWwHgdrMr8bqCN6ZTW9gzmi+3uK+ouHg=
377 github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
378 github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
379 github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk=
@@ -386,6 +388,8 @@ github.com/ipfs/go-ds-measure v0.2.2 h1:4kwvBGbbSXNYe4ANlg7qTIYoZU6mNlqzQHdVqICk
388 github.com/ipfs/go-ds-measure v0.2.2/go.mod h1:b/87ak0jMgH9Ylt7oH0+XGy4P8jHx9KG09Qz+pOeTIs=
389 github.com/ipfs/go-ds-pebble v0.5.1 h1:p0FAE0zw9J/3T1VkGB9s98jWmfKmw2t0iEwfMUv8iSQ=
390 github.com/ipfs/go-ds-pebble v0.5.1/go.mod h1:LsmQx4w+0o9znl4hTxYo1Y2lnBTzNCwc4kNpD3wWXM0=
391 +github.com/ipfs/go-dsqueue v0.0.5 h1:TUOk15TlCJ/NKV8Yk2W5wgkEjDa44Nem7a7FGIjsMNU=
392 +github.com/ipfs/go-dsqueue v0.0.5/go.mod h1:i/jAlpZjBbQJLioN+XKbFgnd+u9eAhGZs9IrqIzTd9g=
393 github.com/ipfs/go-fs-lock v0.1.1 h1:TecsP/Uc7WqYYatasreZQiP9EGRy4ZnKoG4yXxR33nw=
394 github.com/ipfs/go-fs-lock v0.1.1/go.mod h1:2goSXMCw7QfscHmSe09oXiR34DQeUdm+ei+dhonqly0=
395 github.com/ipfs/go-ipfs-blockstore v1.3.1 h1:cEI9ci7V0sRNivqaOr0elDsamxXFxJMMMy7PTTDQNsQ=
@@ -426,8 +430,8 @@ github.com/ipfs/go-test v0.2.3 h1:Z/jXNAReQFtCYyn7bsv/ZqUwS6E7iIcSpJ2CuzCvnrc=
430 github.com/ipfs/go-test v0.2.3/go.mod h1:QW8vSKkwYvWFwIZQLGQXdkt9Ud76eQXRQ9Ao2H+cA1o=
431 github.com/ipfs/go-unixfsnode v1.10.1 h1:hGKhzuH6NSzZ4y621wGuDspkjXRNG3B+HqhlyTjSwSM=
432 github.com/ipfs/go-unixfsnode v1.10.1/go.mod h1:eguv/otvacjmfSbYvmamc9ssNAzLvRk0+YN30EYeOOY=
429 -github.com/ipld/go-car/v2 v2.14.3 h1:1Mhl82/ny8MVP+w1M4LXbj4j99oK3gnuZG2GmG1IhC8=
430 -github.com/ipld/go-car/v2 v2.14.3/go.mod h1:/vpSvPngOX8UnvmdFJ3o/mDgXa9LuyXsn7wxOzHDYQE=
433 +github.com/ipld/go-car/v2 v2.15.0 h1:RxtZcGXFx72zFESl+UUsCNQV2YMcy3gEMYx9M3uio24=
434 +github.com/ipld/go-car/v2 v2.15.0/go.mod h1:ovlq/n3xlVJDmoiN3Kd/Z7kIzQbdTIFSwltfOP+qIgk=
435 github.com/ipld/go-codec-dagpb v1.7.0 h1:hpuvQjCSVSLnTnHXn+QAMR0mLmb1gA6wl10LExo2Ts0=
436 github.com/ipld/go-codec-dagpb v1.7.0/go.mod h1:rD3Zg+zub9ZnxcLwfol/OTQRVjaLzXypgy4UqHQvilM=
437 github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8=
@@ -512,11 +516,11 @@ github.com/libp2p/go-libp2p-gostream v0.6.0 h1:QfAiWeQRce6pqnYfmIVWJFXNdDyfiR/qk
516 github.com/libp2p/go-libp2p-gostream v0.6.0/go.mod h1:Nywu0gYZwfj7Jc91PQvbGU8dIpqbQQkjWgDuOrFaRdA=
517 github.com/libp2p/go-libp2p-http v0.5.0 h1:+x0AbLaUuLBArHubbbNRTsgWz0RjNTy6DJLOxQ3/QBc=
518 github.com/libp2p/go-libp2p-http v0.5.0/go.mod h1:glh87nZ35XCQyFsdzZps6+F4HYI6DctVFY5u1fehwSg=
515 -github.com/libp2p/go-libp2p-kad-dht v0.34.0 h1:yvJ/Vrt36GVjsqPxiGcuuwOloKuZLV9Aa7awIKyNXy0=
516 -github.com/libp2p/go-libp2p-kad-dht v0.34.0/go.mod h1:JNbkES4W5tajS6uYivw6MPs0842cPHAwhgaPw8sQG4o=
519 +github.com/libp2p/go-libp2p-kad-dht v0.34.1-0.20250918150625-2e3cea182b63 h1:XQSASQ9N5haD/uYmop/633tYMZNsM+lKKI8/Is30w4o=
520 +github.com/libp2p/go-libp2p-kad-dht v0.34.1-0.20250918150625-2e3cea182b63/go.mod h1:HbI1rUTFF87WHklzKTGZC8Oys9+1rkKyqvmSZcAW55Y=
521 github.com/libp2p/go-libp2p-kbucket v0.3.1/go.mod h1:oyjT5O7tS9CQurok++ERgc46YLwEpuGoFq9ubvoUOio=
518 -github.com/libp2p/go-libp2p-kbucket v0.7.0 h1:vYDvRjkyJPeWunQXqcW2Z6E93Ywx7fX0jgzb/dGOKCs=
519 -github.com/libp2p/go-libp2p-kbucket v0.7.0/go.mod h1:blOINGIj1yiPYlVEX0Rj9QwEkmVnz3EP8LK1dRKBC6g=
522 +github.com/libp2p/go-libp2p-kbucket v0.8.0 h1:QAK7RzKJpYe+EuSEATAaaHYMYLkPDGC18m9jxPLnU8s=
523 +github.com/libp2p/go-libp2p-kbucket v0.8.0/go.mod h1:JMlxqcEyKwO6ox716eyC0hmiduSWZZl6JY93mGaaqc4=
524 github.com/libp2p/go-libp2p-peerstore v0.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVdLxvqh7hXOujessqdzs=
525 github.com/libp2p/go-libp2p-pubsub v0.14.2 h1:nT5lFHPQOFJcp9CW8hpKtvbpQNdl2udJuzLQWbgRum8=
526 github.com/libp2p/go-libp2p-pubsub v0.14.2/go.mod h1:MKPU5vMI8RRFyTP0HfdsF9cLmL1nHAeJm44AxJGJx44=
@@ -726,6 +730,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH
730 github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o=
731 github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4=
732 github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw=
733 +github.com/probe-lab/go-libdht v0.2.1 h1:oBCsKBvS/OVirTO5+BT6/AOocWjdqwpfSfkTfBjUPJE=
734 +github.com/probe-lab/go-libdht v0.2.1/go.mod h1:q+WlGiqs/UIRfdhw9Gmc+fPoAYlOim7VvXTjOI6KJmQ=
735 github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
736 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
737 github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
@@ -734,8 +740,8 @@ github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqr
740 github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
741 github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
742 github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
737 -github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
738 -github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=
743 +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
744 +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
745 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
746 github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
747 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -749,8 +755,8 @@ github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9
755 github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
756 github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
757 github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
752 -github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
753 -github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
758 +github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
759 +github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
760 github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
761 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
762 github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
@@ -848,8 +854,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
854 github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
855 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
856 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
851 -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
852 -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
857 +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
858 +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
859 github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
860 github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
861 github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs=
@@ -924,8 +930,8 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
930 go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
931 go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
932 go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
927 -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 h1:Hf9xI/XLML9ElpiHVDNwvqI0hIFlzV8dgIr35kV1kRU=
928 -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0/go.mod h1:NfchwuyNoMcZ5MLHwPrODwUF1HWCXWrL31s8gSAdIKY=
933 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18=
934 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg=
935 go.opentelemetry.io/contrib/propagators/autoprop v0.46.1 h1:cXTYcMjY0dsYokAuo8LbNBQxpF8VgTHdiHJJ1zlIXl4=
936 go.opentelemetry.io/contrib/propagators/autoprop v0.46.1/go.mod h1:WZxgny1/6+j67B1s72PLJ4bGjidoWFzSmLNfJKVt2bo=
937 go.opentelemetry.io/contrib/propagators/aws v1.21.1 h1:uQIQIDWb0gzyvon2ICnghpLAf9w7ADOCUiIiwCQgR2o=
@@ -936,28 +942,28 @@ go.opentelemetry.io/contrib/propagators/jaeger v1.21.1 h1:f4beMGDKiVzg9IcX7/VuWV
942 go.opentelemetry.io/contrib/propagators/jaeger v1.21.1/go.mod h1:U9jhkEl8d1LL+QXY7q3kneJWJugiN3kZJV2OWz3hkBY=
943 go.opentelemetry.io/contrib/propagators/ot v1.21.1 h1:3TN5vkXjKYWp0YdMcnUEC/A+pBPvqz9V3nCS2xmcurk=
944 go.opentelemetry.io/contrib/propagators/ot v1.21.1/go.mod h1:oy0MYCbS/b3cqUDW37wBWtlwBIsutngS++Lklpgh+fc=
939 -go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
940 -go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
941 -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 h1:Ahq7pZmv87yiyn3jeFz/LekZmPLLdKejuO3NcK9MssM=
942 -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0/go.mod h1:MJTqhM0im3mRLw1i8uGHnCvUEeS7VwRyxlLC78PA18M=
943 -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0 h1:EtFWSnwW9hGObjkIdmlnWSydO+Qs8OwzfzXLUPg4xOc=
944 -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0/go.mod h1:QjUEoiGCPkvFZ/MjK6ZZfNOS6mfVEVKYE99dFhuN2LI=
945 -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 h1:bDMKF3RUSxshZ5OjOTi8rsHGaPKsAt76FaqgvIUySLc=
946 -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0/go.mod h1:dDT67G/IkA46Mr2l9Uj7HsQVwsjASyV9SjGofsiUZDA=
947 -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 h1:SNhVp/9q4Go/XHBkQ1/d5u9P/U+L1yaGPoi0x+mStaI=
948 -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0/go.mod h1:tx8OOlGH6R4kLV67YaYO44GFXloEjGPZuMjEkaaqIp4=
949 -go.opentelemetry.io/otel/exporters/zipkin v1.37.0 h1:Z2apuaRnHEjzDAkpbWNPiksz1R0/FCIrJSjiMA43zwI=
950 -go.opentelemetry.io/otel/exporters/zipkin v1.37.0/go.mod h1:ofGu/7fG+bpmjZoiPUUmYDJ4vXWxMT57HmGoegx49uw=
951 -go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
952 -go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
953 -go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
954 -go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
955 -go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
956 -go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
957 -go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
958 -go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
959 -go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os=
960 -go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo=
945 +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
946 +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
947 +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24=
948 +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU=
949 +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 h1:lwI4Dc5leUqENgGuQImwLo4WnuXFPetmPpkLi2IrX54=
950 +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0/go.mod h1:Kz/oCE7z5wuyhPxsXDuaPteSWqjSBD5YaSdbxZYGbGk=
951 +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 h1:aTL7F04bJHUlztTsNGJ2l+6he8c+y/b//eR0jjjemT4=
952 +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4=
953 +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0 h1:kJxSDN4SgWWTjG/hPp3O7LCGLcHXFlvS2/FFOrwL+SE=
954 +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0/go.mod h1:mgIOzS7iZeKJdeB8/NYHrJ48fdGc71Llo5bJ1J4DWUE=
955 +go.opentelemetry.io/otel/exporters/zipkin v1.38.0 h1:0rJ2TmzpHDG+Ib9gPmu3J3cE0zXirumQcKS4wCoZUa0=
956 +go.opentelemetry.io/otel/exporters/zipkin v1.38.0/go.mod h1:Su/nq/K5zRjDKKC3Il0xbViE3juWgG3JDoqLumFx5G0=
957 +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
958 +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
959 +go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
960 +go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
961 +go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
962 +go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
963 +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
964 +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
965 +go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4=
966 +go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE=
967 go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
968 go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
969 go.uber.org/dig v1.19.0 h1:BACLhebsYdpQ7IROQ1AGPjrXcP5dF80U3gKoFzbaq/4=
@@ -974,6 +980,8 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
980 go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
981 go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U=
982 go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ=
983 +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
984 +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
985 go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
986 go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc=
987 go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU=
@@ -1009,8 +1017,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
1017 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
1018 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
1019 golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
1012 -golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 h1:SbTAbRFnd5kjQXbczszQ0hdk3ctwYf3qBNH9jIsGclE=
1013 -golang.org/x/exp v0.0.0-20250813145105-42675adae3e6/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
1020 +golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0=
1021 +golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
1022 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
1023 golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
1024 golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -1098,8 +1106,8 @@ golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4Iltr
1106 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
1107 golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
1108 golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
1101 -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
1102 -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
1109 +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo=
1110 +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
1111 golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
1112 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
1113 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1115,8 +1123,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
1123 golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
1124 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
1125 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
1118 -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
1119 -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
1126 +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
1127 +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
1128 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
1129 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
1130 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1184,8 +1192,8 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
1192 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
1193 golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
1194 golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
1187 -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
1188 -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
1195 +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
1196 +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
1197 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
1198 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
1199 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -1337,10 +1345,10 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc
1345 google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
1346 google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
1347 google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
1340 -google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY=
1341 -google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc=
1342 -google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE=
1343 -google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
1348 +google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY=
1349 +google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE=
1350 +google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE=
1351 +google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc=
1352 google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
1353 google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
1354 google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
@@ -1357,8 +1365,8 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji
1365 google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
1366 google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
1367 google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
1360 -google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
1361 -google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
1368 +google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4=
1369 +google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
1370 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
1371 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
1372 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -1373,8 +1381,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
1381 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
1382 google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
1383 google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
1376 -google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A=
1377 -google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
1384 +google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
1385 +google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
1386 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
1387 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
1388 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
test/cli/provider_test.go
+172 -120
@@ -12,17 +12,28 @@ import (
12 "github.com/stretchr/testify/require"
13 )
14
15 -func TestProvider(t *testing.T) {
16 - t.Parallel()
15 +const (
16 + timeStep = 20 * time.Millisecond
17 + timeout = time.Second
18 +)
19 +
20 +type cfgApplier func(*harness.Node)
21 +
22 +func runProviderSuite(t *testing.T, reprovide bool, apply cfgApplier) {
23 + t.Helper()
24
25 initNodes := func(t *testing.T, n int, fn func(n *harness.Node)) harness.Nodes {
26 nodes := harness.NewT(t).NewNodes(n).Init()
27 + nodes.ForEachPar(apply)
28 nodes.ForEachPar(fn)
21 - return nodes.StartDaemons().Connect()
29 + nodes = nodes.StartDaemons().Connect()
30 + time.Sleep(500 * time.Millisecond) // wait for DHT clients to be bootstrapped
31 + return nodes
32 }
33
34 initNodesWithoutStart := func(t *testing.T, n int, fn func(n *harness.Node)) harness.Nodes {
35 nodes := harness.NewT(t).NewNodes(n).Init()
36 + nodes.ForEachPar(apply)
37 nodes.ForEachPar(fn)
38 return nodes
39 }
@@ -35,9 +46,15 @@ func TestProvider(t *testing.T) {
46 }
47
48 expectProviders := func(t *testing.T, cid, expectedProvider string, nodes ...*harness.Node) {
49 + outerLoop:
50 for _, node := range nodes {
39 - res := node.IPFS("routing", "findprovs", "-n=1", cid)
40 - require.Equal(t, expectedProvider, res.Stdout.Trimmed())
51 + for i := time.Duration(0); i*timeStep < timeout; i++ {
52 + res := node.IPFS("routing", "findprovs", "-n=1", cid)
53 + if res.Stdout.Trimmed() == expectedProvider {
54 + continue outerLoop
55 + }
56 + }
57 + require.FailNowf(t, "found no providers", "expected a provider for %s", cid)
58 }
59 }
60
@@ -260,164 +277,167 @@ func TestProvider(t *testing.T) {
277 expectProviders(t, cid, nodes[0].PeerID().String(), nodes[1:]...)
278 })
279
263 - t.Run("Reprovides with 'all' strategy when strategy is '' (empty)", func(t *testing.T) {
264 - t.Parallel()
280 + if reprovide {
281
266 - nodes := initNodesWithoutStart(t, 2, func(n *harness.Node) {
267 - n.SetIPFSConfig("Reprovider.Strategy", "")
268 - })
269 -
270 - cid := nodes[0].IPFSAddStr(time.Now().String())
282 + t.Run("Reprovides with 'all' strategy when strategy is '' (empty)", func(t *testing.T) {
283 + t.Parallel()
284
272 - nodes = nodes.StartDaemons().Connect()
273 - defer nodes.StopDaemons()
274 - expectNoProviders(t, cid, nodes[1:]...)
285 + nodes := initNodesWithoutStart(t, 2, func(n *harness.Node) {
286 + n.SetIPFSConfig("Reprovider.Strategy", "")
287 + })
288
276 - nodes[0].IPFS("routing", "reprovide")
289 + cid := nodes[0].IPFSAddStr(time.Now().String())
290
278 - expectProviders(t, cid, nodes[0].PeerID().String(), nodes[1:]...)
279 - })
291 + nodes = nodes.StartDaemons().Connect()
292 + defer nodes.StopDaemons()
293 + expectNoProviders(t, cid, nodes[1:]...)
294
281 - t.Run("Reprovides with 'all' strategy", func(t *testing.T) {
282 - t.Parallel()
295 + nodes[0].IPFS("routing", "reprovide")
296
284 - nodes := initNodesWithoutStart(t, 2, func(n *harness.Node) {
285 - n.SetIPFSConfig("Reprovider.Strategy", "all")
297 + expectProviders(t, cid, nodes[0].PeerID().String(), nodes[1:]...)
298 })
299
288 - cid := nodes[0].IPFSAddStr(time.Now().String())
300 + t.Run("Reprovides with 'all' strategy", func(t *testing.T) {
301 + t.Parallel()
302
290 - nodes = nodes.StartDaemons().Connect()
291 - defer nodes.StopDaemons()
292 - expectNoProviders(t, cid, nodes[1:]...)
303 + nodes := initNodesWithoutStart(t, 2, func(n *harness.Node) {
304 + n.SetIPFSConfig("Reprovider.Strategy", "all")
305 + })
306
294 - nodes[0].IPFS("routing", "reprovide")
307 + cid := nodes[0].IPFSAddStr(time.Now().String())
308
296 - expectProviders(t, cid, nodes[0].PeerID().String(), nodes[1:]...)
297 - })
309 + nodes = nodes.StartDaemons().Connect()
310 + defer nodes.StopDaemons()
311 + expectNoProviders(t, cid, nodes[1:]...)
312
299 - t.Run("Reprovides with 'pinned' strategy", func(t *testing.T) {
300 - t.Parallel()
313 + nodes[0].IPFS("routing", "reprovide")
314
302 - foo := random.Bytes(1000)
303 - bar := random.Bytes(1000)
304 -
305 - nodes := initNodesWithoutStart(t, 2, func(n *harness.Node) {
306 - n.SetIPFSConfig("Reprovider.Strategy", "pinned")
315 + expectProviders(t, cid, nodes[0].PeerID().String(), nodes[1:]...)
316 })
317
309 - // Add a pin while offline so it cannot be provided
310 - cidBarDir := nodes[0].IPFSAdd(bytes.NewReader(bar), "-Q", "-w")
318 + t.Run("Reprovides with 'pinned' strategy", func(t *testing.T) {
319 + t.Parallel()
320
312 - nodes = nodes.StartDaemons().Connect()
313 - defer nodes.StopDaemons()
321 + foo := random.Bytes(1000)
322 + bar := random.Bytes(1000)
323
315 - // Add content without pinning while daemon line
316 - cidFoo := nodes[0].IPFSAdd(bytes.NewReader(foo), "--pin=false")
317 - cidBar := nodes[0].IPFSAdd(bytes.NewReader(bar), "--pin=false")
324 + nodes := initNodesWithoutStart(t, 2, func(n *harness.Node) {
325 + n.SetIPFSConfig("Reprovider.Strategy", "pinned")
326 + })
327
319 - // Nothing should have been provided. The pin was offline, and
320 - // the others should not be provided per the strategy.
321 - expectNoProviders(t, cidFoo, nodes[1:]...)
322 - expectNoProviders(t, cidBar, nodes[1:]...)
323 - expectNoProviders(t, cidBarDir, nodes[1:]...)
328 + // Add a pin while offline so it cannot be provided
329 + cidBarDir := nodes[0].IPFSAdd(bytes.NewReader(bar), "-Q", "-w")
330
325 - nodes[0].IPFS("routing", "reprovide")
331 + nodes = nodes.StartDaemons().Connect()
332 + defer nodes.StopDaemons()
333
327 - // cidFoo is not pinned so should not be provided.
328 - expectNoProviders(t, cidFoo, nodes[1:]...)
329 - // cidBar gets provided by being a child from cidBarDir even though we added with pin=false.
330 - expectProviders(t, cidBar, nodes[0].PeerID().String(), nodes[1:]...)
331 - expectProviders(t, cidBarDir, nodes[0].PeerID().String(), nodes[1:]...)
332 - })
334 + // Add content without pinning while daemon line
335 + cidFoo := nodes[0].IPFSAdd(bytes.NewReader(foo), "--pin=false")
336 + cidBar := nodes[0].IPFSAdd(bytes.NewReader(bar), "--pin=false")
337
334 - t.Run("Reprovides with 'roots' strategy", func(t *testing.T) {
335 - t.Parallel()
338 + // Nothing should have been provided. The pin was offline, and
339 + // the others should not be provided per the strategy.
340 + expectNoProviders(t, cidFoo, nodes[1:]...)
341 + expectNoProviders(t, cidBar, nodes[1:]...)
342 + expectNoProviders(t, cidBarDir, nodes[1:]...)
343
337 - foo := random.Bytes(1000)
338 - bar := random.Bytes(1000)
344 + nodes[0].IPFS("routing", "reprovide")
345
340 - nodes := initNodesWithoutStart(t, 2, func(n *harness.Node) {
341 - n.SetIPFSConfig("Reprovider.Strategy", "roots")
346 + // cidFoo is not pinned so should not be provided.
347 + expectNoProviders(t, cidFoo, nodes[1:]...)
348 + // cidBar gets provided by being a child from cidBarDir even though we added with pin=false.
349 + expectProviders(t, cidBar, nodes[0].PeerID().String(), nodes[1:]...)
350 + expectProviders(t, cidBarDir, nodes[0].PeerID().String(), nodes[1:]...)
351 })
343 - n0pid := nodes[0].PeerID().String()
352
345 - // Add a pin. Only root should get pinned but not provided
346 - // because node not started
347 - cidBarDir := nodes[0].IPFSAdd(bytes.NewReader(bar), "-Q", "-w")
353 + t.Run("Reprovides with 'roots' strategy", func(t *testing.T) {
354 + t.Parallel()
355
349 - nodes = nodes.StartDaemons().Connect()
350 - defer nodes.StopDaemons()
356 + foo := random.Bytes(1000)
357 + bar := random.Bytes(1000)
358
352 - cidFoo := nodes[0].IPFSAdd(bytes.NewReader(foo))
353 - cidBar := nodes[0].IPFSAdd(bytes.NewReader(bar), "--pin=false")
359 + nodes := initNodesWithoutStart(t, 2, func(n *harness.Node) {
360 + n.SetIPFSConfig("Reprovider.Strategy", "roots")
361 + })
362 + n0pid := nodes[0].PeerID().String()
363
355 - // cidFoo will get provided per the strategy but cidBar will not.
356 - expectProviders(t, cidFoo, n0pid, nodes[1:]...)
357 - expectNoProviders(t, cidBar, nodes[1:]...)
364 + // Add a pin. Only root should get pinned but not provided
365 + // because node not started
366 + cidBarDir := nodes[0].IPFSAdd(bytes.NewReader(bar), "-Q", "-w")
367
359 - nodes[0].IPFS("routing", "reprovide")
368 + nodes = nodes.StartDaemons().Connect()
369 + defer nodes.StopDaemons()
370
361 - expectProviders(t, cidFoo, n0pid, nodes[1:]...)
362 - expectNoProviders(t, cidBar, nodes[1:]...)
363 - expectProviders(t, cidBarDir, n0pid, nodes[1:]...)
364 - })
371 + cidFoo := nodes[0].IPFSAdd(bytes.NewReader(foo))
372 + cidBar := nodes[0].IPFSAdd(bytes.NewReader(bar), "--pin=false")
373
366 - t.Run("Reprovides with 'mfs' strategy", func(t *testing.T) {
367 - t.Parallel()
374 + // cidFoo will get provided per the strategy but cidBar will not.
375 + expectProviders(t, cidFoo, n0pid, nodes[1:]...)
376 + expectNoProviders(t, cidBar, nodes[1:]...)
377
369 - bar := random.Bytes(1000)
378 + nodes[0].IPFS("routing", "reprovide")
379
371 - nodes := initNodesWithoutStart(t, 2, func(n *harness.Node) {
372 - n.SetIPFSConfig("Reprovider.Strategy", "mfs")
380 + expectProviders(t, cidFoo, n0pid, nodes[1:]...)
381 + expectNoProviders(t, cidBar, nodes[1:]...)
382 + expectProviders(t, cidBarDir, n0pid, nodes[1:]...)
383 })
374 - n0pid := nodes[0].PeerID().String()
384
376 - // add something and lets put it in MFS
377 - cidBar := nodes[0].IPFSAdd(bytes.NewReader(bar), "--pin=false", "-Q")
378 - nodes[0].IPFS("files", "cp", "/ipfs/"+cidBar, "/myfile")
385 + t.Run("Reprovides with 'mfs' strategy", func(t *testing.T) {
386 + t.Parallel()
387
380 - nodes = nodes.StartDaemons().Connect()
381 - defer nodes.StopDaemons()
388 + bar := random.Bytes(1000)
389
383 - // cidBar is in MFS but not provided
384 - expectNoProviders(t, cidBar, nodes[1:]...)
390 + nodes := initNodesWithoutStart(t, 2, func(n *harness.Node) {
391 + n.SetIPFSConfig("Reprovider.Strategy", "mfs")
392 + })
393 + n0pid := nodes[0].PeerID().String()
394
386 - nodes[0].IPFS("routing", "reprovide")
395 + // add something and lets put it in MFS
396 + cidBar := nodes[0].IPFSAdd(bytes.NewReader(bar), "--pin=false", "-Q")
397 + nodes[0].IPFS("files", "cp", "/ipfs/"+cidBar, "/myfile")
398
388 - // And now is provided
389 - expectProviders(t, cidBar, n0pid, nodes[1:]...)
390 - })
399 + nodes = nodes.StartDaemons().Connect()
400 + defer nodes.StopDaemons()
401
392 - t.Run("Reprovides with 'pinned+mfs' strategy", func(t *testing.T) {
393 - t.Parallel()
394 -
395 - nodes := initNodesWithoutStart(t, 2, func(n *harness.Node) {
396 - n.SetIPFSConfig("Reprovider.Strategy", "pinned+mfs")
397 - })
398 - n0pid := nodes[0].PeerID().String()
402 + // cidBar is in MFS but not provided
403 + expectNoProviders(t, cidBar, nodes[1:]...)
404
400 - // Add a pinned CID (should be provided)
401 - cidPinned := nodes[0].IPFSAddStr("pinned content", "--pin=true")
402 - // Add a CID to MFS (should be provided)
403 - cidMFS := nodes[0].IPFSAddStr("mfs content")
404 - nodes[0].IPFS("files", "cp", "/ipfs/"+cidMFS, "/myfile")
405 - // Add a CID that is neither pinned nor in MFS (should not be provided)
406 - cidNeither := nodes[0].IPFSAddStr("neither content", "--pin=false")
405 + nodes[0].IPFS("routing", "reprovide")
406
408 - nodes = nodes.StartDaemons().Connect()
409 - defer nodes.StopDaemons()
410 -
411 - // Trigger reprovide
412 - nodes[0].IPFS("routing", "reprovide")
407 + // And now is provided
408 + expectProviders(t, cidBar, n0pid, nodes[1:]...)
409 + })
410
414 - // Check that pinned CID is provided
415 - expectProviders(t, cidPinned, n0pid, nodes[1:]...)
416 - // Check that MFS CID is provided
417 - expectProviders(t, cidMFS, n0pid, nodes[1:]...)
418 - // Check that neither CID is not provided
419 - expectNoProviders(t, cidNeither, nodes[1:]...)
420 - })
411 + t.Run("Reprovides with 'pinned+mfs' strategy", func(t *testing.T) {
412 + t.Parallel()
413 +
414 + nodes := initNodesWithoutStart(t, 2, func(n *harness.Node) {
415 + n.SetIPFSConfig("Reprovider.Strategy", "pinned+mfs")
416 + })
417 + n0pid := nodes[0].PeerID().String()
418 +
419 + // Add a pinned CID (should be provided)
420 + cidPinned := nodes[0].IPFSAddStr("pinned content", "--pin=true")
421 + // Add a CID to MFS (should be provided)
422 + cidMFS := nodes[0].IPFSAddStr("mfs content")
423 + nodes[0].IPFS("files", "cp", "/ipfs/"+cidMFS, "/myfile")
424 + // Add a CID that is neither pinned nor in MFS (should not be provided)
425 + cidNeither := nodes[0].IPFSAddStr("neither content", "--pin=false")
426 +
427 + nodes = nodes.StartDaemons().Connect()
428 + defer nodes.StopDaemons()
429 +
430 + // Trigger reprovide
431 + nodes[0].IPFS("routing", "reprovide")
432 +
433 + // Check that pinned CID is provided
434 + expectProviders(t, cidPinned, n0pid, nodes[1:]...)
435 + // Check that MFS CID is provided
436 + expectProviders(t, cidMFS, n0pid, nodes[1:]...)
437 + // Check that neither CID is not provided
438 + expectNoProviders(t, cidNeither, nodes[1:]...)
439 + })
440 + }
441
442 t.Run("provide clear command removes items from provide queue", func(t *testing.T) {
443 t.Parallel()
@@ -512,5 +532,37 @@ func TestProvider(t *testing.T) {
532 // Should be a non-negative integer (0 or positive)
533 assert.GreaterOrEqual(t, result, 0)
534 })
535 +}
536 +
537 +func TestProvider(t *testing.T) {
538 + t.Parallel()
539
540 + variants := []struct {
541 + name string
542 + reprovide bool
543 + apply cfgApplier
544 + }{
545 + {
546 + name: "LegacyProvider",
547 + reprovide: true,
548 + apply: func(n *harness.Node) {
549 + n.SetIPFSConfig("Reprovider.Sweep.Enabled", false)
550 + },
551 + },
552 + {
553 + name: "SweepingProvider",
554 + reprovide: false,
555 + apply: func(n *harness.Node) {
556 + n.SetIPFSConfig("Reprovider.Sweep.Enabled", true)
557 + },
558 + },
559 + }
560 +
561 + for _, v := range variants {
562 + v := v // capture
563 + t.Run(v.name, func(t *testing.T) {
564 + // t.Parallel()
565 + runProviderSuite(t, v.reprovide, v.apply)
566 + })
567 + }
568 }
test/dependencies/go.mod
+20 -17
@@ -89,7 +89,8 @@ require (
89 github.com/francoispqt/gojay v1.2.13 // indirect
90 github.com/fsnotify/fsnotify v1.8.0 // indirect
91 github.com/fzipp/gocyclo v0.6.0 // indirect
92 - github.com/gabriel-vasile/mimetype v1.4.9 // indirect
92 + github.com/gabriel-vasile/mimetype v1.4.10 // indirect
93 + github.com/gammazero/chanqueue v1.1.1 // indirect
94 github.com/gammazero/deque v1.1.0 // indirect
95 github.com/getsentry/sentry-go v0.27.0 // indirect
96 github.com/ghostiam/protogetter v0.3.9 // indirect
@@ -134,11 +135,12 @@ require (
135 github.com/huin/goupnp v1.3.0 // indirect
136 github.com/inconshreveable/mousetrap v1.1.0 // indirect
137 github.com/ipfs/bbloom v0.0.4 // indirect
137 - github.com/ipfs/boxo v0.34.1-0.20250909170220-e69f67e94c11 // indirect
138 + github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3 // indirect
139 github.com/ipfs/go-bitfield v1.1.0 // indirect
140 github.com/ipfs/go-block-format v0.2.2 // indirect
141 github.com/ipfs/go-cid v0.5.0 // indirect
141 - github.com/ipfs/go-datastore v0.8.3 // indirect
142 + github.com/ipfs/go-datastore v0.8.4 // indirect
143 + github.com/ipfs/go-dsqueue v0.0.5 // indirect
144 github.com/ipfs/go-ipfs-redirects-file v0.1.2 // indirect
145 github.com/ipfs/go-ipld-cbor v0.2.1 // indirect
146 github.com/ipfs/go-ipld-format v0.6.2 // indirect
@@ -146,7 +148,7 @@ require (
148 github.com/ipfs/go-metrics-interface v0.3.0 // indirect
149 github.com/ipfs/go-unixfsnode v1.10.1 // indirect
150 github.com/ipfs/kubo v0.31.0 // indirect
149 - github.com/ipld/go-car/v2 v2.14.3 // indirect
151 + github.com/ipld/go-car/v2 v2.15.0 // indirect
152 github.com/ipld/go-codec-dagpb v1.7.0 // indirect
153 github.com/ipld/go-ipld-prime v0.21.0 // indirect
154 github.com/ipshipyard/p2p-forge v0.6.1 // indirect
@@ -180,8 +182,8 @@ require (
182 github.com/libp2p/go-flow-metrics v0.3.0 // indirect
183 github.com/libp2p/go-libp2p v0.43.0 // indirect
184 github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
183 - github.com/libp2p/go-libp2p-kad-dht v0.34.0 // indirect
184 - github.com/libp2p/go-libp2p-kbucket v0.7.0 // indirect
185 + github.com/libp2p/go-libp2p-kad-dht v0.34.1-0.20250918150625-2e3cea182b63 // indirect
186 + github.com/libp2p/go-libp2p-kbucket v0.8.0 // indirect
187 github.com/libp2p/go-libp2p-record v0.3.1 // indirect
188 github.com/libp2p/go-libp2p-routing-helpers v0.7.5 // indirect
189 github.com/libp2p/go-msgio v0.3.0 // indirect
@@ -244,9 +246,9 @@ require (
246 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
247 github.com/polydawn/refmt v0.89.0 // indirect
248 github.com/polyfloyd/go-errorlint v1.7.1 // indirect
247 - github.com/prometheus/client_golang v1.23.0 // indirect
249 + github.com/prometheus/client_golang v1.23.2 // indirect
250 github.com/prometheus/client_model v0.6.2 // indirect
249 - github.com/prometheus/common v0.65.0 // indirect
251 + github.com/prometheus/common v0.66.1 // indirect
252 github.com/prometheus/procfs v0.17.0 // indirect
253 github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 // indirect
254 github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect
@@ -284,7 +286,7 @@ require (
286 github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect
287 github.com/stbenjam/no-sprintf-host-port v0.2.0 // indirect
288 github.com/stretchr/objx v0.5.2 // indirect
287 - github.com/stretchr/testify v1.10.0 // indirect
289 + github.com/stretchr/testify v1.11.1 // indirect
290 github.com/subosito/gotenv v1.6.0 // indirect
291 github.com/tdakkota/asciicheck v0.4.1 // indirect
292 github.com/tetafro/godot v1.5.0 // indirect
@@ -313,10 +315,10 @@ require (
315 go-simpler.org/musttag v0.13.0 // indirect
316 go-simpler.org/sloglint v0.9.0 // indirect
317 go.opentelemetry.io/auto/sdk v1.1.0 // indirect
316 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 // indirect
317 - go.opentelemetry.io/otel v1.37.0 // indirect
318 - go.opentelemetry.io/otel/metric v1.37.0 // indirect
319 - go.opentelemetry.io/otel/trace v1.37.0 // indirect
318 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect
319 + go.opentelemetry.io/otel v1.38.0 // indirect
320 + go.opentelemetry.io/otel/metric v1.38.0 // indirect
321 + go.opentelemetry.io/otel/trace v1.38.0 // indirect
322 go.uber.org/automaxprocs v1.6.0 // indirect
323 go.uber.org/dig v1.19.0 // indirect
324 go.uber.org/fx v1.24.0 // indirect
@@ -324,20 +326,21 @@ require (
326 go.uber.org/multierr v1.11.0 // indirect
327 go.uber.org/zap v1.27.0 // indirect
328 go.uber.org/zap/exp v0.3.0 // indirect
329 + go.yaml.in/yaml/v2 v2.4.2 // indirect
330 golang.org/x/crypto v0.41.0 // indirect
328 - golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 // indirect
331 + golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b // indirect
332 golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect
333 golang.org/x/mod v0.27.0 // indirect
334 golang.org/x/net v0.43.0 // indirect
332 - golang.org/x/sync v0.16.0 // indirect
333 - golang.org/x/sys v0.35.0 // indirect
335 + golang.org/x/sync v0.17.0 // indirect
336 + golang.org/x/sys v0.36.0 // indirect
337 golang.org/x/term v0.34.0 // indirect
338 golang.org/x/text v0.28.0 // indirect
339 golang.org/x/time v0.12.0 // indirect
340 golang.org/x/tools v0.36.0 // indirect
341 golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
342 gonum.org/v1/gonum v0.16.0 // indirect
340 - google.golang.org/protobuf v1.36.7 // indirect
343 + google.golang.org/protobuf v1.36.9 // indirect
344 gopkg.in/ini.v1 v1.67.0 // indirect
345 gopkg.in/yaml.v2 v2.4.0 // indirect
346 gopkg.in/yaml.v3 v3.0.1 // indirect
test/dependencies/go.sum
+42 -38
@@ -183,8 +183,8 @@ github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/
183 github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
184 github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo=
185 github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA=
186 -github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
187 -github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
186 +github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
187 +github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
188 github.com/gammazero/chanqueue v1.1.1 h1:n9Y+zbBxw2f7uUE9wpgs0rOSkP/I/yhDLiNuhyVjojQ=
189 github.com/gammazero/chanqueue v1.1.1/go.mod h1:fMwpwEiuUgpab0sH4VHiVcEoji1pSi+EIzeG4TPeKPc=
190 github.com/gammazero/deque v1.1.0 h1:OyiyReBbnEG2PP0Bnv1AASLIYvyKqIFN5xfl1t8oGLo=
@@ -332,8 +332,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
332 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
333 github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
334 github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
335 -github.com/ipfs/boxo v0.34.1-0.20250909170220-e69f67e94c11 h1:EsCbOKE+giLtrFTysnbTzIRQENOiLdcpOY3kV3y6wlU=
336 -github.com/ipfs/boxo v0.34.1-0.20250909170220-e69f67e94c11/go.mod h1:rXql6ncaLZZfLqDG3Cuw9ZYQKd3rMU5bk1TGXF0+ZL0=
335 +github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3 h1:qp8w52Rf5eEOrNFZ1VdLSOU3kA5N2EGMNv0xZAACSfs=
336 +github.com/ipfs/boxo v0.34.1-0.20250918150710-6fe835c011c3/go.mod h1:YbQ2GM5GolkfJ8qB29RL+cXgFEa/HsDrHeHSB+fOrlY=
337 github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
338 github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
339 github.com/ipfs/go-block-format v0.2.2 h1:uecCTgRwDIXyZPgYspaLXoMiMmxQpSx2aq34eNc4YvQ=
@@ -342,10 +342,12 @@ github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg=
342 github.com/ipfs/go-cid v0.5.0/go.mod h1:0L7vmeNXpQpUS9vt+yEARkJ8rOg43DF3iPgn4GIN0mk=
343 github.com/ipfs/go-cidutil v0.1.0 h1:RW5hO7Vcf16dplUU60Hs0AKDkQAVPVplr7lk97CFL+Q=
344 github.com/ipfs/go-cidutil v0.1.0/go.mod h1:e7OEVBMIv9JaOxt9zaGEmAoSlXW9jdFZ5lP/0PwcfpA=
345 -github.com/ipfs/go-datastore v0.8.3 h1:z391GsQyGKUIUof2tPoaZVeDknbt7fNHs6Gqjcw5Jo4=
346 -github.com/ipfs/go-datastore v0.8.3/go.mod h1:raxQ/CreIy9L6MxT71ItfMX12/ASN6EhXJoUFjICQ2M=
345 +github.com/ipfs/go-datastore v0.8.4 h1:vXEsd76T3KIOSKXizjhmS3ICGMl+oOSjpLSxE3v8/Wc=
346 +github.com/ipfs/go-datastore v0.8.4/go.mod h1:uT77w/XEGrvJWwHgdrMr8bqCN6ZTW9gzmi+3uK+ouHg=
347 github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
348 github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
349 +github.com/ipfs/go-dsqueue v0.0.5 h1:TUOk15TlCJ/NKV8Yk2W5wgkEjDa44Nem7a7FGIjsMNU=
350 +github.com/ipfs/go-dsqueue v0.0.5/go.mod h1:i/jAlpZjBbQJLioN+XKbFgnd+u9eAhGZs9IrqIzTd9g=
351 github.com/ipfs/go-ipfs-blockstore v1.3.1 h1:cEI9ci7V0sRNivqaOr0elDsamxXFxJMMMy7PTTDQNsQ=
352 github.com/ipfs/go-ipfs-blockstore v1.3.1/go.mod h1:KgtZyc9fq+P2xJUiCAzbRdhhqJHvsw8u2Dlqy2MyRTE=
353 github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ=
@@ -380,8 +382,8 @@ github.com/ipfs/iptb v1.4.1 h1:faXd3TKGPswbHyZecqqg6UfbES7RDjTKQb+6VFPKDUo=
382 github.com/ipfs/iptb v1.4.1/go.mod h1:nTsBMtVYFEu0FjC5DgrErnABm3OG9ruXkFXGJoTV5OA=
383 github.com/ipfs/iptb-plugins v0.5.1 h1:11PNTNEt2+SFxjUcO5qpyCTXqDj6T8Tx9pU/G4ytCIQ=
384 github.com/ipfs/iptb-plugins v0.5.1/go.mod h1:mscJAjRnu4g16QK6oUBn9RGpcp8ueJmLfmPxIG/At78=
383 -github.com/ipld/go-car/v2 v2.14.3 h1:1Mhl82/ny8MVP+w1M4LXbj4j99oK3gnuZG2GmG1IhC8=
384 -github.com/ipld/go-car/v2 v2.14.3/go.mod h1:/vpSvPngOX8UnvmdFJ3o/mDgXa9LuyXsn7wxOzHDYQE=
385 +github.com/ipld/go-car/v2 v2.15.0 h1:RxtZcGXFx72zFESl+UUsCNQV2YMcy3gEMYx9M3uio24=
386 +github.com/ipld/go-car/v2 v2.15.0/go.mod h1:ovlq/n3xlVJDmoiN3Kd/Z7kIzQbdTIFSwltfOP+qIgk=
387 github.com/ipld/go-codec-dagpb v1.7.0 h1:hpuvQjCSVSLnTnHXn+QAMR0mLmb1gA6wl10LExo2Ts0=
388 github.com/ipld/go-codec-dagpb v1.7.0/go.mod h1:rD3Zg+zub9ZnxcLwfol/OTQRVjaLzXypgy4UqHQvilM=
389 github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E=
@@ -462,10 +464,10 @@ github.com/libp2p/go-libp2p v0.43.0 h1:b2bg2cRNmY4HpLK8VHYQXLX2d3iND95OjodLFymvq
464 github.com/libp2p/go-libp2p v0.43.0/go.mod h1:IiSqAXDyP2sWH+J2gs43pNmB/y4FOi2XQPbsb+8qvzc=
465 github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94=
466 github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8=
465 -github.com/libp2p/go-libp2p-kad-dht v0.34.0 h1:yvJ/Vrt36GVjsqPxiGcuuwOloKuZLV9Aa7awIKyNXy0=
466 -github.com/libp2p/go-libp2p-kad-dht v0.34.0/go.mod h1:JNbkES4W5tajS6uYivw6MPs0842cPHAwhgaPw8sQG4o=
467 -github.com/libp2p/go-libp2p-kbucket v0.7.0 h1:vYDvRjkyJPeWunQXqcW2Z6E93Ywx7fX0jgzb/dGOKCs=
468 -github.com/libp2p/go-libp2p-kbucket v0.7.0/go.mod h1:blOINGIj1yiPYlVEX0Rj9QwEkmVnz3EP8LK1dRKBC6g=
467 +github.com/libp2p/go-libp2p-kad-dht v0.34.1-0.20250918150625-2e3cea182b63 h1:XQSASQ9N5haD/uYmop/633tYMZNsM+lKKI8/Is30w4o=
468 +github.com/libp2p/go-libp2p-kad-dht v0.34.1-0.20250918150625-2e3cea182b63/go.mod h1:HbI1rUTFF87WHklzKTGZC8Oys9+1rkKyqvmSZcAW55Y=
469 +github.com/libp2p/go-libp2p-kbucket v0.8.0 h1:QAK7RzKJpYe+EuSEATAaaHYMYLkPDGC18m9jxPLnU8s=
470 +github.com/libp2p/go-libp2p-kbucket v0.8.0/go.mod h1:JMlxqcEyKwO6ox716eyC0hmiduSWZZl6JY93mGaaqc4=
471 github.com/libp2p/go-libp2p-record v0.3.1 h1:cly48Xi5GjNw5Wq+7gmjfBiG9HCzQVkiZOUZ8kUl+Fg=
472 github.com/libp2p/go-libp2p-record v0.3.1/go.mod h1:T8itUkLcWQLCYMqtX7Th6r7SexyUJpIyPgks757td/E=
473 github.com/libp2p/go-libp2p-routing-helpers v0.7.5 h1:HdwZj9NKovMx0vqq6YNPTh6aaNzey5zHD7HeLJtq6fI=
@@ -647,14 +649,14 @@ github.com/polyfloyd/go-errorlint v1.7.1/go.mod h1:aXjNb1x2TNhoLsk26iv1yl7a+zTnX
649 github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
650 github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
651 github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
650 -github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
651 -github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=
652 +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
653 +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
654 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
655 github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
656 github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
657 github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
656 -github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
657 -github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
658 +github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
659 +github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
660 github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
661 github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
662 github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
@@ -778,8 +780,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
780 github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
781 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
782 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
781 -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
782 -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
783 +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
784 +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
785 github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
786 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
787 github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
@@ -863,18 +865,18 @@ go-simpler.org/sloglint v0.9.0/go.mod h1:G/OrAF6uxj48sHahCzrbarVMptL2kjWTaUeC8+f
865 go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
866 go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
867 go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
866 -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 h1:Hf9xI/XLML9ElpiHVDNwvqI0hIFlzV8dgIr35kV1kRU=
867 -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0/go.mod h1:NfchwuyNoMcZ5MLHwPrODwUF1HWCXWrL31s8gSAdIKY=
868 -go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
869 -go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
870 -go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
871 -go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
872 -go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
873 -go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
874 -go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
875 -go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
876 -go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
877 -go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
868 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18=
869 +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg=
870 +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
871 +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
872 +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
873 +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
874 +go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
875 +go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
876 +go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
877 +go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
878 +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
879 +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
880 go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
881 go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
882 go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
@@ -893,6 +895,8 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
895 go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
896 go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U=
897 go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ=
898 +go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
899 +go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
900 go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
901 golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
902 golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -912,8 +916,8 @@ golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1m
916 golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
917 golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
918 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
915 -golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 h1:SbTAbRFnd5kjQXbczszQ0hdk3ctwYf3qBNH9jIsGclE=
916 -golang.org/x/exp v0.0.0-20250813145105-42675adae3e6/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
919 +golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0=
920 +golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
921 golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
922 golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
923 golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac h1:TSSpLIG4v+p0rPv1pNOQtl1I8knsO4S9trOxNMOLVP4=
@@ -983,8 +987,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
987 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
988 golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
989 golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
986 -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
987 -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
990 +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
991 +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
992 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
993 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
994 golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1014,8 +1018,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
1018 golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
1019 golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
1020 golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
1017 -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
1018 -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
1021 +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
1022 +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
1023 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
1024 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
1025 golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
@@ -1104,8 +1108,8 @@ google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmE
1108 google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
1109 google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
1110 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
1107 -google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A=
1108 -google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
1111 +google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
1112 +google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
1113 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
1114 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
1115 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=