| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
test: fix flakes that force CI re-runs (#11413) * fix(routing): keep peers found before the timeout The DHT returns the closest peers it reached together with the context error when a lookup runs past its deadline. We dropped both, so any lookup slower than the routing server's per-request timeout came back as HTTP 500 with nothing in it, indistinguishable from a lookup that found no peers at all. Return what we have, and only error when the set is empty. * test: use local dht swarm for routing v1 test GetClosestPeers joined the public Amino DHT with real bootstrap peers, so the assertions depended on a CI runner reaching bootstrap.libp2p.io from a cold repo. When it could not, the test retried for five minutes and failed; ten such failures since v0.42.0, every one green on re-run. Bootstrap from the harness's in-process DHT peers instead, which the provider tests already use and this one predates. The window drops from five minutes to sixty seconds because there is no longer anything slow to wait for, and passing runs go from tens of seconds to under one. * test: stop handing out ports the kernel reuses NewRandPort binds port zero, notes the number, closes the socket and hands the number to the caller, which leaves a window for anything else on the machine to take it. The number also came from the ephemeral range, the same pool every outgoing connection draws from, and the CLI suite opens a lot of those. Both TestP2PForeground tunnel subtests died on "bind: address already in use" for a server the test binds itself. - NewTCPListener hands back the bound listener, closing that window for callers that listen in-process - ports for daemons we spawn now come from below the ephemeral range, so an outgoing connection cannot land on one * test: sync gc tests to the adder, not the clock TestAddGCLive asserted that gc had not started yet, but the only thing it waited for was the first file's output event. Between that event and the adder reaching the next file there is a gap, and the adder hands the pin lock to a waiting gc at exactly that boundary, so on a loaded runner gc really had started and the assertion was right to fail. Wrap the pipe so the test learns when the adder is inside the hanging file, and poll GCRequested instead of sleeping 100ms to know gc is queued. TestAddMultipleGCLive gets the same treatment for its two sleeps: too short there means gc never gets the lock and the test waits out its five second timeout instead. * test: move watched file in atomically os.WriteFile creates the file and fills it in two steps, and ipfswatch adds whatever is on disk when the create event wakes it. Catch it between the two and it adds an empty file, so the CID the test pulls out of the log reads back as nothing. Stage the file outside the watched directory and rename it in, which the watcher sees as one event for a file that is already complete. * test(sharness): poll the daemon request log The test backgrounded "ipfs log tail", slept 100ms and expected the daemon to be listing the request. The daemon only sees it once the client has started up and connected, which on a loaded runner takes longer than that, and then both the active and the inactive assertion fail together because the entry never appears at all. Poll for each state instead. The extra requests that polling makes push the daemon closer to the point where it drops finished entries from the log, so keep them with "diag cmds set-time" first. * test(sharness): drop stale peer count check The connect case opened by re-asserting that the previous case had left zero peers connected. Disconnecting is not permanent: the DHT keeps the other node in its routing table and re-dials it on any refresh, so that count is only true for as long as nothing else runs. What this case is named for, connecting with a bare /p2p/ address, is still covered by the connect itself and the peer count after it. * test(fuse): mount one node at a time Every parallel subtest does identical setup before mounting, so they all reach the mount together and around twenty setuid fusermount helpers open /dev/fuse inside the same instant. One occasionally comes back with a bare exit status 1. Take a lock for the mount call itself, which the subtests only hold for tens of milliseconds. Also report the failure instead of panicking: a panic failed all 37 tests in the package and left daemons behind, and the daemon's stderr, where fusermount says what actually went wrong, was captured and then thrown away. * test: compare cat output byte for byte The payload is 100 random bytes and the comparison ran through Trimmed(), which strips one trailing newline. Roughly one run in 256 ends in 0x0a and loses it. * test: wait for the fast-provide log line The daemon writes the line before it answers the RPC, but the test reads a buffer that a goroutine fills by copying the daemon's stderr, and that copy can still be behind when the command returns. Wait for the line rather than assuming it has landed. * test: allow for ipns republish mid-test A minute after the daemon starts, the republisher re-signs every key and publishes it again, giving the same value a new signature and expiry. The test captured one PUT body and compared it byte for byte with what routing returned, so a run slow enough to straddle that minute compared the first record against the second. Keep every record the mock is sent and require that routing's answer is one of them, which is what the assertion was reaching for. * fix(examples): turn off mdns in library example The example connects its two nodes by address, but left mDNS on, so local discovery could connect them first. A connection opened while a node is still being built is invisible to that node's bitswap, which only learns about connections made after it registers its notifier, and with no routing configured there is nothing to fall back on. The final fetch then waited forever and the test died on its two minute timeout with no clue why. Turning mDNS off makes the explicit dial the only way the two can meet, and keeps the example off the reader's LAN. Alongside that: - connectToPeers returns dial errors instead of logging and continuing into a fetch that cannot succeed - the example's own deadline now fits inside the test budget, so a stall names the step that hung - CommandContext so a hung child does not outlive the test * ci: make helia-interop job resilient Seven failures since v0.42.0 came from this job's setup rather than from any incompatibility. It installs whatever @helia/interop published last, and upstream shipped three packages in a row whose test config does not work from inside node_modules; a GitHub blip took out the rest. - find the compiled specs and pass them to aegir, instead of patching the config upstream ships into node_modules and grepping its text - pin node to a major: setup-node resolves an lts/ alias through a GitHub manifest with no retry and no fallback, and newer node rejects a flag aegir sets unconditionally - retry the registry lookup and fail loudly, since the old one-liner could not fail and left an empty cache key behind - install the exact version the cache key names, and only save the cache once the install is known good - drop the playwright apt packages, unused since this job stopped running browser targets | 1 个月前 | |
fix(rpc): CARv2 import over HTTP API (#11253) * test(cli): add CARv2 import over HTTP API test Regression test for https://github.com/ipfs/kubo/issues/9361. Imports a CARv2 fixture via the daemon (online mode) and verifies the blocks are accessible. Currently fails with "operation not supported" due to the multipart reader not supporting seeking. * fix(cmd): support CARv2 import over HTTP API Strip the io.Seeker interface from the file before passing it to go-car's NewBlockReader. Over the HTTP API the underlying reader is a multipart stream that cannot seek, but boxo's ReaderFile advertises io.Seeker and returns ErrNotSupported at runtime. Hiding the interface lets go-car fall back to forward-only reading. Fixes https://github.com/ipfs/kubo/issues/9361 --------- Co-authored-by: Andrew Gillis <11790789+gammazero@users.noreply.github.com> | 5 个月前 | |
test: fix flakes that force CI re-runs (#11413) * fix(routing): keep peers found before the timeout The DHT returns the closest peers it reached together with the context error when a lookup runs past its deadline. We dropped both, so any lookup slower than the routing server's per-request timeout came back as HTTP 500 with nothing in it, indistinguishable from a lookup that found no peers at all. Return what we have, and only error when the set is empty. * test: use local dht swarm for routing v1 test GetClosestPeers joined the public Amino DHT with real bootstrap peers, so the assertions depended on a CI runner reaching bootstrap.libp2p.io from a cold repo. When it could not, the test retried for five minutes and failed; ten such failures since v0.42.0, every one green on re-run. Bootstrap from the harness's in-process DHT peers instead, which the provider tests already use and this one predates. The window drops from five minutes to sixty seconds because there is no longer anything slow to wait for, and passing runs go from tens of seconds to under one. * test: stop handing out ports the kernel reuses NewRandPort binds port zero, notes the number, closes the socket and hands the number to the caller, which leaves a window for anything else on the machine to take it. The number also came from the ephemeral range, the same pool every outgoing connection draws from, and the CLI suite opens a lot of those. Both TestP2PForeground tunnel subtests died on "bind: address already in use" for a server the test binds itself. - NewTCPListener hands back the bound listener, closing that window for callers that listen in-process - ports for daemons we spawn now come from below the ephemeral range, so an outgoing connection cannot land on one * test: sync gc tests to the adder, not the clock TestAddGCLive asserted that gc had not started yet, but the only thing it waited for was the first file's output event. Between that event and the adder reaching the next file there is a gap, and the adder hands the pin lock to a waiting gc at exactly that boundary, so on a loaded runner gc really had started and the assertion was right to fail. Wrap the pipe so the test learns when the adder is inside the hanging file, and poll GCRequested instead of sleeping 100ms to know gc is queued. TestAddMultipleGCLive gets the same treatment for its two sleeps: too short there means gc never gets the lock and the test waits out its five second timeout instead. * test: move watched file in atomically os.WriteFile creates the file and fills it in two steps, and ipfswatch adds whatever is on disk when the create event wakes it. Catch it between the two and it adds an empty file, so the CID the test pulls out of the log reads back as nothing. Stage the file outside the watched directory and rename it in, which the watcher sees as one event for a file that is already complete. * test(sharness): poll the daemon request log The test backgrounded "ipfs log tail", slept 100ms and expected the daemon to be listing the request. The daemon only sees it once the client has started up and connected, which on a loaded runner takes longer than that, and then both the active and the inactive assertion fail together because the entry never appears at all. Poll for each state instead. The extra requests that polling makes push the daemon closer to the point where it drops finished entries from the log, so keep them with "diag cmds set-time" first. * test(sharness): drop stale peer count check The connect case opened by re-asserting that the previous case had left zero peers connected. Disconnecting is not permanent: the DHT keeps the other node in its routing table and re-dials it on any refresh, so that count is only true for as long as nothing else runs. What this case is named for, connecting with a bare /p2p/ address, is still covered by the connect itself and the peer count after it. * test(fuse): mount one node at a time Every parallel subtest does identical setup before mounting, so they all reach the mount together and around twenty setuid fusermount helpers open /dev/fuse inside the same instant. One occasionally comes back with a bare exit status 1. Take a lock for the mount call itself, which the subtests only hold for tens of milliseconds. Also report the failure instead of panicking: a panic failed all 37 tests in the package and left daemons behind, and the daemon's stderr, where fusermount says what actually went wrong, was captured and then thrown away. * test: compare cat output byte for byte The payload is 100 random bytes and the comparison ran through Trimmed(), which strips one trailing newline. Roughly one run in 256 ends in 0x0a and loses it. * test: wait for the fast-provide log line The daemon writes the line before it answers the RPC, but the test reads a buffer that a goroutine fills by copying the daemon's stderr, and that copy can still be behind when the command returns. Wait for the line rather than assuming it has landed. * test: allow for ipns republish mid-test A minute after the daemon starts, the republisher re-signs every key and publishes it again, giving the same value a new signature and expiry. The test captured one PUT body and compared it byte for byte with what routing returned, so a run slow enough to straddle that minute compared the first record against the second. Keep every record the mock is sent and require that routing's answer is one of them, which is what the assertion was reaching for. * fix(examples): turn off mdns in library example The example connects its two nodes by address, but left mDNS on, so local discovery could connect them first. A connection opened while a node is still being built is invisible to that node's bitswap, which only learns about connections made after it registers its notifier, and with no routing configured there is nothing to fall back on. The final fetch then waited forever and the test died on its two minute timeout with no clue why. Turning mDNS off makes the explicit dial the only way the two can meet, and keeps the example off the reader's LAN. Alongside that: - connectToPeers returns dial errors instead of logging and continuing into a fetch that cannot succeed - the example's own deadline now fits inside the test budget, so a stall names the step that hung - CommandContext so a hung child does not outlive the test * ci: make helia-interop job resilient Seven failures since v0.42.0 came from this job's setup rather than from any incompatibility. It installs whatever @helia/interop published last, and upstream shipped three packages in a row whose test config does not work from inside node_modules; a GitHub blip took out the rest. - find the compiled specs and pass them to aegir, instead of patching the config upstream ships into node_modules and grepping its text - pin node to a major: setup-node resolves an lts/ alias through a GitHub manifest with no retry and no fallback, and newer node rejects a flag aegir sets unconditionally - retry the registry lookup and fail loudly, since the old one-liner could not fail and left an empty cache key behind - install the exact version the cache key names, and only save the cache once the install is known good - drop the playwright apt packages, unused since this job stopped running browser targets | 1 个月前 | |
test: fix flakes that force CI re-runs (#11413) * fix(routing): keep peers found before the timeout The DHT returns the closest peers it reached together with the context error when a lookup runs past its deadline. We dropped both, so any lookup slower than the routing server's per-request timeout came back as HTTP 500 with nothing in it, indistinguishable from a lookup that found no peers at all. Return what we have, and only error when the set is empty. * test: use local dht swarm for routing v1 test GetClosestPeers joined the public Amino DHT with real bootstrap peers, so the assertions depended on a CI runner reaching bootstrap.libp2p.io from a cold repo. When it could not, the test retried for five minutes and failed; ten such failures since v0.42.0, every one green on re-run. Bootstrap from the harness's in-process DHT peers instead, which the provider tests already use and this one predates. The window drops from five minutes to sixty seconds because there is no longer anything slow to wait for, and passing runs go from tens of seconds to under one. * test: stop handing out ports the kernel reuses NewRandPort binds port zero, notes the number, closes the socket and hands the number to the caller, which leaves a window for anything else on the machine to take it. The number also came from the ephemeral range, the same pool every outgoing connection draws from, and the CLI suite opens a lot of those. Both TestP2PForeground tunnel subtests died on "bind: address already in use" for a server the test binds itself. - NewTCPListener hands back the bound listener, closing that window for callers that listen in-process - ports for daemons we spawn now come from below the ephemeral range, so an outgoing connection cannot land on one * test: sync gc tests to the adder, not the clock TestAddGCLive asserted that gc had not started yet, but the only thing it waited for was the first file's output event. Between that event and the adder reaching the next file there is a gap, and the adder hands the pin lock to a waiting gc at exactly that boundary, so on a loaded runner gc really had started and the assertion was right to fail. Wrap the pipe so the test learns when the adder is inside the hanging file, and poll GCRequested instead of sleeping 100ms to know gc is queued. TestAddMultipleGCLive gets the same treatment for its two sleeps: too short there means gc never gets the lock and the test waits out its five second timeout instead. * test: move watched file in atomically os.WriteFile creates the file and fills it in two steps, and ipfswatch adds whatever is on disk when the create event wakes it. Catch it between the two and it adds an empty file, so the CID the test pulls out of the log reads back as nothing. Stage the file outside the watched directory and rename it in, which the watcher sees as one event for a file that is already complete. * test(sharness): poll the daemon request log The test backgrounded "ipfs log tail", slept 100ms and expected the daemon to be listing the request. The daemon only sees it once the client has started up and connected, which on a loaded runner takes longer than that, and then both the active and the inactive assertion fail together because the entry never appears at all. Poll for each state instead. The extra requests that polling makes push the daemon closer to the point where it drops finished entries from the log, so keep them with "diag cmds set-time" first. * test(sharness): drop stale peer count check The connect case opened by re-asserting that the previous case had left zero peers connected. Disconnecting is not permanent: the DHT keeps the other node in its routing table and re-dials it on any refresh, so that count is only true for as long as nothing else runs. What this case is named for, connecting with a bare /p2p/ address, is still covered by the connect itself and the peer count after it. * test(fuse): mount one node at a time Every parallel subtest does identical setup before mounting, so they all reach the mount together and around twenty setuid fusermount helpers open /dev/fuse inside the same instant. One occasionally comes back with a bare exit status 1. Take a lock for the mount call itself, which the subtests only hold for tens of milliseconds. Also report the failure instead of panicking: a panic failed all 37 tests in the package and left daemons behind, and the daemon's stderr, where fusermount says what actually went wrong, was captured and then thrown away. * test: compare cat output byte for byte The payload is 100 random bytes and the comparison ran through Trimmed(), which strips one trailing newline. Roughly one run in 256 ends in 0x0a and loses it. * test: wait for the fast-provide log line The daemon writes the line before it answers the RPC, but the test reads a buffer that a goroutine fills by copying the daemon's stderr, and that copy can still be behind when the command returns. Wait for the line rather than assuming it has landed. * test: allow for ipns republish mid-test A minute after the daemon starts, the republisher re-signs every key and publishes it again, giving the same value a new signature and expiry. The test captured one PUT body and compared it byte for byte with what routing returned, so a run slow enough to straddle that minute compared the first record against the second. Keep every record the mock is sent and require that routing's answer is one of them, which is what the assertion was reaching for. * fix(examples): turn off mdns in library example The example connects its two nodes by address, but left mDNS on, so local discovery could connect them first. A connection opened while a node is still being built is invisible to that node's bitswap, which only learns about connections made after it registers its notifier, and with no routing configured there is nothing to fall back on. The final fetch then waited forever and the test died on its two minute timeout with no clue why. Turning mDNS off makes the explicit dial the only way the two can meet, and keeps the example off the reader's LAN. Alongside that: - connectToPeers returns dial errors instead of logging and continuing into a fetch that cannot succeed - the example's own deadline now fits inside the test budget, so a stall names the step that hung - CommandContext so a hung child does not outlive the test * ci: make helia-interop job resilient Seven failures since v0.42.0 came from this job's setup rather than from any incompatibility. It installs whatever @helia/interop published last, and upstream shipped three packages in a row whose test config does not work from inside node_modules; a GitHub blip took out the rest. - find the compiled specs and pass them to aegir, instead of patching the config upstream ships into node_modules and grepping its text - pin node to a major: setup-node resolves an lts/ alias through a GitHub manifest with no retry and no fallback, and newer node rejects a flag aegir sets unconditionally - retry the registry lookup and fail loudly, since the old one-liner could not fail and left an empty cache key behind - install the exact version the cache key names, and only save the cache once the install is known good - drop the playwright apt packages, unused since this job stopped running browser targets | 1 个月前 | |
feat(provide): +unique and +entities strategy modifiers (#11245) * fix(config): harden provide strategy parsing with error returns - config: ParseProvideStrategy returns error, rejects "all" mixed with selective strategies, removes dead strategy==0 check - config: add MustParseProvideStrategy for pre-validated call sites - config: ValidateProvideConfig validates strategy at startup - config: ShouldProvideForStrategy uses bitmask check for ProvideStrategyAll - core/node: downstream callers use MustParseProvideStrategy - core/node: fix Pinning() nil return that caused fx.Provide panic * feat(config): add +unique and +entities strategy modifiers - ProvideStrategyUnique: bloom filter cross-DAG deduplication - ProvideStrategyEntities: entity-aware traversal (implies Unique) - parser: "unique" and "entities" tokens recognized - validation: modifiers must combine with pinned/mfs, incompatible with all/roots - go.mod: update boxo to feat/provide-entity-roots-with-dedup (VisitedTracker, WalkDAG, WalkEntityRoots, NewConcatProvider, NewUniquePinnedProvider, NewPinnedEntityRootsProvider) * refactor(cmd): rename ExecuteFastProvide to ExecuteFastProvideRoot pure rename, no behavior change. prepares for ExecuteFastProvideDAG which will walk the DAG according to Provide.Strategy. * feat(pin): fast-provide root CID after pin add and pin update adds ExecuteFastProvideRoot calls to pin add and pin update, matching the behavior of ipfs add and ipfs dag import. respects Import.FastProvideRoot and Import.FastProvideWait config options. previously, pin add/update did not trigger any immediate providing, leaving pinned content invisible to the DHT until the next reprovide cycle (up to 22h). * feat(provider): wire +unique reprovide cycle with bloom dedup when Provide.Strategy includes +unique, the reprovide cycle uses a shared BloomTracker across all sub-walks (MFS, recursive pins, direct pins). duplicate sub-DAG branches across recursive pins are detected and skipped, reducing traversal from O(pins * total_blocks) to O(unique_blocks). - readLastUniqueCount / persistUniqueCount: persist bloom sizing count between cycles at /reprovideLastUniqueCount - uniqueMFSProvider: MFS walker with shared tracker + locality check - createKeyProvider restructured: +unique bit checked first, non-unique strategies fall through to existing switch unchanged - per-cycle fresh BloomTracker sized from previous cycle's count - channel wrapper persists count on successful cycle completion * feat(provider): wire +entities reprovide cycle with entity root walkers when Provide.Strategy includes +entities (which implies +unique), the reprovide cycle uses WalkEntityRoots instead of WalkDAG, emitting only entity roots (files, directories, HAMT shards) and skipping internal file chunks. - mfsEntityRootsProvider: MFS walk with entity root detection - createKeyProvider: select walker based on +entities flag via function references (makePinProv / makeMFSProv) to avoid duplicating the stream wiring logic - all combinations: pinned+entities, mfs+entities, pinned+mfs+entities * docs: document +unique and +entities strategy modifiers - config.md: document +unique, +entities modifiers with caveats (range request limitation, roots vs entities distinction) - changelog v0.41: add entries for strategy modifiers, pin add/update fast-provide, and hardened strategy parsing * feat: gate providingDagService behind --fast-provide-dag per-block providing during ipfs add is now opt-in via --fast-provide-dag (or Import.FastProvideDAG config, default: false). without it, only the root CID is fast-provided after add, and the reprovide cycle handles the rest. this changes the default for Provide.Strategy=pinned: previously every block was provided during write, now only the root is immediate. use --fast-provide-dag=true to restore the previous behavior. Provide.Strategy=all is unaffected (blockstore hook provides on Put). * feat(pin): expose --fast-provide-root and --fast-provide-wait flags pin add and pin update now accept the same --fast-provide-root and --fast-provide-wait CLI flags as ipfs add and ipfs dag import, with the same config fallbacks (Import.FastProvideRoot, Import.FastProvideWait). previously these were config-only with no CLI override. * feat: wire --fast-provide-dag across all content commands --fast-provide-dag now available on ipfs add, ipfs dag import, ipfs pin add, and ipfs pin update (matching --fast-provide-root). - ExecuteFastProvideDAG accepts []cid.Cid so multiple roots share one bloom tracker (cross-root dedup for dag import and pin add) - --fast-provide-dag supersedes --fast-provide-root (DAG walk includes the root CID as the first emitted via DFS pre-order) - wait parameter: when true blocks until walk completes, when false runs in background goroutine - Import.FastProvideDAG config option (default: false) * docs(config): improve Provide.Strategy docs, add Import.FastProvideDAG - strategy section: clearer trade-offs, suggested configurations, memory comparison with concrete numbers - Import.FastProvideDAG: new config option documentation - Import.FastProvideRoot/Wait: updated to mention pin commands - all three Import.FastProvide* options: consistent "Applies to" lists * chore: gofumpt and gci formatting * chore: update boxo to latest feat/provide-entity-roots-with-dedup * feat: TEST_DHT_STUB with ephemeral DHT peers when TEST_DHT_STUB=1, the CLI test harness creates 20 in-process libp2p hosts on loopback, each running a DHT server with a shared in-memory ProviderStore. kubo daemons bootstrap to them over real TCP, exercising the full DHT code path without public internet. tests opt in via h.SetStubBootstrap(nodes) after Init(). on the daemon side, WAN DHT filters (AddressFilter, QueryFilter, RoutingTableFilter, RoutingTablePeerDiversityFilter) are lifted to accept loopback peers when TEST_DHT_STUB is set. depends on: github.com/libp2p/go-libp2p-kad-dht#1241 * test: harden provider strategy tests add sweep reprovide tests for all strategies (all, pinned, roots, mfs, pinned+mfs). each test waits for two reprovide cycles to confirm the schedule runs repeatedly. sweep uses short Provide.DHT.Interval and polls provide stat --enc=json. harden negative assertions: - roots: test excludes child blocks of a recursive pin (not just unpinned content), using --only-hash to learn the child CID - mfs: test that pinned content outside MFS is not provided fix: ipfs add --only-hash no longer triggers fast-provide or pinning (was providing CIDs for data that was never stored) rename SetStubBootstrap to BootstrapWithStubDHT with lazy-init (ephemeral peers created on first call, not on harness creation) * test: add +unique and +entities strategy tests strategy tests for pinned+mfs+unique and pinned+mfs+entities, covering both provide-at-add-time and reprovide (two cycles). content uses a nested DAG (root/subdir/largefile with 1 MiB chunks) to exercise the walker on multi-level structures. BootstrapWithStubDHT is now self-contained: it always creates 20 ephemeral DHT peers on loopback and sets TEST_DHT_STUB=1 on each node's environment so the daemon lifts WAN DHT filters. no external env var needed. the sweep provider requires >=20 DHT peers to estimate network size (prefix length); without enough peers it stays offline and never provides. TEST_DHT_STUB on the daemon side lifts WAN DHT filters (AddressFilter, QueryFilter, RoutingTableFilter, RoutingTablePeerDiversityFilter) to accept loopback peers. this is set automatically by BootstrapWithStubDHT. other changes: - Provide.DHT.Interval=30s in sweep reprovide tests (was 1m) - uniq() helper for unique CIDs across parallel subtests - ipfs add --only-hash disables fast-provide and pinning * docs: improve help text and changelog accuracy ipfs add --help: rewrite fast-provide section with clear structure (content discoverability, flag defaults, strategy=all behavior) ipfs routing reprovide: mark as deprecated, note it returns an error with sweep provider, log error with actionable guidance changelog: fix missing --fast-provide-dag flag on pin commands, use "routing system" instead of "DHT" where applicable, link to docs/config.md as source of truth for defaults environment-variables.md: note that BootstrapWithStubDHT sets TEST_DHT_STUB automatically, no external env var needed * chore: revert go-libp2p-kad-dht to released v0.39.0 the fork (NoopMessageSender, MsgSenderBuilder) is no longer used. the ephemeral peer pool in BootstrapWithStubDHT replaced the NoopMessageSender approach. * feat: log bloom dedup stats after provide cycles log providedCIDs and skippedBranches after each unique reprovide cycle and fast-provide-dag walk. tests verify exact counts with two dir pins sharing a 10 KiB file (5 KiB chunks): fast-provide-dag asserts 5 provided + 1 skipped branch, reprovide asserts 6 provided + 1 skipped branch (includes empty MFS root pin). both assert bloom tracker created and no autoscale. updates boxo to pick up Deduplicated() counter, bloom creation/autoscale logging, and review feedback fixes. * chore(deps): switch boxo to post-merge commit boxo#1124 landed on master; point to the merge commit instead of the PR branch. * fix(coreapi): drop providingDagService wrap ipfs add --pin --fast-provide-dag wrapped the DAGService with providingDagService, which announced every block as it was written regardless of strategy modifiers. ExecuteFastProvideDAG ran in parallel as the post-add walker. Net effect: - pinned+entities: chunks reached the DHT despite +entities saying they should be skipped (correctness bug) - pinned+unique: every block announced twice; the post-walk bloom only dedups against its own pass - pinned (plain): every block announced twice ExecuteFastProvideDAG already has bloom dedup, entity-roots support, and unbuffered backpressure, so it is now the single mechanism for --fast-provide-dag across ipfs add, dag import, pin add, and pin update. Provide.Strategy=all is untouched: every block is provided at the blockstore level via the blockstore.Provider hook in core/node/storage.go, which is independent of coreapi. The Pinned strategy bit gated providingDagService and the parser rejects combining "all" with other strategies, so "all" never set that bit in the first place. - core/coreapi/unixfs.go: drop the wrap, the providingDagService struct, and the now-unused mh and boxo/provider imports - core/coreiface/options/unixfs.go: drop FastProvideDAG option - core/coreapi/coreapi.go: drop now-dead providingStrategy field - core/commands/add.go: drop the FastProvideDAG option pass-through - test/cli/provider_test.go: regression test using ipfs add --fast-provide-dag with pinned+entities -- fails on the previous code and passes here * feat(config): add Provide.BloomFPRate Operators tuning +unique or +entities strategies on memory-constrained or extra-large repos previously had no way to trade bloom filter memory against false-positive rate -- both the reprovide cycle and fast-provide-dag walks hardcoded walker.DefaultBloomFPRate. Provide.BloomFPRate is the target false positive rate (1/N) for the shared bloom tracker. Has no effect on Provide.Strategy=all or other strategies that do not walk DAGs through the tracker. Validation rejects values below 1_000_000 (~1 in 1M); below that the bloom becomes lossy enough to drop a meaningful fraction of CIDs from each reprovide cycle. The single source of truth for the default value is config.DefaultProvideBloomFPRate; docs reference it descriptively (~1 in 4.75M, ~4 bytes/CID) so the literal lives in exactly one place. - config/provide.go: BloomFPRate field, DefaultProvideBloomFPRate and MinProvideBloomFPRate constants, validation - config/provide_test.go: round-trip + validation cases - core/node/provider.go: plumb fpRate through setReproviderKeyProvider and createKeyProvider - core/commands/cmdenv/env.go: ExecuteFastProvideDAG takes fpRate - core/commands/{add,dag/import,pin/pin}.go: resolve from cfg and pass through to ExecuteFastProvideDAG - docs/config.md: new Provide.BloomFPRate section after Provide.DHT.* with memory tradeoff table and minimum-value note - docs/changelogs/v0.41.md: link to the new option from the +unique/ +entities section * test(node): cover unique count persistence readLastUniqueCount and persistUniqueCount were exercised only indirectly via CLI tests, leaving the 8-byte length check and the "missing key" fallback without direct coverage. - empty datastore returns 0 (no previous cycle) - round trip across the full uint64 range (0, 1, 1k, 1M, 1B, MaxUint64) - overwrite returns the most recent value (matches per-cycle persist) - corrupt length (empty, short, long, single byte) returns 0 instead of panicking * fix(cmdenv): tie async fast-provide to node ctx Background fast-provide goroutines were implicitly bound to req.Context, which go-ipfs-cmds cancels on handler exit, so async --fast-provide-dag (and --fast-provide-root parented on context.Background) aborted or outlived the node. Parent both paths off the IpfsNode lifetime context instead. - ExecuteFastProvideRoot: async goroutine now derives from ipfsNode.Context(), so it cancels on daemon shutdown rather than potentially touching a closed DHT client. - ExecuteFastProvideDAG: takes cmdCtx and nodeCtx; wait=true runs inline under cmdCtx (Ctrl+C still cancels the walk), wait=false runs in a goroutine under nodeCtx so the walk survives command exit but still stops on shutdown. - add, dag import, pin add/update: pass node.Context() as the new nodeCtx argument. - changelog: note the behavior change for opt-in strategies. * test(cli): cover async fast-provide-dag walk Adds TestProviderFastProvideDAGAsyncSurvives: ipfs add with --fast-provide-dag=true but no --fast-provide-wait must walk the full DAG in a background goroutine that outlives the command handler, announce every block, and leave chunk CIDs findable by peers via findprovs. A long Provide.DHT.Interval ensures the scheduled reprovide cycle cannot be the source of the chunk announcements. * docs(changelog): tighten v0.41 provide section | 4 个月前 | |
fix(key): restore secp256k1 keygen and add PEM PKCS8 import/export (#11387) * fix(key): restore secp256k1 keygen and add PEM PKCS8 import/export * fix(key): validate --size for fixed-size key types ed25519 and secp256k1 keys have a single valid size, so a --size (--bits for init) that does not match it is now an error instead of being accepted and ignored. core/coreapi Generate and config.CreateIdentity share a new options.CheckKeySize helper, so key gen, key rotate, and init accept --size only when it equals the fixed 256 bits. RSA keeps its variable size. * test(cli): cover key lifecycle for all key types Adds end-to-end CLI coverage of the key commands (gen, list, export, import, rename, rm, rotate) for rsa, ed25519, and secp256k1. This mirrors the sharness keystore and rotate suites and extends them to secp256k1, which they never exercised. - OpenSSL fixtures under testdata/ pin byte-identical PKCS#8 export and import in both directions - rotate checks the previous identity survives, usable, under the backup name - reserved-name ('self') and restricted-type imports assert the specific refusal, not just a non-zero exit * chore(deps): note secp256k1 version alignment go-libp2p/core/crypto's key types alias this package, so the direct and transitive pins must stay on one version to avoid two copies in the build. The go.mod comment flags that for future dependency bumps. --------- Co-authored-by: Marcin Rataj <lidel@lidel.org> | 2 个月前 | |
docs: drop expired pgp key from security notes (#11422) The key expired in 2018 and the pgp.mit.edu lookup it pointed at returns 503, so anyone following it hits a dead end twice. No successor key is published for security@ipfs.io on any keyserver, so the notes point at the repository security policy instead. Seeding the init docs changes their directory CID, so the constants the tests assert against move with it. | 1 个月前 | |
refactor: apply go fix modernizers from Go 1.26 (#11190) * chore: apply go fix modernizers from Go 1.26 automated refactoring: interface{} to any, slices.Contains, and other idiomatic updates. * feat(ci): add `go fix` check to Go analysis workflow ensures Go 1.26 modernizers are applied, fails CI if `go fix ./...` produces any changes (similar to existing `go fmt` enforcement) | 6 个月前 | |
fix(cmds): cleanup unicode identify strings (#9465) preserve private use characters as specified in https://github.com/libp2p/specs/pull/491 enforce 128 rune limit on untrusted peer data | 11 个月前 | |
refactor: apply go fix modernizers from Go 1.26 (#11190) * chore: apply go fix modernizers from Go 1.26 automated refactoring: interface{} to any, slices.Contains, and other idiomatic updates. * feat(ci): add `go fix` check to Go analysis workflow ensures Go 1.26 modernizers are applied, fails CI if `go fix ./...` produces any changes (similar to existing `go fmt` enforcement) | 6 个月前 | |
feat(autotls): skip issuance when broker is down (#11397) * feat(autotls): skip issuance when broker is down Bump github.com/ipshipyard/p2p-forge to the head of ipshipyard/p2p-forge#91: before first-time ACME issuance the client now confirms the broker responds with HTTP 204 on /v1/health, after the registration delay and once the node is publicly reachable. While the broker keeps failing the check, certificate setup is postponed with one ERROR and an hourly re-check (respecting Retry-After, capped at 24h) instead of doomed ACME retries for weeks. Ephemeral nodes (CI runners) still produce no broker traffic at all, and nodes with a certificate in storage are unaffected. * chore: update p2p-forge to v0.10.0 | 1 个月前 | |
shutdown daemon after test (#11135) | 7 个月前 | |
refactor: apply go fix modernizers from Go 1.26 (#11190) * chore: apply go fix modernizers from Go 1.26 automated refactoring: interface{} to any, slices.Contains, and other idiomatic updates. * feat(ci): add `go fix` check to Go analysis workflow ensures Go 1.26 modernizers are applied, fails CI if `go fix ./...` produces any changes (similar to existing `go fmt` enforcement) | 6 个月前 | |
refactor: apply go fix modernizers from Go 1.26 (#11190) * chore: apply go fix modernizers from Go 1.26 automated refactoring: interface{} to any, slices.Contains, and other idiomatic updates. * feat(ci): add `go fix` check to Go analysis workflow ensures Go 1.26 modernizers are applied, fails CI if `go fix ./...` produces any changes (similar to existing `go fmt` enforcement) | 6 个月前 | |
refactor: apply go fix modernizers from Go 1.26 (#11190) * chore: apply go fix modernizers from Go 1.26 automated refactoring: interface{} to any, slices.Contains, and other idiomatic updates. * feat(ci): add `go fix` check to Go analysis workflow ensures Go 1.26 modernizers are applied, fails CI if `go fix ./...` produces any changes (similar to existing `go fmt` enforcement) | 6 个月前 | |
feat(config): AutoConf with "auto" placeholders (#10883) https://github.com/ipfs/kubo/pull/10883 https://github.com/ipshipyard/config.ipfs-mainnet.org/issues/3 --------- Co-authored-by: gammazero <gammazero@users.noreply.github.com> | 1 年前 | |
fix(cli/rpc): --cid-base works in all commands (#11239) * fix: --cid-base works in all commands and auto-upgrades CIDv0 Passing --cid-base=base32 now returns CIDv1 in base32 everywhere, including block, dag stat, and object patch which previously ignored it. - cidbase: auto-upgrade CIDv0 when base is not base58btc, deprecate --upgrade-cidv0-in-output, remove GetLowLevelCidEncoder - block stat/put/rm: use GetCidEncoder - dag stat: store CID as pre-encoded string, drop MarshalJSON/UnmarshalJSON - object patch rm-link/add-link: use GetCidEncoder - bitswap: switch to GetCidEncoder * test: add harness tests for --cid-base flag Remove unused DagStat.String() which truncated CIDs. Add CLI tests for --cid-base across block, dag stat, and object patch commands, including the --format=v0 interaction. * fix: respect --cid-base in refs local, object diff, pin remote, files chroot Use GetCidEncoder in commands that were still outputting CIDs via raw .String() calls. - refs local: encode blockstore keys with the requested base - object diff: encode Before/After CIDs in text encoder - pin remote add/ls: pass encoder through toRemotePinOutput - files chroot: encode old/new root CIDs in status message - tests: use base16 to avoid false positives if base32 becomes default * docs: update changelog entry for --cid-base fixes * test: cover --cid-base for add, pin ls, dag import Add harness tests for add, add -Q, pin ls, and dag import. Fix object patch tests broken by upstream UnixFS validation. Use base16 in all tests to avoid false positives. * docs: add metrics and CARv2 highlights to v0.41 changelog | 4 个月前 | |
feat(config): add Import.* for CID Profiles from IPIP-499 (#11148) * feat(config): Import.* and unixfs-v1-2025 profile implements IPIP-499: add config options for controlling UnixFS DAG determinism and introduces `unixfs-v1-2025` and `unixfs-v0-2015` profiles for cross-implementation CID reproducibility. changes: - add Import.* fields: HAMTDirectorySizeEstimation, SymlinkMode, DAGLayout, IncludeEmptyDirectories, IncludeHidden - add validation for all Import.* config values - add unixfs-v1-2025 profile (recommended for new data) - add unixfs-v0-2015 profile (alias: legacy-cid-v0) - remove deprecated test-cid-v1 and test-cid-v1-wide profiles - wire Import.HAMTSizeEstimationMode() to boxo globals - update go.mod to use boxo with SizeEstimationMode support ref: https://specs.ipfs.tech/ipips/ipip-0499/ * feat(add): add --dereference-symlinks, --empty-dirs, --hidden CLI flags add CLI flags for controlling file collection behavior during ipfs add: - `--dereference-symlinks`: recursively resolve symlinks to their target content (replaces deprecated --dereference-args which only worked on CLI arguments). wired through go-ipfs-cmds to boxo's SerialFileOptions. - `--empty-dirs` / `-E`: include empty directories (default: true) - `--hidden` / `-H`: include hidden files (default: false) these flags are CLI-only and not wired to Import.* config options because go-ipfs-cmds library handles input file filtering before the directory tree is passed to kubo. removed unused Import.UnixFSSymlinkMode config option that was defined but never actually read by the CLI. also: - wire --trickle to Import.UnixFSDAGLayout config default - update go-ipfs-cmds to v0.15.1-0.20260117043932-17687e216294 - add SYMLINK HANDLING section to ipfs add help text - add CLI tests for all three flags ref: https://github.com/ipfs/specs/pull/499 * test(add): add CID profile tests and wire SizeEstimationMode add comprehensive test suite for UnixFS CID determinism per IPIP-499: - verify exact HAMT threshold boundary for both estimation modes: - v0-2015 (links): sum(name_len + cid_len) == 262144 - v1-2025 (block): serialized block size == 262144 - verify HAMT triggers at threshold + 1 byte for both profiles - add all deterministic CIDs for cross-implementation testing also wires SizeEstimationMode through CLI/API, allowing Import.UnixFSHAMTSizeEstimation config to take effect. bumps boxo to ipfs/boxo@6707376 which aligns HAMT threshold with JS implementation (uses > instead of >=), fixing CID determinism at the exact 256 KiB boundary. * feat(add): --dereference-symlinks now resolves all symlinks Previously, resolving symlinks required two flags: - --dereference-args: resolved symlinks passed as CLI arguments - --dereference-symlinks: resolved symlinks inside directories Now --dereference-symlinks handles both cases. Users only need one flag to fully dereference symlinks when adding files to IPFS. The deprecated --dereference-args still works for backwards compatibility but is no longer necessary. * chore: update boxo and improve changelog - update boxo to ebdaf07c (nil filter fix, thread-safety docs) - simplify changelog for IPIP-499 section - shorten test names, move context to comments * chore: update boxo to 5cf22196 * chore: apply suggestions from code review Co-authored-by: Andrew Gillis <11790789+gammazero@users.noreply.github.com> * test(add): verify balanced DAG layout produces uniform leaf depth add test that confirms kubo uses balanced layout (all leaves at same depth) rather than balanced-packed (varying depths). creates 45MiB file to trigger multi-level DAG and walks it to verify leaf depth uniformity. includes trickle subtest to validate test logic can detect varying depths. supports CAR export via DAG_LAYOUT_CAR_OUTPUT env var for test vectors. * chore(deps): update boxo to 6141039ad8ef switches to https://github.com/ipfs/boxo/pull/1088/commits/6141039ad8ef098c3b65db8b2d1aeb3c16727c6c changes since 5cf22196ad0b: - refactor(unixfs): use arithmetic for exact block size calculation - refactor(unixfs): unify size tracking and make SizeEstimationMode immutable - feat(unixfs): optimize SizeEstimationBlock and add mode/mtime tests also clarifies that directory sharding globals affect both `ipfs add` and MFS. * test(cli): improve HAMT threshold tests with exact +1 byte verification - add UnixFSDataType() helper to directly check UnixFS type via protobuf - refactor threshold tests to use exact +1 byte calculations instead of +1 file - verify directory type directly (ft.TDirectory vs ft.THAMTShard) instead of inferring from link count - clean up helper function signatures by removing unused cidLength parameter * test(cli): consolidate profile tests into cid_profiles_test.go remove duplicate profile threshold tests from add_test.go since they are fully covered by the data-driven tests in cid_profiles_test.go. changes: - improve test names to describe what threshold is being tested - add inline documentation explaining each test's purpose - add byte-precise helper IPFSAddDeterministicBytes for threshold tests - remove ~200 lines of duplicated test code from add_test.go - keep non-profile tests (pinning, symlinks, hidden files) in add_test.go * chore: update to rebased boxo and go-ipfs-cmds PRs * docs: add HAMT threshold fix details to changelog * feat(mfs): use Import config for CID version and hash function make MFS commands (files cp, files write, files mkdir, files chcid) respect Import.CidVersion and Import.HashFunction config settings when CLI options are not explicitly provided. also add tests for: - files write respects Import.UnixFSRawLeaves=true - single-block file: files write produces same CID as ipfs add - updated comments clarifying CID parity with ipfs add * feat(files): wire Import.UnixFSChunker and UnixFSDirectoryMaxLinks to MFS `ipfs files` commands now respect these Import.* config options: - UnixFSChunker: configures chunk size for `files write` - UnixFSDirectoryMaxLinks: triggers HAMT sharding in `files mkdir` - UnixFSHAMTDirectorySizeEstimation: controls size estimation mode previously, MFS used hardcoded defaults ignoring user config. changes: - config/import.go: add UnixFSSplitterFunc() returning chunk.SplitterGen - core/node/core.go: pass chunker, maxLinks, sizeEstimationMode to mfs.NewRoot() via new boxo RootOption API - core/commands/files.go: pass maxLinks and sizeEstimationMode to mfs.Mkdir() and ensureContainingDirectoryExists(); document that UnixFSFileMaxLinks doesn't apply to files write (trickle DAG limitation) - test/cli/files_test.go: add tests for UnixFSDirectoryMaxLinks and UnixFSChunker, including CID parity test with `ipfs add --trickle` related: boxo@54e044f1b265 * feat(files): wire Import.UnixFSHAMTDirectoryMaxFanout and UnixFSHAMTDirectorySizeThreshold wire remaining HAMT config options to MFS root: - Import.UnixFSHAMTDirectoryMaxFanout via mfs.WithMaxHAMTFanout - Import.UnixFSHAMTDirectorySizeThreshold via mfs.WithHAMTShardingSize add CLI tests: - files mkdir respects Import.UnixFSHAMTDirectoryMaxFanout - files mkdir respects Import.UnixFSHAMTDirectorySizeThreshold - config change takes effect after daemon restart add UnixFSHAMTFanout() helper to test harness update boxo to ac97424d99ab90e097fc7c36f285988b596b6f05 * fix(mfs): single-block files in CIDv1 dirs now produce raw CIDs problem: `ipfs files write` in CIDv1 directories wrapped single-block files in dag-pb even when raw-leaves was enabled, producing different CIDs than `ipfs add --raw-leaves` for the same content. fix: boxo now collapses single-block ProtoNode wrappers (with no metadata) to RawNode in DagModifier.GetNode(). files with mtime/mode stay as dag-pb since raw blocks cannot store UnixFS metadata. also fixes sparse file writes where writing past EOF would lose data because expandSparse didn't update the internal node pointer. updates boxo to v0.36.1-0.20260203003133-7884ae23aaff updates t0250-files-api.sh test hashes to match new behavior * chore(test): use Go 1.22+ range-over-int syntax * chore: update boxo to c6829fe26860 - fix typo in files write help text - update boxo with CI fixes (gofumpt, race condition in test) * chore: update go-ipfs-cmds to 192ec9d15c1f includes binary content types fix: gzip, zip, vnd.ipld.car, vnd.ipld.raw, vnd.ipfs.ipns-record * chore: update boxo to 0a22cde9225c includes refactor of maxLinks check in addLinkChild (review feedback). * ci: fix helia-interop and improve caching skip '@helia/mfs - should have the same CID after creating a file' test until helia implements IPIP-499 (tracking: https://github.com/ipfs/helia/issues/941) the test fails because kubo now collapses single-block files to raw CIDs while helia explicitly uses reduceSingleLeafToSelf: false changes: - run aegir directly instead of helia-interop binary (binary ignores --grep flags) - cache node_modules keyed by @helia/interop version from npm registry - skip npm install on cache hit (matches ipfs-webui caching pattern) * chore: update boxo to 1e30b954 includes latest upstream changes from boxo main * chore: update go-ipfs-cmds to 1b2a641ed6f6 * chore: update boxo to f188f79fd412 switches to boxo@main after merging https://github.com/ipfs/boxo/pull/1088 * chore: update go-ipfs-cmds to af9bcbaf5709 switches to go-ipfs-cmds@master after merging https://github.com/ipfs/go-ipfs-cmds/pull/315 --------- Co-authored-by: Andrew Gillis <11790789+gammazero@users.noreply.github.com> | 7 个月前 | |
feat(cmd): add 'ipfs cid inspect' command (#11241) * feat(cmd): add 'ipfs cid inspect' command Adds a new subcommand to inspect and display detailed CID information including version, multibase encoding, multicodec, and multihash components. Also shows equivalent CIDv0/CIDv1 representations. Example output: CID: bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi Version: 1 Multibase: base32 (b) Multicodec: dag-pb (0x70) Multihash: sha2-256 (0x12) Length: 32 bytes Digest: c3c4733ec8affd06cf9e9ff50ffc6bcd2ec85a6170004bb709669c31de94391a CIDv0: QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR CIDv1: bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi Supports --enc=json for machine-readable output. Fixes #11205 * refactor: tidy up CidInspectRes struct and add '/cid/inspect' route to tests This commit refines the CidInspectRes struct for better readability and consistency. Additionally, it includes the '/cid/inspect' route in the command tests to ensure comprehensive coverage of the new CID inspection functionality. * docs: update changelog for v0.42 to include new `ipfs cid inspect` command Added a section highlighting the new `ipfs cid inspect <cid>` command, detailing its functionality to display comprehensive CID information, including version, encoding, and hash details. The command supports machine-readable output and operates offline. * feat(cmd): improve ipfs cid inspect - multibase: always shown (implicit for CIDv0), prefix as string - multicodec/multihash: annotated (implicit) for CIDv0 - digest: uppercase hex with 0x prefix - cidV0: empty in JSON when not possible, text encoder explains why - cidV1: base36 for libp2p-key codec, base32 otherwise - errors: ErrorMsg kept for HTTP RPC API, text encoder returns non-zero exit - PeerID fallback: helpful hint with equivalent CID on invalid input - unknown codec/hash: graceful "unknown" label - stdin support via .EnableStdin() - inspect listed first in subcommands, cid format points to inspect - cli tests for all cases including JSON, PeerID, unknown codec * chore: move cid inspect changelog to v0.41 - digest: bare lowercase hex (no 0x prefix), matching sha256sum --------- Co-authored-by: Marcin Rataj <lidel@lidel.org> | 5 个月前 | |
fix(cli): support HTTPS in ipfs --api (#10659) * fix(cli): support HTTPS in ipfs --api Closes #10539 * chore: go-ipfs-cmds v0.14.1 https://github.com/ipfs/go-ipfs-cmds/releases/tag/v0.14.1 * docs: ipfs --api example * test(cli): https rpc support makes sure we dont have regression where HTTPS endpoint starts getting cleartext requests | 1 年前 | |
fix: `ipfs cid` without repo (#10897) * fix: `ipfs cid format` without repo these commands should work without daemon or repo but were missing SetDoesNotUseRepo(true) * test: test/cli/commands_without_repo_test.go | 1 年前 | |
chore(ci): remove self-hosted runners [skip changelog] (#11426) * ci: remove self-hosted runners * test: fix zsh completion test on hosted runners The test runs compinit in a non-interactive zsh. When a directory in fpath is writable by group or others, compinit asks a question. There is no terminal to answer it, so compinit aborts and the test fails. GitHub-hosted runner images have such a directory. compinit -i skips insecure directories without asking. The test checks kubo's generated completion script, not the permissions of the host's zsh directories. --------- Co-authored-by: Marcin Rataj <lidel@lidel.org> | 28 天前 | |
fix(config): protect and derive PeerID during JSON replace (#11344) * commands: derive peer ID on config replace Signed-off-by: morning-verlu <258725120+morning-verlu@users.noreply.github.com> * feat: validate Identity.PeerID against node key Setting Identity.PeerID to a value that disagrees with the node's private key produces a config the node refuses to start with. The config command now validates the field against the stored key, the same way config replace re-derives it. - reject a mismatched Identity.PeerID and point at `ipfs key rotate`; accept the node's own PeerID in any base58 or CIDv1 form and store the canonical base58 string - share the PeerID derivation between the set path and config replace - document the identity fields and `ipfs key rotate` in docs/config.md - cover the set-path guard and base36 normalization in test/cli - switch the t0070 sharness probe off Identity.PeerID, now validated --------- Signed-off-by: morning-verlu <258725120+morning-verlu@users.noreply.github.com> Co-authored-by: morning-verlu <258725120+morning-verlu@users.noreply.github.com> Co-authored-by: Guillaume Michel <guillaumemichel@users.noreply.github.com> Co-authored-by: Andrew Gillis <11790789+gammazero@users.noreply.github.com> Co-authored-by: Marcin Rataj <lidel@lidel.org> | 2 个月前 | |
refactor: apply go fix modernizers from Go 1.26 (#11190) * chore: apply go fix modernizers from Go 1.26 automated refactoring: interface{} to any, slices.Contains, and other idiomatic updates. * feat(ci): add `go fix` check to Go analysis workflow ensures Go 1.26 modernizers are applied, fails CI if `go fix ./...` produces any changes (similar to existing `go fmt` enforcement) | 6 个月前 | |
chore: replace random test utils with equivalents in go-test/random (#10915) Replace test functionality that is dublicated in go-test/random | 1 年前 | |
refactor: remove goprocess (#10872) * refactor: remove goprocess The `goprocess` package is no longer needed. It can be replaces by modern `context` and `context.AfterFunc`. * mod tidy * log unmount errors on shutdown * Do not log non-mounted errors on shutdown * Use WaitGroup associated with IPFS node to wait for services to whutdown * Prefer explicit Close to context.ArterFunc * Do not use node-level WaitGroup * Unmount for non-supported platforms * fix return values * test: daemon shuts down gracefully make sure ongoing operations dont block shutdown * test(cli): add TestFUSE * test: smarter RequiresFUSE opportunistically run FUSE tests if env has fusermount and TEST_FUSE was not explicitly set * docs: changelog --------- Co-authored-by: gammazero <gammazero@users.noreply.github.com> Co-authored-by: Marcin Rataj <lidel@lidel.org> | 1 年前 | |
feat(config): add Import.* for CID Profiles from IPIP-499 (#11148) * feat(config): Import.* and unixfs-v1-2025 profile implements IPIP-499: add config options for controlling UnixFS DAG determinism and introduces `unixfs-v1-2025` and `unixfs-v0-2015` profiles for cross-implementation CID reproducibility. changes: - add Import.* fields: HAMTDirectorySizeEstimation, SymlinkMode, DAGLayout, IncludeEmptyDirectories, IncludeHidden - add validation for all Import.* config values - add unixfs-v1-2025 profile (recommended for new data) - add unixfs-v0-2015 profile (alias: legacy-cid-v0) - remove deprecated test-cid-v1 and test-cid-v1-wide profiles - wire Import.HAMTSizeEstimationMode() to boxo globals - update go.mod to use boxo with SizeEstimationMode support ref: https://specs.ipfs.tech/ipips/ipip-0499/ * feat(add): add --dereference-symlinks, --empty-dirs, --hidden CLI flags add CLI flags for controlling file collection behavior during ipfs add: - `--dereference-symlinks`: recursively resolve symlinks to their target content (replaces deprecated --dereference-args which only worked on CLI arguments). wired through go-ipfs-cmds to boxo's SerialFileOptions. - `--empty-dirs` / `-E`: include empty directories (default: true) - `--hidden` / `-H`: include hidden files (default: false) these flags are CLI-only and not wired to Import.* config options because go-ipfs-cmds library handles input file filtering before the directory tree is passed to kubo. removed unused Import.UnixFSSymlinkMode config option that was defined but never actually read by the CLI. also: - wire --trickle to Import.UnixFSDAGLayout config default - update go-ipfs-cmds to v0.15.1-0.20260117043932-17687e216294 - add SYMLINK HANDLING section to ipfs add help text - add CLI tests for all three flags ref: https://github.com/ipfs/specs/pull/499 * test(add): add CID profile tests and wire SizeEstimationMode add comprehensive test suite for UnixFS CID determinism per IPIP-499: - verify exact HAMT threshold boundary for both estimation modes: - v0-2015 (links): sum(name_len + cid_len) == 262144 - v1-2025 (block): serialized block size == 262144 - verify HAMT triggers at threshold + 1 byte for both profiles - add all deterministic CIDs for cross-implementation testing also wires SizeEstimationMode through CLI/API, allowing Import.UnixFSHAMTSizeEstimation config to take effect. bumps boxo to ipfs/boxo@6707376 which aligns HAMT threshold with JS implementation (uses > instead of >=), fixing CID determinism at the exact 256 KiB boundary. * feat(add): --dereference-symlinks now resolves all symlinks Previously, resolving symlinks required two flags: - --dereference-args: resolved symlinks passed as CLI arguments - --dereference-symlinks: resolved symlinks inside directories Now --dereference-symlinks handles both cases. Users only need one flag to fully dereference symlinks when adding files to IPFS. The deprecated --dereference-args still works for backwards compatibility but is no longer necessary. * chore: update boxo and improve changelog - update boxo to ebdaf07c (nil filter fix, thread-safety docs) - simplify changelog for IPIP-499 section - shorten test names, move context to comments * chore: update boxo to 5cf22196 * chore: apply suggestions from code review Co-authored-by: Andrew Gillis <11790789+gammazero@users.noreply.github.com> * test(add): verify balanced DAG layout produces uniform leaf depth add test that confirms kubo uses balanced layout (all leaves at same depth) rather than balanced-packed (varying depths). creates 45MiB file to trigger multi-level DAG and walks it to verify leaf depth uniformity. includes trickle subtest to validate test logic can detect varying depths. supports CAR export via DAG_LAYOUT_CAR_OUTPUT env var for test vectors. * chore(deps): update boxo to 6141039ad8ef switches to https://github.com/ipfs/boxo/pull/1088/commits/6141039ad8ef098c3b65db8b2d1aeb3c16727c6c changes since 5cf22196ad0b: - refactor(unixfs): use arithmetic for exact block size calculation - refactor(unixfs): unify size tracking and make SizeEstimationMode immutable - feat(unixfs): optimize SizeEstimationBlock and add mode/mtime tests also clarifies that directory sharding globals affect both `ipfs add` and MFS. * test(cli): improve HAMT threshold tests with exact +1 byte verification - add UnixFSDataType() helper to directly check UnixFS type via protobuf - refactor threshold tests to use exact +1 byte calculations instead of +1 file - verify directory type directly (ft.TDirectory vs ft.THAMTShard) instead of inferring from link count - clean up helper function signatures by removing unused cidLength parameter * test(cli): consolidate profile tests into cid_profiles_test.go remove duplicate profile threshold tests from add_test.go since they are fully covered by the data-driven tests in cid_profiles_test.go. changes: - improve test names to describe what threshold is being tested - add inline documentation explaining each test's purpose - add byte-precise helper IPFSAddDeterministicBytes for threshold tests - remove ~200 lines of duplicated test code from add_test.go - keep non-profile tests (pinning, symlinks, hidden files) in add_test.go * chore: update to rebased boxo and go-ipfs-cmds PRs * docs: add HAMT threshold fix details to changelog * feat(mfs): use Import config for CID version and hash function make MFS commands (files cp, files write, files mkdir, files chcid) respect Import.CidVersion and Import.HashFunction config settings when CLI options are not explicitly provided. also add tests for: - files write respects Import.UnixFSRawLeaves=true - single-block file: files write produces same CID as ipfs add - updated comments clarifying CID parity with ipfs add * feat(files): wire Import.UnixFSChunker and UnixFSDirectoryMaxLinks to MFS `ipfs files` commands now respect these Import.* config options: - UnixFSChunker: configures chunk size for `files write` - UnixFSDirectoryMaxLinks: triggers HAMT sharding in `files mkdir` - UnixFSHAMTDirectorySizeEstimation: controls size estimation mode previously, MFS used hardcoded defaults ignoring user config. changes: - config/import.go: add UnixFSSplitterFunc() returning chunk.SplitterGen - core/node/core.go: pass chunker, maxLinks, sizeEstimationMode to mfs.NewRoot() via new boxo RootOption API - core/commands/files.go: pass maxLinks and sizeEstimationMode to mfs.Mkdir() and ensureContainingDirectoryExists(); document that UnixFSFileMaxLinks doesn't apply to files write (trickle DAG limitation) - test/cli/files_test.go: add tests for UnixFSDirectoryMaxLinks and UnixFSChunker, including CID parity test with `ipfs add --trickle` related: boxo@54e044f1b265 * feat(files): wire Import.UnixFSHAMTDirectoryMaxFanout and UnixFSHAMTDirectorySizeThreshold wire remaining HAMT config options to MFS root: - Import.UnixFSHAMTDirectoryMaxFanout via mfs.WithMaxHAMTFanout - Import.UnixFSHAMTDirectorySizeThreshold via mfs.WithHAMTShardingSize add CLI tests: - files mkdir respects Import.UnixFSHAMTDirectoryMaxFanout - files mkdir respects Import.UnixFSHAMTDirectorySizeThreshold - config change takes effect after daemon restart add UnixFSHAMTFanout() helper to test harness update boxo to ac97424d99ab90e097fc7c36f285988b596b6f05 * fix(mfs): single-block files in CIDv1 dirs now produce raw CIDs problem: `ipfs files write` in CIDv1 directories wrapped single-block files in dag-pb even when raw-leaves was enabled, producing different CIDs than `ipfs add --raw-leaves` for the same content. fix: boxo now collapses single-block ProtoNode wrappers (with no metadata) to RawNode in DagModifier.GetNode(). files with mtime/mode stay as dag-pb since raw blocks cannot store UnixFS metadata. also fixes sparse file writes where writing past EOF would lose data because expandSparse didn't update the internal node pointer. updates boxo to v0.36.1-0.20260203003133-7884ae23aaff updates t0250-files-api.sh test hashes to match new behavior * chore(test): use Go 1.22+ range-over-int syntax * chore: update boxo to c6829fe26860 - fix typo in files write help text - update boxo with CI fixes (gofumpt, race condition in test) * chore: update go-ipfs-cmds to 192ec9d15c1f includes binary content types fix: gzip, zip, vnd.ipld.car, vnd.ipld.raw, vnd.ipfs.ipns-record * chore: update boxo to 0a22cde9225c includes refactor of maxLinks check in addLinkChild (review feedback). * ci: fix helia-interop and improve caching skip '@helia/mfs - should have the same CID after creating a file' test until helia implements IPIP-499 (tracking: https://github.com/ipfs/helia/issues/941) the test fails because kubo now collapses single-block files to raw CIDs while helia explicitly uses reduceSingleLeafToSelf: false changes: - run aegir directly instead of helia-interop binary (binary ignores --grep flags) - cache node_modules keyed by @helia/interop version from npm registry - skip npm install on cache hit (matches ipfs-webui caching pattern) * chore: update boxo to 1e30b954 includes latest upstream changes from boxo main * chore: update go-ipfs-cmds to 1b2a641ed6f6 * chore: update boxo to f188f79fd412 switches to boxo@main after merging https://github.com/ipfs/boxo/pull/1088 * chore: update go-ipfs-cmds to af9bcbaf5709 switches to go-ipfs-cmds@master after merging https://github.com/ipfs/go-ipfs-cmds/pull/315 --------- Co-authored-by: Andrew Gillis <11790789+gammazero@users.noreply.github.com> | 7 个月前 | |
fix: avoid redundant cidset in dag stat (#11353) boxo's Traverse already dedups each root with its own seen set, so the command-level cid.Set held a second copy of every CID in the DAG. On a multi-hundred-GiB root that doubled the dedup memory and OOM-killed daemons mid-stat. - allocate the set only for multiple roots (cross-root dedup needs it) - single root derives UniqueBlocks from the per-root block count | 3 个月前 | |
fix(http-routing): keep browser transports in provider records (#11394) * chore: bump go-libp2p for sorted confirmed addrs Pin the head commit of libp2p/go-libp2p#3526: AutoNAT V2's ConfirmedAddrs returned unsorted buckets, and removeNotInSource silently dropped webrtc-direct from the confirmed set. Switch to a master pseudo-version once the PR merges. * fix: keep browser transports in provider records Provider records sent to HTTP routers were narrowed to the addresses AutoNAT V2 confirmed reachable, which silently dropped the only two transports a browser can dial: the AutoTLS /tls/ws address and webrtc-direct. A publicly reachable node was invisible to browser and Helia clients that found it through a delegated router, even though ipfs id and the DHT both advertised those addresses. AutoNAT only ever sees listen addresses, so the AutoTLS address, which the AddrsFactory synthesizes afterwards, can never reach the confirmed set. webrtc-direct does get confirmed, but go-libp2p loses it again in getConfirmedAddrs, which feeds an unsorted slice to a scan that assumes sorted input; that one is fixed upstream in libp2p/go-libp2p#3526. Announce host.Addrs() instead, the same set identify sends to peers and the DHT already publishes, narrowed to globally routable addresses so loopback and LAN entries stay out of a public index. Nodes with no public address keep announcing what they have, so LAN-only setups pointing at a local router are unaffected. - core/node/libp2p/routingopt.go: drop the ConfirmedAddrs branch from httpRouterAddrFunc, filter host.Addrs() with manet.IsPublicAddr; AppendAnnounce is emitted exactly once and does not count toward the public-addr check - core/commands/swarm_addrs_autonat.go: take over the BasicHost compile-time assertion, now the only ConfirmedAddrs consumer Fixes #11369 * docs: move highlight to v0.43 and scope it The fix ships in v0.43, so the entry moves out of v0.44.md and in next to the other browser-retrieval highlights. - names the config it applies to: Routing.Type=custom with a provide method on an HTTP router. Default auto provides over the DHT alone and is unaffected, since constructDefaultHTTPRouters leaves ProvideRouter as a noop. - cites bitsocial.net, which runs libp2p in the browser and uses delegated routers to find peers, as the app the gap broke | 1 个月前 | |
shutdown daemon after test (#11135) | 7 个月前 | |
test: fix flakes that force CI re-runs (#11413) * fix(routing): keep peers found before the timeout The DHT returns the closest peers it reached together with the context error when a lookup runs past its deadline. We dropped both, so any lookup slower than the routing server's per-request timeout came back as HTTP 500 with nothing in it, indistinguishable from a lookup that found no peers at all. Return what we have, and only error when the set is empty. * test: use local dht swarm for routing v1 test GetClosestPeers joined the public Amino DHT with real bootstrap peers, so the assertions depended on a CI runner reaching bootstrap.libp2p.io from a cold repo. When it could not, the test retried for five minutes and failed; ten such failures since v0.42.0, every one green on re-run. Bootstrap from the harness's in-process DHT peers instead, which the provider tests already use and this one predates. The window drops from five minutes to sixty seconds because there is no longer anything slow to wait for, and passing runs go from tens of seconds to under one. * test: stop handing out ports the kernel reuses NewRandPort binds port zero, notes the number, closes the socket and hands the number to the caller, which leaves a window for anything else on the machine to take it. The number also came from the ephemeral range, the same pool every outgoing connection draws from, and the CLI suite opens a lot of those. Both TestP2PForeground tunnel subtests died on "bind: address already in use" for a server the test binds itself. - NewTCPListener hands back the bound listener, closing that window for callers that listen in-process - ports for daemons we spawn now come from below the ephemeral range, so an outgoing connection cannot land on one * test: sync gc tests to the adder, not the clock TestAddGCLive asserted that gc had not started yet, but the only thing it waited for was the first file's output event. Between that event and the adder reaching the next file there is a gap, and the adder hands the pin lock to a waiting gc at exactly that boundary, so on a loaded runner gc really had started and the assertion was right to fail. Wrap the pipe so the test learns when the adder is inside the hanging file, and poll GCRequested instead of sleeping 100ms to know gc is queued. TestAddMultipleGCLive gets the same treatment for its two sleeps: too short there means gc never gets the lock and the test waits out its five second timeout instead. * test: move watched file in atomically os.WriteFile creates the file and fills it in two steps, and ipfswatch adds whatever is on disk when the create event wakes it. Catch it between the two and it adds an empty file, so the CID the test pulls out of the log reads back as nothing. Stage the file outside the watched directory and rename it in, which the watcher sees as one event for a file that is already complete. * test(sharness): poll the daemon request log The test backgrounded "ipfs log tail", slept 100ms and expected the daemon to be listing the request. The daemon only sees it once the client has started up and connected, which on a loaded runner takes longer than that, and then both the active and the inactive assertion fail together because the entry never appears at all. Poll for each state instead. The extra requests that polling makes push the daemon closer to the point where it drops finished entries from the log, so keep them with "diag cmds set-time" first. * test(sharness): drop stale peer count check The connect case opened by re-asserting that the previous case had left zero peers connected. Disconnecting is not permanent: the DHT keeps the other node in its routing table and re-dials it on any refresh, so that count is only true for as long as nothing else runs. What this case is named for, connecting with a bare /p2p/ address, is still covered by the connect itself and the peer count after it. * test(fuse): mount one node at a time Every parallel subtest does identical setup before mounting, so they all reach the mount together and around twenty setuid fusermount helpers open /dev/fuse inside the same instant. One occasionally comes back with a bare exit status 1. Take a lock for the mount call itself, which the subtests only hold for tens of milliseconds. Also report the failure instead of panicking: a panic failed all 37 tests in the package and left daemons behind, and the daemon's stderr, where fusermount says what actually went wrong, was captured and then thrown away. * test: compare cat output byte for byte The payload is 100 random bytes and the comparison ran through Trimmed(), which strips one trailing newline. Roughly one run in 256 ends in 0x0a and loses it. * test: wait for the fast-provide log line The daemon writes the line before it answers the RPC, but the test reads a buffer that a goroutine fills by copying the daemon's stderr, and that copy can still be behind when the command returns. Wait for the line rather than assuming it has landed. * test: allow for ipns republish mid-test A minute after the daemon starts, the republisher re-signs every key and publishes it again, giving the same value a new signature and expiry. The test captured one PUT body and compared it byte for byte with what routing returned, so a run slow enough to straddle that minute compared the first record against the second. Keep every record the mock is sent and require that routing's answer is one of them, which is what the assertion was reaching for. * fix(examples): turn off mdns in library example The example connects its two nodes by address, but left mDNS on, so local discovery could connect them first. A connection opened while a node is still being built is invisible to that node's bitswap, which only learns about connections made after it registers its notifier, and with no routing configured there is nothing to fall back on. The final fetch then waited forever and the test died on its two minute timeout with no clue why. Turning mDNS off makes the explicit dial the only way the two can meet, and keeps the example off the reader's LAN. Alongside that: - connectToPeers returns dial errors instead of logging and continuing into a fetch that cannot succeed - the example's own deadline now fits inside the test budget, so a stall names the step that hung - CommandContext so a hung child does not outlive the test * ci: make helia-interop job resilient Seven failures since v0.42.0 came from this job's setup rather than from any incompatibility. It installs whatever @helia/interop published last, and upstream shipped three packages in a row whose test config does not work from inside node_modules; a GitHub blip took out the rest. - find the compiled specs and pass them to aegir, instead of patching the config upstream ships into node_modules and grepping its text - pin node to a major: setup-node resolves an lts/ alias through a GitHub manifest with no retry and no fallback, and newer node rejects a flag aegir sets unconditionally - retry the registry lookup and fail loudly, since the old one-liner could not fail and left an empty cache key behind - install the exact version the cache key names, and only save the cache once the install is known good - drop the playwright apt packages, unused since this job stopped running browser targets | 1 个月前 | |
refactor: apply go fix modernizers from Go 1.26 (#11190) * chore: apply go fix modernizers from Go 1.26 automated refactoring: interface{} to any, slices.Contains, and other idiomatic updates. * feat(ci): add `go fix` check to Go analysis workflow ensures Go 1.26 modernizers are applied, fails CI if `go fix ./...` produces any changes (similar to existing `go fmt` enforcement) | 6 个月前 | |
shutdown daemon after test (#11135) | 7 个月前 | |
fix(provider): purge keystore datastore after reset (#11198) * fix(provider): purge keystore datastore after reset * changelog * use MapDatastore if no datastore is configured * bump kad-dht to latest commit * purge orphaned keystore migration * bump kad-dht * use main datastore for keystore "meta" store * add provider/keystore/0 and /1 to ipfs diag command mount keystore datastores to /provider/keystore/0 and /1 so that they are included in the ipfs diag datastore command * fix(provider): reject unexpected keystore suffix to prevent stray deletions destroyDs calls os.RemoveAll with a suffix from the upstream library. If suffix were ever ".." or empty, this could delete wrong directories. Validate that suffix is "0" or "1" in both createDs and destroyDs. * fix(provider): close opened datastores when mounting partially fails If opening datastore "0" succeeds but "1" fails, MountKeystoreDatastores returned an error without closing "0". * fix(provider): defer batch creation in orphan purge until keys are found Avoids allocating a datastore batch when no orphaned keys exist. * fix(provider): warn on unrecognized datastore wrapper types findRootDatastoreSpec silently returns wrapper specs it doesn't know about. If a plugin adds a wrapper with a "child" field, openDatastoreAt gets the wrapper instead of the leaf backend and fails confusingly. Log a warning so operators can spot the issue. * docs: document keystore migration behavior on upgrade and downgrade - explain why context.Background() is used in the migration code - add changelog note about the provide cycle restarting on upgrade - add downgrade caveat about orphaned provider-keystore directory * chore(deps): bump go-libp2p-kad-dht to latest keystore factory commit * fix(provider): harden keystore migration and spec handling - chunk orphan purge into 4096-key batches to bound memory and match existing batching patterns in the same file - cancel the purge context via fx.Lifecycle OnStop so SIGINT during startup does not block indefinitely - deep-copy slices in copySpec (not just maps) so the function matches its documented "deep-copy" contract - return nil from findRootDatastoreSpec when no "/" mount exists, so callers fall back to in-memory instead of passing a mount-type spec to openDatastoreAt - rename local variable to avoid shadowing the mount package import * test(provider): add migration purge test and diag datastore put command - add `ipfs diag datastore put` subcommand for writing arbitrary key-value pairs to the datastore (offline, experimental) - add DatastorePut harness helper for CLI tests - add TestProviderKeystoreMigrationPurge: seeds orphaned keystore keys via `put`, starts the daemon to trigger migration, verifies the orphaned keys are purged and provider-keystore/ dir is created - add put/get roundtrip test for diag datastore * chore(deps): bump go-libp2p-kad-dht to 1bede74b8246 * fix(provider): log keystore datastore create and destroy operations * docs: rewrite provider keystore changelog to focus on user impact * bump kad-dht@master --------- Co-authored-by: Marcin Rataj <lidel@lidel.org> | 5 个月前 | |
feat(dns): skip DNS lookups for AutoTLS hostnames (#11140) * feat(dns): resolve libp2p.direct addresses locally without network I/O p2p-forge hostnames encode IP addresses directly (e.g., 1-2-3-4.peerID.libp2p.direct -> 1.2.3.4), so DNS queries are wasteful. kubo now parses these IPs in-memory. - applies to both default libp2p.direct and custom AutoTLS.DomainSuffix - TXT queries still delegate to network for ACME DNS-01 compatibility - https://github.com/ipfs/kubo/pull/11140#discussion_r2683477754 use fallback to network DNS instead of returning errors when local parsing fails, ensuring forward compatibility with future DNS records - https://github.com/ipfs/kubo/pull/11140#discussion_r2683512408 add peerID validation using peer.Decode(), matching libp2p.direct server behavior, with fallback on invalid peerID - https://github.com/ipfs/kubo/pull/11140#discussion_r2683521930 document interaction with DNS.Resolvers in config.md - https://github.com/ipfs/kubo/pull/11140#discussion_r2683526647 add AutoTLS.SkipDNSLookup config flag to disable local resolution (useful for debugging or custom DNS override scenarios) - https://github.com/ipfs/kubo/pull/11140#discussion_r2683533462 add E2E test verifying libp2p.direct resolves locally even when DNS.Resolvers points to a broken server additional improvements: - use madns.BasicResolver interface instead of custom basicResolver - add compile-time interface checks for p2pForgeResolver and madns.Resolver - refactor tests: merge IPv4/IPv6, add helpers, use config.DefaultDomainSuffix - improve changelog to explain public good benefit (reducing DNS load) Fixes #11136 | 7 个月前 | |
fix(mfs): respect Import config (#11273) * test(deps): quick test of boxo with ipfs/boxo#1125 * test(mfs): verify CidBuilder preservation across mutations and restarts * docs(changelog): highlight MFS CidBuilder fix * fix(mfs): apply Import.CidVersion and HashFunction to MFS root The MFS root loaded at daemon startup never received a CidBuilder from config, so it stayed CIDv0/sha2-256 even with non-default Import settings. Pass the configured CidBuilder to mfs.NewRoot(). - add Import.UnixFSCidBuilder() helper for building cid.Prefix - pass WithCidBuilder to mfs.NewRoot in core/node/core.go - deduplicate getPrefixNew/getPrefix in files.go - strengthen regression test to check CID version and root dir * fix: restore explicit Flush, use upstream boxo - restore explicit Flush: false in addNode and addDir Mkdir calls that was dropped during the MkdirOpts refactor - use %q for hash function error message in getPrefix - switch from boxo fork replace to upstream boxo@98dabcc * fix(config): always build explicit CidBuilder from defaults UnixFSCidBuilder used to return nil when CidVersion and HashFunction matched compile-time defaults, relying on boxo's internal CIDv0/sha2-256 fallback. This will break when DefaultCidVersion changes to 1, because boxo will keep using CIDv0 regardless. - remove early-return short-circuit in UnixFSCidBuilder - add unit tests for explicit and default CidBuilder construction Refs: https://github.com/ipfs/kubo/issues/4143 * fix(files): reject chcid on MFS root path The MFS root CID format is now always set from Import.CidVersion and Import.HashFunction at startup, so chcid on "/" was silently overridden on every subsequent command or daemon restart. - chcid now requires a path argument and rejects "/" - help text and changelog explain how to change root CID format - sharness tests use Import config + daemon restarts instead of chcid / - added test for chcid on subdirectories with blake2b-256 * chore(deps): update boxo to latest main Picks up ipfs/boxo#1131: fix concurrent flush/close panic in MFS file descriptors (FUSE race condition). * fix(test): sharness daemon pairing and stale shard hash - add restart_daemon helper to avoid tripping t0015 meta-test that counts literal test_kill/test_launch pairs in each file - update cidv1 SHARD_HASH to match current boxo HAMT output --------- Co-authored-by: Andrew Gillis <11790789+gammazero@users.noreply.github.com> | 5 个月前 | |
feat(config): add Gateway.MaxRequestDuration option (#11138) * feat(config): add Gateway.MaxRequestDuration option exposes the previously hardcoded 1 hour gateway request deadline as a configurable option, allowing operators to adjust it to fit deployment needs. protects gateway from edge cases and slow client attacks. boxo: https://github.com/ipfs/boxo/pull/1079 * test(gateway): add MaxRequestDuration integration test verifies config is wired correctly and 504 is returned when exceeded * docs: add MaxRequestDuration to gateway production guide --------- Co-authored-by: Andrew Gillis <11790789+gammazero@users.noreply.github.com> | 7 个月前 | |
shutdown daemon after test (#11135) | 7 个月前 | |
fix: Ipfs-Uri gateway header (IPIP-548) (#11437) * feat: Ipfs-Uri gateway header (IPIP-548) Bump boxo to the IPIP-548 implementation (ipfs/boxo#1209): gateway responses carry a canonical percent-encoded Ipfs-Uri header and stop sending the deprecated X-Ipfs-Path, which cannot represent every UnixFS file name. - sharness: CORS expects Ipfs-Uri exposed, X-Ipfs-Path gone - gateway-conformance CI pinned to the IPIP-548 test suite (ipfs/gateway-conformance#301) until a release ships - reverse-proxy doc and v0.44 changelog updated Refs ipfs/specs#548 * feat: opt-in Gateway.DeprecatedXIpfsPath Expose boxo's opt-in for the legacy X-Ipfs-Path response header as a kubo config flag, default off. Unsafe: the legacy value cannot represent every UnixFS file name, so it must only be used to facilitate migration to Ipfs-Uri, and even when enabled the header is still skipped when the value would include non-ASCII byte sequences. Refs ipfs/specs#548 * ci: bump gateway-conformance pin * ci: gateway-conformance v0.14 * chore: boxo with IPIP-548 from boxo/main * docs: Ipfs-Uri changelog in v0.43.1 * docs: assemble v0.43.1 changelog Move the v0.44 highlights and dependency lines into a new v0.43.1 section, and add the missing entry for owner-only key exports (#11428). v0.44.md returns to an empty skeleton. * docs: note boxo v0.42.2 fixes in v0.43.1 | 15 天前 | |
test: cover ipfs get paths containing closing bracket (#11359) * test: cover ipfs get paths containing closing bracket * test: move get punctuation coverage to test/cli ipfs get must retrieve UnixFS paths whose segments contain punctuation that is valid on Linux, macOS, and Windows but is sensitive to a POSIX shell (issue #9369, where a "]" segment failed). AGENTS.md prefers test/cli for new integration tests, and driving ipfs directly avoids the shell-quoting limits of the sharness loop. - add test/cli/get_test.go: add a directory with one file per segment, then get each "<cid>/<segment>" and compare bytes, exercised both offline and against a daemon - cover the apostrophe segment, which the single-quoted sharness test body could not include - drop the now-redundant punctuation block from t0090-get.sh --------- Co-authored-by: Guillaume Michel <guillaumemichel@users.noreply.github.com> Co-authored-by: Marcin Rataj <lidel@lidel.org> | 2 个月前 | |
shutdown daemon after test (#11135) | 7 个月前 | |
test: fix flakes that force CI re-runs (#11413) * fix(routing): keep peers found before the timeout The DHT returns the closest peers it reached together with the context error when a lookup runs past its deadline. We dropped both, so any lookup slower than the routing server's per-request timeout came back as HTTP 500 with nothing in it, indistinguishable from a lookup that found no peers at all. Return what we have, and only error when the set is empty. * test: use local dht swarm for routing v1 test GetClosestPeers joined the public Amino DHT with real bootstrap peers, so the assertions depended on a CI runner reaching bootstrap.libp2p.io from a cold repo. When it could not, the test retried for five minutes and failed; ten such failures since v0.42.0, every one green on re-run. Bootstrap from the harness's in-process DHT peers instead, which the provider tests already use and this one predates. The window drops from five minutes to sixty seconds because there is no longer anything slow to wait for, and passing runs go from tens of seconds to under one. * test: stop handing out ports the kernel reuses NewRandPort binds port zero, notes the number, closes the socket and hands the number to the caller, which leaves a window for anything else on the machine to take it. The number also came from the ephemeral range, the same pool every outgoing connection draws from, and the CLI suite opens a lot of those. Both TestP2PForeground tunnel subtests died on "bind: address already in use" for a server the test binds itself. - NewTCPListener hands back the bound listener, closing that window for callers that listen in-process - ports for daemons we spawn now come from below the ephemeral range, so an outgoing connection cannot land on one * test: sync gc tests to the adder, not the clock TestAddGCLive asserted that gc had not started yet, but the only thing it waited for was the first file's output event. Between that event and the adder reaching the next file there is a gap, and the adder hands the pin lock to a waiting gc at exactly that boundary, so on a loaded runner gc really had started and the assertion was right to fail. Wrap the pipe so the test learns when the adder is inside the hanging file, and poll GCRequested instead of sleeping 100ms to know gc is queued. TestAddMultipleGCLive gets the same treatment for its two sleeps: too short there means gc never gets the lock and the test waits out its five second timeout instead. * test: move watched file in atomically os.WriteFile creates the file and fills it in two steps, and ipfswatch adds whatever is on disk when the create event wakes it. Catch it between the two and it adds an empty file, so the CID the test pulls out of the log reads back as nothing. Stage the file outside the watched directory and rename it in, which the watcher sees as one event for a file that is already complete. * test(sharness): poll the daemon request log The test backgrounded "ipfs log tail", slept 100ms and expected the daemon to be listing the request. The daemon only sees it once the client has started up and connected, which on a loaded runner takes longer than that, and then both the active and the inactive assertion fail together because the entry never appears at all. Poll for each state instead. The extra requests that polling makes push the daemon closer to the point where it drops finished entries from the log, so keep them with "diag cmds set-time" first. * test(sharness): drop stale peer count check The connect case opened by re-asserting that the previous case had left zero peers connected. Disconnecting is not permanent: the DHT keeps the other node in its routing table and re-dials it on any refresh, so that count is only true for as long as nothing else runs. What this case is named for, connecting with a bare /p2p/ address, is still covered by the connect itself and the peer count after it. * test(fuse): mount one node at a time Every parallel subtest does identical setup before mounting, so they all reach the mount together and around twenty setuid fusermount helpers open /dev/fuse inside the same instant. One occasionally comes back with a bare exit status 1. Take a lock for the mount call itself, which the subtests only hold for tens of milliseconds. Also report the failure instead of panicking: a panic failed all 37 tests in the package and left daemons behind, and the daemon's stderr, where fusermount says what actually went wrong, was captured and then thrown away. * test: compare cat output byte for byte The payload is 100 random bytes and the comparison ran through Trimmed(), which strips one trailing newline. Roughly one run in 256 ends in 0x0a and loses it. * test: wait for the fast-provide log line The daemon writes the line before it answers the RPC, but the test reads a buffer that a goroutine fills by copying the daemon's stderr, and that copy can still be behind when the command returns. Wait for the line rather than assuming it has landed. * test: allow for ipns republish mid-test A minute after the daemon starts, the republisher re-signs every key and publishes it again, giving the same value a new signature and expiry. The test captured one PUT body and compared it byte for byte with what routing returned, so a run slow enough to straddle that minute compared the first record against the second. Keep every record the mock is sent and require that routing's answer is one of them, which is what the assertion was reaching for. * fix(examples): turn off mdns in library example The example connects its two nodes by address, but left mDNS on, so local discovery could connect them first. A connection opened while a node is still being built is invisible to that node's bitswap, which only learns about connections made after it registers its notifier, and with no routing configured there is nothing to fall back on. The final fetch then waited forever and the test died on its two minute timeout with no clue why. Turning mDNS off makes the explicit dial the only way the two can meet, and keeps the example off the reader's LAN. Alongside that: - connectToPeers returns dial errors instead of logging and continuing into a fetch that cannot succeed - the example's own deadline now fits inside the test budget, so a stall names the step that hung - CommandContext so a hung child does not outlive the test * ci: make helia-interop job resilient Seven failures since v0.42.0 came from this job's setup rather than from any incompatibility. It installs whatever @helia/interop published last, and upstream shipped three packages in a row whose test config does not work from inside node_modules; a GitHub blip took out the rest. - find the compiled specs and pass them to aegir, instead of patching the config upstream ships into node_modules and grepping its text - pin node to a major: setup-node resolves an lts/ alias through a GitHub manifest with no retry and no fallback, and newer node rejects a flag aegir sets unconditionally - retry the registry lookup and fail loudly, since the old one-liner could not fail and left an empty cache key behind - install the exact version the cache key names, and only save the cache once the install is known good - drop the playwright apt packages, unused since this job stopped running browser targets | 1 个月前 | |
fix: enforce identity CID size limits (#10949) * fix: enforce identity CID size limits - validate --inline-limit against verifcid.MaxDigestSize - add error when --hash=identity exceeds size limit - add tests for identity CID overflow scenarios - update help text to show maximum inline limit This prevents creation of unbounded identity CIDs by enforcing the 128-byte limit defined in https://github.com/ipfs/boxo/pull/1018 Fixes #6011 IPIP: https://github.com/ipfs/specs/pull/512 | 11 个月前 | |
fix(defaultServerFilters): strip loopback and non-public (#11286) * docs(server): document defaultServerFilters with RFC references Rework the `server` profile, `Addresses.NoAnnounce`, and `Swarm.AddrFilters` docs to make the default filter list scrutable, and annotate each entry in `defaultServerFilters` with its RFC origin. - profile.go: per-entry RFC inline comments on defaultServerFilters; godoc points at IANA special-purpose registries and cautions that changes here affect every server-profile user. - config.md NoAnnounce/AddrFilters: active-voice rewrites; cross-link publish-side and dial-side filters; consolidated tip pointing to the server profile section. - config.md server profile: IPv4 and IPv6 prefix tables with RFC references (multiaddr ipcidr notation); scenarios table for overriding specific entries; prose section for optional entries (IPv4 loopback, IPv6 outside 2000::/3) with trade-offs, motivated by loopback and unallocated IPv6 leaking into DHT announces since go-libp2p v0.47. * feat(server): strip loopback and non-public IPv6 from announces v0.40 switched libp2p to enumerate all interface addresses, which started leaking loopback, unallocated IPv6 space (e.g. 1e::/16), and other non-globally-reachable addresses into DHT and identify records of public IPFS nodes including bootstrap peers. adds three entries to defaultServerFilters applied to both Swarm.AddrFilters and Addresses.NoAnnounce: - /ip4/127.0.0.0/ipcidr/8: IPv4 loopback (RFC 1122) - /ip6/::1/ipcidr/128: IPv6 loopback (kept for documentation; subset of ::/3) - /ip6/::/ipcidr/3: everything outside global unicast 2000::/3 docs/config.md: overhaul server-profile section with per-entry RFC references, override guidance for Yggdrasil/NAT64/co-located loopback, and notes on /ip6/::/ipcidr/3 blast radius. docs/changelogs/v0.42.md: highlight entry with upgrade instructions for operators who already applied server profile before v0.42. * docs(server): sort filters, correct ::/3 wording The /ip6/::/ipcidr/3 CIDR matches only the IANA-reserved 0000::/3 block. Prior wording "everything outside global unicast 2000::/3" implied wider coverage; other non-2000::/3 blocks are IANA-reserved or already covered by fc00::/7 and fe80::/10, so behavior is unchanged. Also sort new entries into their numeric positions within the IPv4 and IPv6 blocks in both profile.go and the config.md tables. * docs(v0.41): server profile filter highlight Move the server profile changelog entry from v0.42 to v0.41 since the fix ships in v0.41. Also rewrite to lead with the concrete filter list addition, link to the server profile docs section for full details and override guidance, and warn that applying the profile disables LAN and localhost peer discovery. | 4 个月前 | |
test: fix flakes that force CI re-runs (#11413) * fix(routing): keep peers found before the timeout The DHT returns the closest peers it reached together with the context error when a lookup runs past its deadline. We dropped both, so any lookup slower than the routing server's per-request timeout came back as HTTP 500 with nothing in it, indistinguishable from a lookup that found no peers at all. Return what we have, and only error when the set is empty. * test: use local dht swarm for routing v1 test GetClosestPeers joined the public Amino DHT with real bootstrap peers, so the assertions depended on a CI runner reaching bootstrap.libp2p.io from a cold repo. When it could not, the test retried for five minutes and failed; ten such failures since v0.42.0, every one green on re-run. Bootstrap from the harness's in-process DHT peers instead, which the provider tests already use and this one predates. The window drops from five minutes to sixty seconds because there is no longer anything slow to wait for, and passing runs go from tens of seconds to under one. * test: stop handing out ports the kernel reuses NewRandPort binds port zero, notes the number, closes the socket and hands the number to the caller, which leaves a window for anything else on the machine to take it. The number also came from the ephemeral range, the same pool every outgoing connection draws from, and the CLI suite opens a lot of those. Both TestP2PForeground tunnel subtests died on "bind: address already in use" for a server the test binds itself. - NewTCPListener hands back the bound listener, closing that window for callers that listen in-process - ports for daemons we spawn now come from below the ephemeral range, so an outgoing connection cannot land on one * test: sync gc tests to the adder, not the clock TestAddGCLive asserted that gc had not started yet, but the only thing it waited for was the first file's output event. Between that event and the adder reaching the next file there is a gap, and the adder hands the pin lock to a waiting gc at exactly that boundary, so on a loaded runner gc really had started and the assertion was right to fail. Wrap the pipe so the test learns when the adder is inside the hanging file, and poll GCRequested instead of sleeping 100ms to know gc is queued. TestAddMultipleGCLive gets the same treatment for its two sleeps: too short there means gc never gets the lock and the test waits out its five second timeout instead. * test: move watched file in atomically os.WriteFile creates the file and fills it in two steps, and ipfswatch adds whatever is on disk when the create event wakes it. Catch it between the two and it adds an empty file, so the CID the test pulls out of the log reads back as nothing. Stage the file outside the watched directory and rename it in, which the watcher sees as one event for a file that is already complete. * test(sharness): poll the daemon request log The test backgrounded "ipfs log tail", slept 100ms and expected the daemon to be listing the request. The daemon only sees it once the client has started up and connected, which on a loaded runner takes longer than that, and then both the active and the inactive assertion fail together because the entry never appears at all. Poll for each state instead. The extra requests that polling makes push the daemon closer to the point where it drops finished entries from the log, so keep them with "diag cmds set-time" first. * test(sharness): drop stale peer count check The connect case opened by re-asserting that the previous case had left zero peers connected. Disconnecting is not permanent: the DHT keeps the other node in its routing table and re-dials it on any refresh, so that count is only true for as long as nothing else runs. What this case is named for, connecting with a bare /p2p/ address, is still covered by the connect itself and the peer count after it. * test(fuse): mount one node at a time Every parallel subtest does identical setup before mounting, so they all reach the mount together and around twenty setuid fusermount helpers open /dev/fuse inside the same instant. One occasionally comes back with a bare exit status 1. Take a lock for the mount call itself, which the subtests only hold for tens of milliseconds. Also report the failure instead of panicking: a panic failed all 37 tests in the package and left daemons behind, and the daemon's stderr, where fusermount says what actually went wrong, was captured and then thrown away. * test: compare cat output byte for byte The payload is 100 random bytes and the comparison ran through Trimmed(), which strips one trailing newline. Roughly one run in 256 ends in 0x0a and loses it. * test: wait for the fast-provide log line The daemon writes the line before it answers the RPC, but the test reads a buffer that a goroutine fills by copying the daemon's stderr, and that copy can still be behind when the command returns. Wait for the line rather than assuming it has landed. * test: allow for ipns republish mid-test A minute after the daemon starts, the republisher re-signs every key and publishes it again, giving the same value a new signature and expiry. The test captured one PUT body and compared it byte for byte with what routing returned, so a run slow enough to straddle that minute compared the first record against the second. Keep every record the mock is sent and require that routing's answer is one of them, which is what the assertion was reaching for. * fix(examples): turn off mdns in library example The example connects its two nodes by address, but left mDNS on, so local discovery could connect them first. A connection opened while a node is still being built is invisible to that node's bitswap, which only learns about connections made after it registers its notifier, and with no routing configured there is nothing to fall back on. The final fetch then waited forever and the test died on its two minute timeout with no clue why. Turning mDNS off makes the explicit dial the only way the two can meet, and keeps the example off the reader's LAN. Alongside that: - connectToPeers returns dial errors instead of logging and continuing into a fetch that cannot succeed - the example's own deadline now fits inside the test budget, so a stall names the step that hung - CommandContext so a hung child does not outlive the test * ci: make helia-interop job resilient Seven failures since v0.42.0 came from this job's setup rather than from any incompatibility. It installs whatever @helia/interop published last, and upstream shipped three packages in a row whose test config does not work from inside node_modules; a GitHub blip took out the rest. - find the compiled specs and pass them to aegir, instead of patching the config upstream ships into node_modules and grepping its text - pin node to a major: setup-node resolves an lts/ alias through a GitHub manifest with no retry and no fallback, and newer node rejects a flag aegir sets unconditionally - retry the registry lookup and fail loudly, since the old one-liner could not fail and left an empty cache key behind - install the exact version the cache key names, and only save the cache once the install is known good - drop the playwright apt packages, unused since this job stopped running browser targets | 1 个月前 | |
fix(key): restrict overwritten key exports to owner-only permissions (#11428) * fix(key): restrict overwritten key exports to owner-only permissions Signed-off-by: questfever <questfever@outlook.com> * fix(atomicfile): temp file leak and name limit Both problems surface through `ipfs key export`, which now writes through this helper, but they affect every caller: config writes, repo migrations and `ipfs update`. - remove the temporary file when the rename fails, so one holding private key material is not left next to the target - keep the ".tmp-" prefix and the random suffix within the 255 byte file name limit, so a target with a long name can still be written * fix(key): route key export by target type Choosing the write path with os.Lstat treated /dev/stdout, /dev/stderr and /dev/fd/N as plain paths, because they are symlinks into /proc/self/fd, so the atomic write failed on targets that worked before. Decide by what the path resolves to, and state the whole contract in the command help. - regular file or nothing yet: written to a temporary file and renamed over the target, following symlinks, including one whose target does not exist yet - character device or pipe: streamed in place, confirmed on the open descriptor and without O_TRUNC, so a path swapped for a regular file can neither receive the key nor be emptied - anything else: refused, naming the path - errors name the file the user asked for, and the temporary file is flushed before the rename * fix(key): stop export landing on the wrong file An export could replace a file the target symlink does not point at. resolveSymlink joined a relative link target onto the path as typed, so ".." collapsed lexically. Where a parent component was itself a symlink, the join named a file outside the directory the link resolves to: the key was renamed over that file, and the intended target was never written. The link's parent is now resolved with filepath.EvalSymlinks before the join. * test(key): drop umask dependency in export test os.WriteFile applies the umask, so under umask 077 the fixture was created 0600 and the check that a failed export leaves the file at 0644 failed for reasons unrelated to the code under test. The CLI test already chmods for the same reason. --------- Signed-off-by: questfever <questfever@outlook.com> Co-authored-by: Marcin Rataj <lidel@lidel.org> | 27 天前 | |
refactor: apply go fix modernizers from Go 1.26 (#11190) * chore: apply go fix modernizers from Go 1.26 automated refactoring: interface{} to any, slices.Contains, and other idiomatic updates. * feat(ci): add `go fix` check to Go analysis workflow ensures Go 1.26 modernizers are applied, fails CI if `go fix ./...` produces any changes (similar to existing `go fmt` enforcement) | 6 个月前 | |
feat(cli): add --human and --sort-size to ipfs ls (#11408) * feat(cli): add --human and --sort-size to ipfs ls - --human (-H): SI human-readable sizes in text output (humanize.Bytes) - --sort-size (-S): sort directory entries by size, largest first - Validation: --sort-size + --stream and --sort-size + --size=false errors - Unit tests for formatSize and sort helpers - CLI integration tests for both flags - Changelog highlight in v0.44 * test(ls): make sort tests fail when sorting breaks The tests covering --sort-size could not detect a broken feature. The unit tests copied the comparator into the test body and sorted with their own copy, so they passed regardless of what ls.go did. The CLI tests named each fixture after its size, which left alphabetical order and size order in agreement, so every ordering subtest passed even with --sort-size disabled outright. - extract lsLinkByName and lsLinkBySize so the tests exercise shipped code - point the unit tests at those two functions - name fixtures so their alphabetical order disagrees with their sizes - pin the real directory behaviour: UnixFS directories carry no Filesize, so they sort as 0, tie with empty files and break by name rather than landing strictly last * fix(ls): return 400 not 500 for bad flag combos Passing --sort-size together with --stream or --size=false made /api/v0/ls answer 500 Internal Server Error, telling API clients the server had broken when the caller had simply combined flags that cannot work together. Clients that retry on 5xx would retry a request that can never succeed. cmds.ErrClient maps to 400, matching how the rest of core/commands reports caller mistakes. CLI output is unchanged. * docs: fix --human size examples and JSON claims The help for --human advertised "1K 234M 2G", which no kubo command has ever printed. All three use humanize.Bytes, so the real output is SI with a space: 1.2 kB, 234 MB, 2.0 GB. The stale example was copied into 'ipfs ls' from the two commands that already carried it, so correct all three together. - ls, repo stat, bitswap stat: examples now match real output - drop the claim that --enc=json reports bytes. On the CLI, 'ipfs ls' has a PostRun that prints the text table whatever --enc says, so no JSON is produced there at all. Only the /api/v0/ls response is JSON, and that part is true - directories have no UnixFS Filesize, so they sort as 0 and tie with empty files. They do not land strictly last, so stop saying they do - changelog: a #### highlight with a TOC entry, kept short and pointing at 'ipfs ls --help' for the details - format sizes with strconv.FormatUint rather than fmt.Sprintf("%d") --------- Co-authored-by: Marcin Rataj <lidel@lidel.org> | 1 个月前 | |
feat(cli): ls --long (#11103) * Implements the -l/--long flag for the ipfs ls command to display Unix-style file permissions and modification times, similar to the traditional ls -l. When the --long flag is used, the output includes: - File mode/permissions in Unix format (e.g., -rw-r--r--, drwxr-xr-x) - File hash (CID) - File size (when --size is also specified) - Modification time in human-readable format - File name The permission string implementation handles all file types and special bits: - File types: regular (-), directory (d), symlink (l), named pipe (p), socket (s), character device (c), block device (b) - Special permission bits: setuid (s/S), setgid (s/S), sticky (t/T) - Lowercase when execute bit is set, uppercase when not set The timestamp format follows Unix ls conventions: - Recent files (within 6 months): "Jan 02 15:04" - Older files: "Jan 02 2006" Signed-off-by: sneax <paladesh600@gmail.com> * fix(ls): correct --long flag header order and help text - fix header column order: was "Mode Hash Size Name ModTime" but data outputs "Mode Hash Size ModTime Name", now headers match data order - remove redundant if/else branch in directory output that had identical code in both branches - add example output to help text showing format with mode, hash, size, mtime, and name columns - document that files without preserved metadata show '----------' for mode and '-' for mtime - add changelog entry for v0.40 * test(ls): add format stability tests for --long flag add tests to prevent formatting regressions in ipfs ls --long output: unit tests (core/commands/ls_test.go): - TestFormatMode: 20 cases covering all file types (regular, dir, symlink, pipe, socket, block/char devices) and special permission bits (setuid, setgid, sticky with/without execute) - TestFormatModTime: zero time, old time (year format), future time, format length consistency integration tests (test/cli/ls_test.go): - explicit full output comparison with deterministic CIDs to catch any formatting changes - header column order verification for --long with --size=true/false - files without preserved metadata (---------- and - placeholders) - directory output (trailing slash, d prefix in mode) requested in: https://github.com/ipfs/kubo/pull/11103#issuecomment-3745043561 * fix(ls): improve --long flag docs and fix minor issues - improved godocs for formatMode and formatModTime functions - fixed permBit signature: char rune → char byte (avoids unnecessary cast) - clarified help text: mode/mtime are optional UnixFS metadata - documented that times are displayed in UTC - fixed flaky time test by using 1 month ago instead of 1 hour - removed hardcoded CID assertion that would break on DAG changes * fix(ls): show "-" for missing mode in --long output display "-" instead of "----------" when mode metadata is not preserved. this avoids ambiguity with Unix mode 0000 and matches how missing mtime is already displayed. follows common Unix tool conventions (ps, netstat) where "-" indicates "not available". --------- Signed-off-by: sneax <paladesh600@gmail.com> Co-authored-by: Marcin Rataj <lidel@lidel.org> | 7 个月前 | |
fix(mfs): stop repo gc from freezing files ops (#11386) * fix(mfs): stop repo gc from freezing files ops Running `ipfs repo gc` alongside `ipfs files` writes could leave MFS permanently hung: GC deleted directory-node blocks a write had written to the blockstore but not yet linked into the persisted MFS root, and the next path lookup blocked forever fetching the missing block while holding the MFS directory lock, so every later files command piled up behind it. MFS mutations now take the pin lock, the same lock `ipfs add` uses, and GC computes the MFS root only after it holds the GC lock. A write's blocks are therefore either fully linked into the root before GC runs, or the write waits for GC to finish, so GC never collects data a live write still needs. - core/commands/files.go: hold the pin lock across write, cp, mkdir, mv, rm, flush, chcid, chmod, and touch - gc/gc.go: take the best-effort MFS root snapshot after acquiring the GC lock, closing the snapshot-before-lock window - core/corerepo/gc.go: pass the root as a callback evaluated under the lock - core/node/core.go: document why MFS keeps its online DAG service so lazy `ipfs files cp /ipfs/<cid>` pointers still resolve - gc/gc_test.go: assert the root snapshot is taken under the GC lock Closes #10842 * fix(mfs): extend gc pin lock to add and fuse The pin lock that stops garbage collection from collecting live MFS blocks now covers every path that mutates MFS, not just `ipfs files`, and every live MFS root is part of the GC live set. - core/commands/add.go: hold the pin lock while `ipfs add --to-files` links the added content into the MFS root - fuse/writable, fuse/mfs: hold the pin lock across FUSE `/mfs` structural writes and file flush, fsync, and release - fuse/ipns: same for the per-key `/ipns` mounts, and register their roots so GC keeps their blocks live - core/core.go: track mounted MFS roots for the GC live set - core/corerepo/gc.go: build the live set from the files root plus every registered root, skipping a root that errors instead of aborting the whole GC Closes #6113 Closes #7008 Closes #9553 * fix(mfs): fail fast on a missing block A directory-node block that is missing locally and unreachable would block an MFS operation forever while it held the directory lock, wedging the whole MFS and a clean shutdown until the process was killed. This is what remained after a repo was damaged by an older Kubo, a manual `ipfs block rm`, or a crash (the lockup in #7844). MFS now bounds those network reads: an unreachable block fails the operation with a timeout and releases the lock, while lazily-referenced content (`ipfs files cp /ipfs/<cid>`) still loads as before. - config: add DefaultMFSFetchTimeout and pass it to the MFS root via mfs.WithFetchTimeout in Import.MFSRootOptions - go.mod: bump boxo to pull in mfs.WithFetchTimeout * feat(mfs): honor --timeout in files read and write Adopt boxo's mfs.File.Open(ctx) so MFS file operations carry a context and a read or write stuck on a missing block can be cancelled instead of blocking forever. - go.mod: bump boxo to pick up mfs.File.Open(ctx) - core/commands/files.go: pass the request context to files read and write, so a client --timeout ends a stuck read or write - fuse/writable: bind long-lived FUSE descriptors (Create, Open) to the mount context via the new Config.MountCtx; the transient Setattr truncate uses the per-operation context - fuse/mfs, fuse/ipns: set MountCtx to the node/mount context - test/cli: cover files read and write honoring --timeout on unreachable content * chore(deps): bump boxo to merged mfs fix Switch from the pre-merge branch pseudo-version to the merged commit of ipfs/boxo#1185, the boxo side of the MFS under-lock work this branch depends on. * refactor(fuse): pass request ctx to pin lock Flush, Release, and Fsync passed context.Background() to the pin lock while their own ctx argument was in scope. Thread the passed ctx through instead, matching the other handlers. boxo's default GCLocker discards the context, so this is a consistency change, not a behavior change. https://github.com/ipfs/kubo/pull/11386#discussion_r3534131824 https://github.com/ipfs/kubo/pull/11386#discussion_r3534138912 https://github.com/ipfs/kubo/pull/11386#discussion_r3534140861 Co-authored-by: Andrew Gillis <11790789+gammazero@users.noreply.github.com> * refactor(gc): const for buffer, simplify roots Name the GC result channel buffer size as a const, drop the temporary in the best-effort root snapshot, and use t.Context() in the snapshot test. The buffer size predates this branch; it only shifted in the diff. https://github.com/ipfs/kubo/pull/11386#discussion_r3534154606 https://github.com/ipfs/kubo/pull/11386#discussion_r3534077507 https://github.com/ipfs/kubo/pull/11386#discussion_r3534085418 https://github.com/ipfs/kubo/pull/11386#discussion_r3534106766 Co-authored-by: Andrew Gillis <11790789+gammazero@users.noreply.github.com> * refactor(add): collapse pin lock defer Fold the pin lock's unlock into the defer at both --to-files call sites, matching the one-line style used elsewhere. https://github.com/ipfs/kubo/pull/11386#discussion_r3534006489 https://github.com/ipfs/kubo/pull/11386#discussion_r3534013057 Co-authored-by: Andrew Gillis <11790789+gammazero@users.noreply.github.com> --------- Co-authored-by: Andrew Gillis <11790789+gammazero@users.noreply.github.com> | 2 个月前 | |
test: port remote pinning tests to Go (#9720) This also means that rb-pinning-service-api is no longer required for running remote pinning tests. This alone saves at least 3 minutes in test runtime in CI because we don't need to checkout the repo, build the Docker image, run it, etc. Instead this implements a simple pinning service in Go that the test runs in-process, with a callback that can be used to control the async behavior of the pinning service (e.g. simulate work happening asynchronously like transitioning from "queued" -> "pinning" -> "pinned"). This also adds an environment variable to Kubo to control the MFS remote pin polling interval, so that we don't have to wait 30 seconds in the test for MFS changes to be repinned. This is purely for tests so I don't think we should document this. This entire test suite runs in around 2.5 sec on my laptop, compared to the existing 3+ minutes in CI. | 3 年前 | |
fix: bound ipns caching and validate lifetimes (#11349) * chore: bump boxo to test ipfs/boxo#1166 Bumps github.com/ipfs/boxo to the tip of fix/ipns-cache-control-expiry (55fd621d1872) to exercise the IPNS cache-control/TTL/EOL fixes from ipfs/boxo#1166. Root, docs/examples, and test/dependencies modules tidied via make mod_tidy. Signed-off-by: Marcin Rataj <lidel@lidel.org> * fix: validate ipns lifetime and ttl settings ipfs name publish now sanitizes its duration flags instead of emitting a record that fails verification later: a non-positive --lifetime and a negative --ttl are rejected, an explicit --ttl over --lifetime is rejected, and an omitted --ttl is capped to --lifetime. The --lifetime and --ttl defaults are applied server-side so an explicit value is distinguishable from the default. The daemon also refuses to start when Ipns.RecordLifetime is shorter than Ipns.RepublishPeriod, which would let records expire before they are republished. Signed-off-by: Marcin Rataj <lidel@lidel.org> * switch to boxo@main with fix #1166 --------- Signed-off-by: Marcin Rataj <lidel@lidel.org> Co-authored-by: gammazero <11790789+gammazero@users.noreply.github.com> | 3 个月前 | |
test: fix flakes that force CI re-runs (#11413) * fix(routing): keep peers found before the timeout The DHT returns the closest peers it reached together with the context error when a lookup runs past its deadline. We dropped both, so any lookup slower than the routing server's per-request timeout came back as HTTP 500 with nothing in it, indistinguishable from a lookup that found no peers at all. Return what we have, and only error when the set is empty. * test: use local dht swarm for routing v1 test GetClosestPeers joined the public Amino DHT with real bootstrap peers, so the assertions depended on a CI runner reaching bootstrap.libp2p.io from a cold repo. When it could not, the test retried for five minutes and failed; ten such failures since v0.42.0, every one green on re-run. Bootstrap from the harness's in-process DHT peers instead, which the provider tests already use and this one predates. The window drops from five minutes to sixty seconds because there is no longer anything slow to wait for, and passing runs go from tens of seconds to under one. * test: stop handing out ports the kernel reuses NewRandPort binds port zero, notes the number, closes the socket and hands the number to the caller, which leaves a window for anything else on the machine to take it. The number also came from the ephemeral range, the same pool every outgoing connection draws from, and the CLI suite opens a lot of those. Both TestP2PForeground tunnel subtests died on "bind: address already in use" for a server the test binds itself. - NewTCPListener hands back the bound listener, closing that window for callers that listen in-process - ports for daemons we spawn now come from below the ephemeral range, so an outgoing connection cannot land on one * test: sync gc tests to the adder, not the clock TestAddGCLive asserted that gc had not started yet, but the only thing it waited for was the first file's output event. Between that event and the adder reaching the next file there is a gap, and the adder hands the pin lock to a waiting gc at exactly that boundary, so on a loaded runner gc really had started and the assertion was right to fail. Wrap the pipe so the test learns when the adder is inside the hanging file, and poll GCRequested instead of sleeping 100ms to know gc is queued. TestAddMultipleGCLive gets the same treatment for its two sleeps: too short there means gc never gets the lock and the test waits out its five second timeout instead. * test: move watched file in atomically os.WriteFile creates the file and fills it in two steps, and ipfswatch adds whatever is on disk when the create event wakes it. Catch it between the two and it adds an empty file, so the CID the test pulls out of the log reads back as nothing. Stage the file outside the watched directory and rename it in, which the watcher sees as one event for a file that is already complete. * test(sharness): poll the daemon request log The test backgrounded "ipfs log tail", slept 100ms and expected the daemon to be listing the request. The daemon only sees it once the client has started up and connected, which on a loaded runner takes longer than that, and then both the active and the inactive assertion fail together because the entry never appears at all. Poll for each state instead. The extra requests that polling makes push the daemon closer to the point where it drops finished entries from the log, so keep them with "diag cmds set-time" first. * test(sharness): drop stale peer count check The connect case opened by re-asserting that the previous case had left zero peers connected. Disconnecting is not permanent: the DHT keeps the other node in its routing table and re-dials it on any refresh, so that count is only true for as long as nothing else runs. What this case is named for, connecting with a bare /p2p/ address, is still covered by the connect itself and the peer count after it. * test(fuse): mount one node at a time Every parallel subtest does identical setup before mounting, so they all reach the mount together and around twenty setuid fusermount helpers open /dev/fuse inside the same instant. One occasionally comes back with a bare exit status 1. Take a lock for the mount call itself, which the subtests only hold for tens of milliseconds. Also report the failure instead of panicking: a panic failed all 37 tests in the package and left daemons behind, and the daemon's stderr, where fusermount says what actually went wrong, was captured and then thrown away. * test: compare cat output byte for byte The payload is 100 random bytes and the comparison ran through Trimmed(), which strips one trailing newline. Roughly one run in 256 ends in 0x0a and loses it. * test: wait for the fast-provide log line The daemon writes the line before it answers the RPC, but the test reads a buffer that a goroutine fills by copying the daemon's stderr, and that copy can still be behind when the command returns. Wait for the line rather than assuming it has landed. * test: allow for ipns republish mid-test A minute after the daemon starts, the republisher re-signs every key and publishes it again, giving the same value a new signature and expiry. The test captured one PUT body and compared it byte for byte with what routing returned, so a run slow enough to straddle that minute compared the first record against the second. Keep every record the mock is sent and require that routing's answer is one of them, which is what the assertion was reaching for. * fix(examples): turn off mdns in library example The example connects its two nodes by address, but left mDNS on, so local discovery could connect them first. A connection opened while a node is still being built is invisible to that node's bitswap, which only learns about connections made after it registers its notifier, and with no routing configured there is nothing to fall back on. The final fetch then waited forever and the test died on its two minute timeout with no clue why. Turning mDNS off makes the explicit dial the only way the two can meet, and keeps the example off the reader's LAN. Alongside that: - connectToPeers returns dial errors instead of logging and continuing into a fetch that cannot succeed - the example's own deadline now fits inside the test budget, so a stall names the step that hung - CommandContext so a hung child does not outlive the test * ci: make helia-interop job resilient Seven failures since v0.42.0 came from this job's setup rather than from any incompatibility. It installs whatever @helia/interop published last, and upstream shipped three packages in a row whose test config does not work from inside node_modules; a GitHub blip took out the rest. - find the compiled specs and pass them to aegir, instead of patching the config upstream ships into node_modules and grepping its text - pin node to a major: setup-node resolves an lts/ alias through a GitHub manifest with no retry and no fallback, and newer node rejects a flag aegir sets unconditionally - retry the registry lookup and fail loudly, since the old one-liner could not fail and left an empty cache key behind - install the exact version the cache key names, and only save the cache once the install is known good - drop the playwright apt packages, unused since this job stopped running browser targets | 1 个月前 | |
feat(cli): accept native ipfs:// and ipns:// URIs (#11375) * feat: accept native ipfs:// and ipns:// URIs Commands that take a content path or CID now also accept native IPFS URIs (ipfs://cid, ipns://name, and the schemeless ipfs:/ipns: forms), so a URI copied from a browser or another tool works as-is. - cmdutils: PathOrCidPath parses via boxo NewPathFromURI; new CidFromArg for raw-CID commands takes the root CID and rejects sub-paths and mutable IPNS. - files: cp/stat sources and getNodeFromPath accept URIs and content paths; chroot takes its CID via CidFromArg. - resolve and name resolve normalize URIs before the namespace checks; name resolve stays IPNS-only. - routing, provide, filestore, pin remote: raw-CID args via CidFromArg. Depends on boxo NewPathFromURI (ipfs/boxo#1182); go.mod pins the PR commit until it is released. * depend on boxo@main * test: fix telemetry opt-out assertions #11374 made telemetry opt-in and rewrote the explicit "off" mode to no longer log "telemetry disabled via opt-out", but the opt-out subtests still assert that string, so TestTelemetry is red on master. Assert the "telemetry collection skipped: opted out" message the daemon emits whenever telemetry is off. * ci: inject .aegir.js for helia interop @helia/interop v11.0.0+ ships without .aegir.js (ipfs/helia#1049), so aegir test finds no specs and the interop job fails. Inject a minimal config pointing at the prebuilt dist specs when it is missing. Helia's own .aegir.js can't be reused as-is: it globs source .ts specs that Node won't run from node_modules. The same omission regressed before (ipfs/helia#1001, fixed by ipfs/helia#1003); see the comment. * ci: force mocha exit after helia interop run The node interop specs leave kubo daemon and libp2p handles open, so mocha prints "N passing" and then hangs until the job timeout instead of exiting. Pass --exit so mocha quits once the run completes. --------- Co-authored-by: Andrew Gillis <11790789+gammazero@users.noreply.github.com> | 2 个月前 | |
refactor: apply go fix modernizers from Go 1.26 (#11190) * chore: apply go fix modernizers from Go 1.26 automated refactoring: interface{} to any, slices.Contains, and other idiomatic updates. * feat(ci): add `go fix` check to Go analysis workflow ensures Go 1.26 modernizers are applied, fails CI if `go fix ./...` produces any changes (similar to existing `go fmt` enforcement) | 6 个月前 | |
fix(rpc/pin): return error if listing an invalid, but known, pin type (#11238) * fix(core/commands/pin): return error if listing an invalid, but known, pin type * test: add cli test for pin ls with known but non-listable type Covers the case where --type=internal passes boxo's StringToMode validation but is rejected by options.Pin.Ls.Type, which previously caused a panic instead of returning an error. --------- Co-authored-by: Marcin Rataj <lidel@lidel.org> | 5 个月前 | |
feat: limit pin names to 255 bytes (#10981) adds validation to ensure pin names don't exceed 255 bytes across all commands that accept pin names. this prevents issues with filesystem limitations and improves compatibility. affected commands: - ipfs pin add --name - ipfs add --pin-name - ipfs pin ls --name (filter) - ipfs pin remote add --name - ipfs pin remote ls --name (filter) - ipfs pin remote rm --name (filter) | 11 个月前 | |
shutdown daemon after test (#11135) | 7 个月前 | |
refactor: apply go fix modernizers from Go 1.26 (#11190) * chore: apply go fix modernizers from Go 1.26 automated refactoring: interface{} to any, slices.Contains, and other idiomatic updates. * feat(ci): add `go fix` check to Go analysis workflow ensures Go 1.26 modernizers are applied, fails CI if `go fix ./...` produces any changes (similar to existing `go fmt` enforcement) | 6 个月前 | |
fix: update go-test module (#11390) - Use new `go-test/random` API - no global seed values - reuse generator where appropriate - Fix tests to match new random data generation - update expected deterministic values - fix t0040-add-and-cat.sh - fix t0043-add-w.sh - fix t0045-ls.sh - fix t0087-repo-robust-gc.sh - fix t0270-filestore.sh - fix t0271-filestore-utils.sh - fix t0272-urlstore.sh - Migrate from `/math/rand' to `/math/rand/v2` - random seeds are now `[32]byte` and not `uint64` - use `StringToSeed` or `Uint64ToSeed` to create random seeds for deterministic output | 1 个月前 | |
feat(provide): add `ipfs provide once` and support Interval=0 mode (#11321) * feat(provide): add ipfs provide once for ad-hoc announcements Adds an experimental subcommand that submits provider records for the given CIDs through the provider system right away, without waiting for the next reprovide cycle. Use -r to walk the DAG and announce every reachable block. Designed against the sweep provider (the default since v0.39): StartProviding queues to the burst-provide workers, which publish records to the DHT efficiently. Works with the legacy provider too, though it queues into the slower serial worker pool. CIDs must already exist in the local blockstore. Re-announcement on the regular schedule is governed by Provide.Strategy and Provide.DHT.Interval; this command does not change either. * refactor(routing): deprecate ipfs routing provide Marks `ipfs routing provide` as deprecated and points users at the new `ipfs provide once`. The command keeps its existing Run, Encoders, and flags so existing scripts continue to work; only the status flag and helptext change. * docs(routing): clarify when ipfs routing reprovide applies Tightens the helptext and the sweep-mode error message so the constraint is obvious: this command only triggers a cycle on the legacy provider, and points users at 'ipfs provide stat --all' for monitoring the default sweep schedule. * docs: tighten provide helptext and update routing-provide references Updates docs/config.md and docs/experimental-features.md to reference 'ipfs provide once' instead of 'ipfs routing provide'. Tightens the helptext for 'ipfs provide clear' and the 'ipfs provide stat' overview: drops headings around short paragraphs, prefers active voice, and notes that the sweep provider is the default. * docs: changelog entry for ipfs provide once * docs: use 'provide system' wording consistently * test(provide): cover --recursive and multi-CID paths for provide once Adds two subtests under runProviderSuite (run for both Legacy and Sweep): - --recursive walks the DAG and announces every chunk of a 2 MiB file added with --pin=false under Provide.Strategy=roots, so the auto- provide path stays out of the way. - multiple CIDs in a single invocation succeed and the text encoder reports 'queued 3 CID(s) for immediate provide'. * feat(provide): stream cids and per-cid output for ipfs provide once Each CID flows through the command independently, so stdin can be piped without buffering and consumers see results as they happen. - Run reads CIDs from argv and then from BodyArgs (stdin scanner) one at a time, calling StartProviding per CID. - With -r, the dag.Walk visit callback emits per visited block; the walk cancels its context on the first announce error to stop fetching. - A typed ProvideOnceEvent (one per queued CID) replaces the prior batch result. JSON output streams {"Queued":"<cid>"} per line. - Text output via PostRun: when stderr is a tty, the running count is redrawn on a single line; otherwise a final count is printed. The text encoder still works for HTTP/RPC consumers (one CID per line). - Adds tests for stdin streaming and --enc=json one-event-per-line. * feat(provide): dedupe across all roots and recursive walks Previously the cid set was scoped per root, so a CID shared by two arguments or by two recursive DAG walks was announced twice. Move the set out to the Run scope so each unique CID is announced exactly once per invocation, regardless of how many times it shows up in argv, stdin, or the DAG walks. For -r, hitting an already-seen CID also stops descent into that subtree, avoiding redundant block fetches when DAGs overlap. * style(provide): rename useTTY to isTTY in PostRun * refactor(provide): align ipfs provide once with kubo cmds-lib idioms - Use the existing argumentIterator helper from cid.go to read argv followed by stdin, replacing the inlined two-loop variant. - Document why PostRun forks on encoder type (TTY redraw needs to bypass the encoder; json/xml must keep streaming through it). - Log an ERROR for unexpected response types instead of dropping them silently, mirroring the defensive pattern in cat.go's PostRun. * docs(routing): document streaming limitations of routing provide Spell out what 'ipfs routing provide' does worse than 'ipfs provide once' so users on the deprecation path know why to switch: input buffering, no per-cid output, no dedup across recursive roots, and the sync dht lookup that defeats sweep batching. * docs(changelog): rewrite ipfs provide once entry around user impact Recasts the highlight to lead with what the user can now do, not what the code does internally. Adds a one-line example showing the streaming stdin path that the previous version did not surface, and replaces "namespace" plumbing language with the actual capabilities (running count, json-per-line, single announcement per shared block under -r). * feat(provide): use boxo BloomTracker for cross-input dedup Swaps the cid.Set used by 'ipfs provide once' for the autoscaling boxo BloomTracker, the same dedup mechanism that powers Provide.Strategy=+unique. Run executes on the daemon, not the cli, so this caps daemon memory under hostile or accidental input: a user piping 100M cids previously would have grown the daemon's set to ~7 gb of resident memory; with the bloom chain it plateaus around 700 mb at the default fp rate, and under 100 mb up to 10m unique cids. The trade-off is a small false-positive rate (~1 in 4.75m, the kubo default) that can cause an occasional cid to be silently skipped. For ad-hoc providing this is acceptable; the regular reprovide cycle will pick up anything matched by Provide.Strategy on the next pass. * docs(changelog): use ipfs refs as the provide once example * style(provide): goimports import order * docs(provide): soften dedup wording, comment re.Emit gate, cover Provide.Enabled=false - Change "exactly once per invocation" to acknowledge the bloom false-positive rate now that the dedup is probabilistic. - Add a comment to the text branch of PostRun warning future readers not to call re.Emit there, since the encoder would race with the TTY counter. - Add a runProviderSuite subtest that exercises Provide.Enabled=false through the new code path (the existing routing-provide test only covers the deprecated alias's Run). * docs(changelog): clarify provide once use case and add second example - Note that provide once is also for fine-tuned control over which CIDs get announced when, alongside the regular reprovide schedule. - Add a second example using ipfs pin ls so users see the pattern for replaying their pinset alongside the dag-walk pattern. * feat(provide): error on ipfs provide once with Provide.DHT.Interval=0 When Provide.DHT.Interval=0, kubo wires NoopProvider via OnlineProviders -> OfflineProviders, so StartProviding silently no-ops and the cid never gets announced. provide once was returning success without any DHT publish: a footgun. Add an explicit precondition check that mirrors the routing reprovide error path. Decoupling the wiring so ad-hoc provide works under Interval=0 is tracked separately. * chore(deps): pin go-libp2p-kad-dht to PR #1246 head Pulls in the WithReprovideInterval(0) burst-only mode from https://github.com/libp2p/go-libp2p-kad-dht/pull/1246 so the kubo side of the Provide.DHT.Interval=0 decoupling can be developed against it. * chore(deps): re-pin go-libp2p-kad-dht to PR #1246 head Updates to the latest commit on the upstream branch (817031b) which also relaxes the dual SweepingProvider's reprovide-interval validator to accept 0, on top of the single-provider relaxation in the previous pseudo-version. * feat(provide): decouple Provide.DHT.Interval=0 from the master kill-switch Provide.Enabled is now the only switch that fully turns off the provide system. Provide.DHT.Interval=0 disables only the periodic reprovide schedule; new CIDs still announce via fast-provide-root and 'ipfs provide once'. - groups.go: drop the Interval=0 factor from isProviderEnabled. The real provider (sweep or legacy) is now wired even when Interval=0. - provider.go: skip the keystore sync goroutine in no-schedule mode. The ticker would panic on a zero interval, and with no schedule the keystore has no reader. - cmdenv/env.go: drop the fast-provide-root short-circuit on Interval=0. Provide.Enabled=false is now the only short-circuit. - commands/provide.go: drop the temporary 'cannot provide: Provide.DHT.Interval is 0' error from 'ipfs provide once'. - test/cli: replace the 'Reprovide.Interval=0 disables announcement of new CID too' test (premise is now false) with one asserting that Interval=0 + Enabled=true keeps announcing. Convert the provide-once + Interval=0 test from error path to success path. Tighten the legacy 'Manual Reprovide trigger' test to focus on the error contract. Requires upstream go-libp2p-kad-dht support for WithReprovideInterval(0) (kept under PR #1246). * feat(config): require explicit Provide.Enabled when Provide.DHT.Interval=0 Provide.DHT.Interval=0 used to disable the entire provide system as a side effect. After the decoupling it disables only the periodic reprovide schedule, while new CIDs still announce via fast-provide-root and 'ipfs provide once'. To prevent silent semantic drift on upgrade, the daemon now refuses to start when Interval is explicitly set to 0 unless Provide.Enabled is also set explicitly: - Provide.Enabled=false fully disables providing (the old behaviour). - Provide.Enabled=true keeps ad-hoc providing while skipping the periodic reprovide schedule. The error message names both options so operators can pick the one that matches their intent without reading the changelog. * docs: explain new Provide.DHT.Interval=0 semantic Updates docs/config.md and the v0.42 changelog: Interval=0 now disables only the periodic reprovide schedule, and the daemon refuses to start without an explicit Provide.Enabled in that configuration. Calls out both upgrade paths (Provide.Enabled=false to fully disable, or =true to keep ad-hoc providing). * chore(deps): re-pin go-libp2p-kad-dht to amended PR #1246 head Picks up the timeOffset/timeBetween zero-guards so SweepingProvider.Stats() no longer panics with reprovideInterval=0. Required for 'ipfs provide stat' to work in no-schedule mode. * test(provide): align test expectations with new no-schedule semantic - core/commands/commands_test.go: register /provide/once in the expected command list. - test/cli/provide_stats_test.go: 'ipfs provide stat' with Provide.DHT.Interval=0 now returns valid stats (with the schedule timing fields zeroed) instead of erroring out. Update the assertion to match. * chore(deps): re-pin go-libp2p-kad-dht to amended PR #1246 head Picks up the scheduleEnabled() consistency cleanup so timeOffset and timeBetween match the rest of the upstream gates. * chore(deps): re-pin go-libp2p-kad-dht to PR #1246 merge on master picks up the three follow-up commits guillaumemichel pushed before merging libp2p/go-libp2p-kad-dht#1246: - refactor: simplify StartProvide() - refactor: minimize change diff - fix: don't remove from keystore on StopProviding() * fix(provide): use ProvideOnce in `ipfs provide once` `ipfs provide once` was calling StartProviding, which in sweep mode persists keys to the keystore and adds them to the periodic reprovide schedule. that contradicts the command's name and help text. switch to ProvideOnce so the command publishes once and leaves the schedule untouched. for the legacy provider StartProviding already wraps ProvideOnce, so legacy behaviour is unchanged. also tighten the help text to state plainly that the schedule is not modified. * fix(provider): keep keystore inert when Provide.DHT.Interval=0 In no-schedule mode the keystore has no reader (no reprovide loop) and no writer (kad-dht's burst path skips Put/Delete). Until now we still opened on-disk leveldb/pebble files for it: wasted disk and noise on upgrade/downgrade. Switch the keystore to an in-memory map in no-schedule mode and make destroyDs a no-op. Also purge any pre-existing keystore directory once at startup so users who toggle from schedule to no-schedule reclaim disk. Replace the literal `reprovideInterval == 0` check at the second call site with the named noScheduleMode flag for consistency. | 3 个月前 | |
test: fix flakes that force CI re-runs (#11413) * fix(routing): keep peers found before the timeout The DHT returns the closest peers it reached together with the context error when a lookup runs past its deadline. We dropped both, so any lookup slower than the routing server's per-request timeout came back as HTTP 500 with nothing in it, indistinguishable from a lookup that found no peers at all. Return what we have, and only error when the set is empty. * test: use local dht swarm for routing v1 test GetClosestPeers joined the public Amino DHT with real bootstrap peers, so the assertions depended on a CI runner reaching bootstrap.libp2p.io from a cold repo. When it could not, the test retried for five minutes and failed; ten such failures since v0.42.0, every one green on re-run. Bootstrap from the harness's in-process DHT peers instead, which the provider tests already use and this one predates. The window drops from five minutes to sixty seconds because there is no longer anything slow to wait for, and passing runs go from tens of seconds to under one. * test: stop handing out ports the kernel reuses NewRandPort binds port zero, notes the number, closes the socket and hands the number to the caller, which leaves a window for anything else on the machine to take it. The number also came from the ephemeral range, the same pool every outgoing connection draws from, and the CLI suite opens a lot of those. Both TestP2PForeground tunnel subtests died on "bind: address already in use" for a server the test binds itself. - NewTCPListener hands back the bound listener, closing that window for callers that listen in-process - ports for daemons we spawn now come from below the ephemeral range, so an outgoing connection cannot land on one * test: sync gc tests to the adder, not the clock TestAddGCLive asserted that gc had not started yet, but the only thing it waited for was the first file's output event. Between that event and the adder reaching the next file there is a gap, and the adder hands the pin lock to a waiting gc at exactly that boundary, so on a loaded runner gc really had started and the assertion was right to fail. Wrap the pipe so the test learns when the adder is inside the hanging file, and poll GCRequested instead of sleeping 100ms to know gc is queued. TestAddMultipleGCLive gets the same treatment for its two sleeps: too short there means gc never gets the lock and the test waits out its five second timeout instead. * test: move watched file in atomically os.WriteFile creates the file and fills it in two steps, and ipfswatch adds whatever is on disk when the create event wakes it. Catch it between the two and it adds an empty file, so the CID the test pulls out of the log reads back as nothing. Stage the file outside the watched directory and rename it in, which the watcher sees as one event for a file that is already complete. * test(sharness): poll the daemon request log The test backgrounded "ipfs log tail", slept 100ms and expected the daemon to be listing the request. The daemon only sees it once the client has started up and connected, which on a loaded runner takes longer than that, and then both the active and the inactive assertion fail together because the entry never appears at all. Poll for each state instead. The extra requests that polling makes push the daemon closer to the point where it drops finished entries from the log, so keep them with "diag cmds set-time" first. * test(sharness): drop stale peer count check The connect case opened by re-asserting that the previous case had left zero peers connected. Disconnecting is not permanent: the DHT keeps the other node in its routing table and re-dials it on any refresh, so that count is only true for as long as nothing else runs. What this case is named for, connecting with a bare /p2p/ address, is still covered by the connect itself and the peer count after it. * test(fuse): mount one node at a time Every parallel subtest does identical setup before mounting, so they all reach the mount together and around twenty setuid fusermount helpers open /dev/fuse inside the same instant. One occasionally comes back with a bare exit status 1. Take a lock for the mount call itself, which the subtests only hold for tens of milliseconds. Also report the failure instead of panicking: a panic failed all 37 tests in the package and left daemons behind, and the daemon's stderr, where fusermount says what actually went wrong, was captured and then thrown away. * test: compare cat output byte for byte The payload is 100 random bytes and the comparison ran through Trimmed(), which strips one trailing newline. Roughly one run in 256 ends in 0x0a and loses it. * test: wait for the fast-provide log line The daemon writes the line before it answers the RPC, but the test reads a buffer that a goroutine fills by copying the daemon's stderr, and that copy can still be behind when the command returns. Wait for the line rather than assuming it has landed. * test: allow for ipns republish mid-test A minute after the daemon starts, the republisher re-signs every key and publishes it again, giving the same value a new signature and expiry. The test captured one PUT body and compared it byte for byte with what routing returned, so a run slow enough to straddle that minute compared the first record against the second. Keep every record the mock is sent and require that routing's answer is one of them, which is what the assertion was reaching for. * fix(examples): turn off mdns in library example The example connects its two nodes by address, but left mDNS on, so local discovery could connect them first. A connection opened while a node is still being built is invisible to that node's bitswap, which only learns about connections made after it registers its notifier, and with no routing configured there is nothing to fall back on. The final fetch then waited forever and the test died on its two minute timeout with no clue why. Turning mDNS off makes the explicit dial the only way the two can meet, and keeps the example off the reader's LAN. Alongside that: - connectToPeers returns dial errors instead of logging and continuing into a fetch that cannot succeed - the example's own deadline now fits inside the test budget, so a stall names the step that hung - CommandContext so a hung child does not outlive the test * ci: make helia-interop job resilient Seven failures since v0.42.0 came from this job's setup rather than from any incompatibility. It installs whatever @helia/interop published last, and upstream shipped three packages in a row whose test config does not work from inside node_modules; a GitHub blip took out the rest. - find the compiled specs and pass them to aegir, instead of patching the config upstream ships into node_modules and grepping its text - pin node to a major: setup-node resolves an lts/ alias through a GitHub manifest with no retry and no fallback, and newer node rejects a flag aegir sets unconditionally - retry the registry lookup and fail loudly, since the old one-liner could not fail and left an empty cache key behind - install the exact version the cache key names, and only save the cache once the install is known good - drop the playwright apt packages, unused since this job stopped running browser targets | 1 个月前 | |
refactor: apply go fix modernizers from Go 1.26 (#11190) * chore: apply go fix modernizers from Go 1.26 automated refactoring: interface{} to any, slices.Contains, and other idiomatic updates. * feat(ci): add `go fix` check to Go analysis workflow ensures Go 1.26 modernizers are applied, fails CI if `go fix ./...` produces any changes (similar to existing `go fmt` enforcement) | 6 个月前 | |
shutdown daemon after test (#11135) | 7 个月前 | |
refactor: apply go fix modernizers from Go 1.26 (#11190) * chore: apply go fix modernizers from Go 1.26 automated refactoring: interface{} to any, slices.Contains, and other idiomatic updates. * feat(ci): add `go fix` check to Go analysis workflow ensures Go 1.26 modernizers are applied, fails CI if `go fix ./...` produces any changes (similar to existing `go fmt` enforcement) | 6 个月前 | |
refactor: apply go fix modernizers from Go 1.26 (#11190) * chore: apply go fix modernizers from Go 1.26 automated refactoring: interface{} to any, slices.Contains, and other idiomatic updates. * feat(ci): add `go fix` check to Go analysis workflow ensures Go 1.26 modernizers are applied, fails CI if `go fix ./...` produces any changes (similar to existing `go fmt` enforcement) | 6 个月前 | |
test: add regression tests for API.Authorizations (#11060) | 9 个月前 | |
feat(rpc): Content-Type headers and IPNS record get/put (#11067) * fix http header when compress enabled for get command Closes #2376 * fix(rpc): set Content-Type for ipfs get based on output format - set application/x-tar when outputting tar (default and --archive) - set application/gzip when compression is enabled (--compress) - update go-ipfs-cmds with Tar encoding type and RFC 6713 compliant MIME types (application/gzip instead of application/x-gzip) * test(rpc): add Content-Type header tests for ipfs get * feat(rpc): add Content-Type headers for binary responses set proper Content-Type headers for RPC endpoints that return binary data: - `dag export`: application/vnd.ipld.car - `block get`: application/vnd.ipld.raw - `diag profile`: application/zip - `get`: application/x-tar or application/gzip (already worked, migrated to new API) uses the new OctetStream encoding type and SetContentType() method from go-ipfs-cmds to specify custom MIME types for binary responses. refs: https://github.com/ipfs/kubo/issues/2376 * feat(rpc): add `ipfs name get` command for IPNS record retrieval add dedicated command to retrieve raw signed IPNS records from the routing system. returns protobuf-encoded IPNS record with Content-Type `application/vnd.ipfs.ipns-record`. this provides a more convenient alternative to `ipfs routing get /ipns/<name>` which returns JSON with base64-encoded data. the raw output can be piped directly to `ipfs name inspect`: ipfs name get <name> | ipfs name inspect spec: https://specs.ipfs.tech/ipns/ipns-record/ * feat(rpc): add `ipfs name put` command for IPNS record storage adds `ipfs name put` to complement `ipfs name get`, allowing users to store IPNS records obtained from external sources without needing the private key. useful for backup, restore, and debugging workflows. the command validates records by default (signature, sequence number). use `--force` to bypass validation for testing how routing handles malformed or outdated records. also reorganizes test/cli files: - rename http_rpc_* -> rpc_* to match existing convention - merge name_get_put_test.go into name_test.go - add file header comments documenting test purposes * chore(deps): update go-ipfs-cmds to latest master includes SetContentType() for dynamic Content-Type headers --------- Co-authored-by: Marcin Rataj <lidel@lidel.org> | 7 个月前 | |
feat(rpc): Content-Type headers and IPNS record get/put (#11067) * fix http header when compress enabled for get command Closes #2376 * fix(rpc): set Content-Type for ipfs get based on output format - set application/x-tar when outputting tar (default and --archive) - set application/gzip when compression is enabled (--compress) - update go-ipfs-cmds with Tar encoding type and RFC 6713 compliant MIME types (application/gzip instead of application/x-gzip) * test(rpc): add Content-Type header tests for ipfs get * feat(rpc): add Content-Type headers for binary responses set proper Content-Type headers for RPC endpoints that return binary data: - `dag export`: application/vnd.ipld.car - `block get`: application/vnd.ipld.raw - `diag profile`: application/zip - `get`: application/x-tar or application/gzip (already worked, migrated to new API) uses the new OctetStream encoding type and SetContentType() method from go-ipfs-cmds to specify custom MIME types for binary responses. refs: https://github.com/ipfs/kubo/issues/2376 * feat(rpc): add `ipfs name get` command for IPNS record retrieval add dedicated command to retrieve raw signed IPNS records from the routing system. returns protobuf-encoded IPNS record with Content-Type `application/vnd.ipfs.ipns-record`. this provides a more convenient alternative to `ipfs routing get /ipns/<name>` which returns JSON with base64-encoded data. the raw output can be piped directly to `ipfs name inspect`: ipfs name get <name> | ipfs name inspect spec: https://specs.ipfs.tech/ipns/ipns-record/ * feat(rpc): add `ipfs name put` command for IPNS record storage adds `ipfs name put` to complement `ipfs name get`, allowing users to store IPNS records obtained from external sources without needing the private key. useful for backup, restore, and debugging workflows. the command validates records by default (signature, sequence number). use `--force` to bypass validation for testing how routing handles malformed or outdated records. also reorganizes test/cli files: - rename http_rpc_* -> rpc_* to match existing convention - merge name_get_put_test.go into name_test.go - add file header comments documenting test purposes * chore(deps): update go-ipfs-cmds to latest master includes SetContentType() for dynamic Content-Type headers --------- Co-authored-by: Marcin Rataj <lidel@lidel.org> | 7 个月前 | |
Cleanup commented imports | 2 年前 | |
feat: bound graceful shutdown, add diag healthy (#11329) * feat: bound graceful shutdown, add diag healthy Replace unbounded app.Stop(context.Background()) with a deadline-bounded context driven by a new Internal.ShutdownTimeout config (default 12h, 0 disables). Add an os.Exit(1) watchdog at the same deadline so an FX OnStop hook that never returns can no longer hang the daemon. Add ipfs diag healthy: fails when shutdown has been initiated or when the DAG pipeline cannot resolve the well-known empty-directory CID. Dockerfile HEALTHCHECK now uses it so orchestrators recycle half- shutdown daemons. - core/shutdown: new pkg; atomic startedAt + CloseWithCtx helper - core/builder.go: app.Stop bounded by ShutdownTimeout - cmd/ipfs/kubo/daemon.go: watchdog + MarkStarted on signal - core/commands/diag.go: new healthy subcommand - core/node/{bitswap,libp2p/host,libp2p/routing}.go: OnStop hooks wrapped - config/internal.go: ShutdownTimeout + DefaultShutdownTimeout=12h - Dockerfile: HEALTHCHECK uses "ipfs diag healthy" - docs/{config,changelogs/v0.42}.md: documented - test/cli: enabled + disabled path tests * feat: bound provider stats and ADD_PROVIDER sends bumps go-libp2p-kad-dht past v0.39.2 to b73e1e8 to pick up two related provider bug fixes. - ipfs provide stat now honors client cancellation and deadlines instead of blocking indefinitely behind a slow keystore lookup - adds Provide.DHT.SendProviderRecordTimeout capping each ADD_PROVIDER RPC so unresponsive peers cannot pin a provide worker and stall reprovide cycles - internal reprovide-alert poller bounds its Stats call so a hung keystore.Size cannot delay shutdown * test(shutdown): use synctest for timeout test, document sleep CloseWithCtx_timesOut now runs in a synctest bubble so the deadline assertion is exact (no wall-clock slack), and the simulated close uses a release channel to drain the bubble cleanly after the leak point. The two happy-path tests stay unchanged because their close funcs return immediately and gain nothing from a fake clock. Comment the 2ms sleep in TestMarkStartedPreservesFirstTimestamp so its role (forcing time.Now() to advance between the two MarkStarted calls so a CAS to Store regression is detectable) is not lost. Addresses ipfs/kubo#11329 (review). * fix(pinner): bound pinner Close with shutdown deadline The boxo Pinner.Close contract notes that an in-flight op ignoring its ctx (a downstream bug) can block Close, so the host must bound it at the call site. Wrapping the OnStop hook with CloseWithCtx honors Internal.ShutdownTimeout and surfaces an actionable "subsystem 'pinner' failed to close" log on hang instead of leaving only the watchdog os.Exit(1) trace. * fix(shutdown): bound remaining I/O-touching OnStop hooks Wrap the OnStop hooks whose Close can plausibly block on disk or network: repo (datastore flush + lock release), mfs-root (datastore writes via DAGService), peering (waits on libp2p peer goroutines), legacy-provider (in-flight reprovide RPCs), and the dht-provider plus keystore pair under SweepingProvider. In-memory closes (blockservice, peerstore, resource-manager) are left as-is since they cannot realistically hang. For the dht-provider/keystore pair, provider closes first so nothing can access the keystore afterwards. If the shutdown ctx fires mid-provider-drain, the keystore close sees an expired ctx and returns immediately; the watchdog os.Exit(1) is the ultimate backstop, and keystore writes are fsync'd on put so missing the explicit close is recoverable on next boot. * fix(shutdown): bound remaining in-memory OnStop hooks Wrap blockservice, peerstore, and resource-manager Close hooks with CloseWithCtx for uniformity. These are pure in-memory operations unlikely to hang in practice, but wrapping costs nothing and makes the shutdown audit trail uniform: every OnStop hook now honors the deadline and surfaces a named subsystem on timeout. * fix(shutdown): bound autoRelayFeeder OnStop on ctx OnStop waited on the feeder goroutine via <-done without honoring the shutdown ctx. The goroutine itself selects on ctx in every loop case, so cancel() normally suffices, but a stuck downstream dht.WAN.GetClosestPeers that ignored its ctx could block fx.Stop indefinitely. Adding the ctx.Done() select case mirrors the reprovideAlert pattern in provider.go and lets the shutdown deadline reclaim control even with a misbehaving DHT. * docs(changelog): merge shutdown entries into one user-facing section Combine the pinner-on-shutdown paragraph with the bounded-shutdown section under a single "Reliable shutdown and container health checks" heading. Lead with the visible symptoms (half-shutdown daemons, healthy-but-dead container reports, manual docker restart) instead of fx OnStop jargon. Frame Internal.ShutdownTimeout as a belt-and-suspenders ceiling, with the 12-hour default sized against the 22-hour DHT provider record expiration. | 3 个月前 | |
shutdown daemon after test (#11135) | 7 个月前 | |
feat: `swarm addrs autonat` command (#11184) * feat: add swarm addrs autonat command fixes #11171 by adding a self service way to debug public reachability with autonat * test: add test for ipfs swarm addr autonat command * docs: add ipfs swarm addrs autonat to changelog * test: update failing test * fix: swarm addrs autonat bugfixes and cleanup - fix help text to show capitalized reachability values (Public, Private, Unknown) matching actual output from network.Reachability.String() - default Reachability to "Unknown" instead of empty string when the host interface assertion fails - extract multiaddrsToStrings and writeAddrSection helpers to deduplicate repeated conversion loops and text formatting blocks --------- Co-authored-by: Marcin Rataj <lidel@lidel.org> | 6 个月前 | |
chore: restore default telemetry for now (#11415) Telemetry reports to https://telemetry.ipshipyard.dev by default again, as it did through v0.42. This is a stopgap: it holds while the devgrant support window is active. Every way to turn telemetry off now lives in one place, so ending it later is a config change or a one-line diff rather than a rewrite. - endpoint is a linker-settable var: building with -ldflags "-X ...telemetry.defaultEndpoint=" yields a binary with no destination, which collects nothing and writes no identifier - DO_NOT_TRACK is honored, ranking between IPFS_TELEMETRY and the config Mode, so one variable opts a machine out of every tool - a collector answering 410 Gone retires itself: the node drops its identifier and never sends there again, on this run or a later one, which stops reporting across deployed nodes without a release - first-run notice names DO_NOT_TRACK next to the Kubo switches - docs/telemetry.md leads with how to disable, including at build time - AGENTS.md: telemetry opt-outs are a rule, not a courtesy - changelog: drop the opt-in highlight, v0.43 ships no telemetry change | 1 个月前 | |
shutdown daemon after test (#11135) | 7 个月前 | |
shutdown daemon after test (#11135) | 7 个月前 | |
fix(test): mock GitHub API in TestUpdate (#11300) These tests verify behavior that is independent of who serves the release JSON: TestUpdate exercises the `ipfs update` command tree, and TestUpdateWhileDaemonRuns checks that read-only subcommands still work while the daemon holds the repo lock. They hit the real GitHub Releases API only by accident, which makes them flake on rate limits, transient 5xx, or release-asset upload races. A flake panics the harness and takes every parallel test in test/cli down with it. Replace the network call with a shared `httptest.Server` helper (`newMockGitHubReleases`) and point the spawned binary at it via `TEST_KUBO_UPDATE_GITHUB_URL`, the same hook `TestUpdateInstall` already uses. The mock returns one stable release with a matching binary asset and follows the convention used by real kubo releases: `kubo_<tag>_<os>-<arch>.<ext>`, where ext is `zip` on Windows and `tar.gz` elsewhere. This must match `assetNameForPlatformTag` in `core/commands/update_github.go`, otherwise `findReleaseAsset` reports "no release found with a binary for <os>/<arch>". No network, no token, no flake. Local runtime drops from ~70s to under 1s. | 4 个月前 | |
feat: ipfs-webui v4.9.0 with retrieval diagnostics (#10969) * fix(webui): show helpful errors for incompatible configurations - show error when Gateway.NoFetch=true and WebUI is not available locally - show error when Gateway.DeserializedResponses=false (incompatible) - add tests for both error scenarios * chore(webui): update to v4.9.0 https://github.com/ipfs/ipfs-webui/releases/tag/v4.9.0 * docs: add WebUI v4.9.0 update to v0.38 changelog - highlight new diagnostics screen for troubleshooting - include screenshots of key features in table format - add local access URL for WebUI - update TOC with new sections | 11 个月前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 1 个月前 | ||
| 5 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 4 个月前 | ||
| 2 个月前 | ||
| 1 个月前 | ||
| 6 个月前 | ||
| 11 个月前 | ||
| 6 个月前 | ||
| 1 个月前 | ||
| 7 个月前 | ||
| 6 个月前 | ||
| 6 个月前 | ||
| 6 个月前 | ||
| 1 年前 | ||
| 4 个月前 | ||
| 7 个月前 | ||
| 5 个月前 | ||
| 1 年前 | ||
| 1 年前 | ||
| 28 天前 | ||
| 2 个月前 | ||
| 6 个月前 | ||
| 1 年前 | ||
| 1 年前 | ||
| 7 个月前 | ||
| 3 个月前 | ||
| 1 个月前 | ||
| 7 个月前 | ||
| 1 个月前 | ||
| 6 个月前 | ||
| 7 个月前 | ||
| 5 个月前 | ||
| 7 个月前 | ||
| 5 个月前 | ||
| 7 个月前 | ||
| 7 个月前 | ||
| 15 天前 | ||
| 2 个月前 | ||
| 7 个月前 | ||
| 1 个月前 | ||
| 11 个月前 | ||
| 4 个月前 | ||
| 1 个月前 | ||
| 27 天前 | ||
| 6 个月前 | ||
| 1 个月前 | ||
| 7 个月前 | ||
| 2 个月前 | ||
| 3 年前 | ||
| 3 个月前 | ||
| 1 个月前 | ||
| 2 个月前 | ||
| 6 个月前 | ||
| 5 个月前 | ||
| 11 个月前 | ||
| 7 个月前 | ||
| 6 个月前 | ||
| 1 个月前 | ||
| 3 个月前 | ||
| 1 个月前 | ||
| 6 个月前 | ||
| 7 个月前 | ||
| 6 个月前 | ||
| 6 个月前 | ||
| 9 个月前 | ||
| 7 个月前 | ||
| 7 个月前 | ||
| 2 年前 | ||
| 3 个月前 | ||
| 7 个月前 | ||
| 6 个月前 | ||
| 1 个月前 | ||
| 7 个月前 | ||
| 7 个月前 | ||
| 4 个月前 | ||
| 11 个月前 |