fix: IPFS peering never persists, and bitswap hangs even when peered - #363
Open
EnriqueL8 wants to merge 2 commits into
Open
fix: IPFS peering never persists, and bitswap hangs even when peered#363EnriqueL8 wants to merge 2 commits into
EnriqueL8 wants to merge 2 commits into
Conversation
Two separate bugs were still causing shared storage downloads to hang/time out intermittently even after the earlier peering fix (#359): 1. swarm/peering/add returns success but never actually writes to the on-disk Peering.Peers config - verified directly by checking the config immediately after calling it. It only registers the peer with the running daemon's in-memory peering service for that session. Since first-time setup restarts the IPFS containers partway through (to apply finalized config), any peering set up before that restart was silently lost, leaving nodes to fall back on unreliable mDNS. Switched to POST /api/v0/config to persist Peering.Peers for real; verified it survives a full container restart with both nodes reconnecting automatically. 2. Even once genuinely peered, content fetches still hang: this is a long-standing upstream Kubo/bitswap bug (ipfs/kubo#8346, open since 2021) where in a small private network, bitswap discovers a provider via the DHT but never sends it a WANT message if the swarm connection to that peer already existed - reproduced directly (bitswap stat showed 0 partners despite an active, bitswap-protocol-negotiated swarm connection). Routing.Type is now set to "none" instead of "dht": with no DHT to depend on, bitswap has no choice but to broadcast wants directly to its connected peers, which is all a small private swarm needs anyway. Verified 5/5 sequential cross-node fetches plus the HTTP gateway path all succeed reliably with this change. Signed-off-by: Enrique Lacal <enrique.lacal@kaleido.io>
Makes it possible to confirm from a run's own log output whether peering happened, instead of having to dig into container-level config/bitswap state after the fact - which is how the persistence bug in this PR was found in the first place. Signed-off-by: Enrique Lacal <enrique.lacal@kaleido.io>
awrichar
approved these changes
Jul 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Background
#359 fixed the initial "IPFS nodes never peer" bug (private-network connection bug in
go-ipfs:v0.10.0, mDNS unreliable on Linux Docker bridge networks in CI) by bumping toipfs/kubo:v0.42.0and adding an explicit peering step (swarm/peering/add+swarm/connect) after startup.It's still failing intermittently in CI and in the
fireflyCore E2E suite (see hyperledger-firefly/firefly#1766 run failures onv1.5.0-rc.3) with the same symptom:Waiting for 2 orgs to appeartiming out after 10 minutes, IPFS shared storage downloads failing withcontext deadline exceeded.Root causes (two separate bugs)
1.
swarm/peering/addreturns success but never persists anything.Verified directly: called the endpoint, got
{"Status":"success"}, then immediately checkedipfs config Peering.Peerson the same node - it wasnull. The endpoint only registers the peer with the running daemon's in-memory peering service for that process's lifetime. It does not write to the on-disk config the wayipfs config(the CLI command) does.This matters because
runFirstTimeSetupdoes a fulldocker compose stop+ restart partway through, to apply finalized FireFly config. Since the peering relationship was never actually saved anywhere, that restart silently wipes it. From then on the nodes are back to relying on mDNS, which is unreliable in CI - so every run was a coin flip depending on whether FireFly's first broadcast happened to land before that restart.Fix:
POST /api/v0/config?arg=Peering.Peers&arg=<json>instead - the same endpoint theipfs configCLI command uses under the hood. Verified this persists to disk and survives a full container restart, with both nodes reconnecting automatically within ~30s.2. Even genuinely peered, content fetches can still hang.
This is a long-standing upstream Kubo/bitswap bug: ipfs/kubo#8346, filed 2021 against
go-ipfs 0.9.1, still open and unaddressed (labeledneed/analysis, no maintainer activity since 2021). In a small private network, bitswap finds a provider via the DHT but never sends it aWANTmessage if the swarm connection to that peer already existed - so it looks connected,ipfs routing findprovscorrectly identifies the provider, butipfs cat/the gateway just hangs.Reproduced directly: with
Routing.Type: dht,ipfs bitswap statshowedpartners [0]on both nodes despiteipfs swarm peersshowing an active, bitswap-protocol-negotiated connection - even right after a fresh, verified-persisted peering + restart.Fix: set
Routing.Type: noneinstead ofdht. With no DHT to depend on, bitswap has no choice but to broadcast wants directly to its connected peers, which is all a small private swarm actually needs - there's no "crowd" to search when you already know and are directly connected to the only other member. Verified 5/5 sequential cross-nodeipfs catcalls plus the HTTP gateway path all succeed reliably with this change, versus 0/many succeeding withdht.Test plan
Peering.Peerspersists and survives a full manual container restart, verified viaipfs config Peering.Peersbefore/afteripfs catcalls succeed withRouting.Type: none(0/many succeeded withdht, reproduced repeatedly)go build ./...passes