Context
- Bee version: v2.7.2-rc1
- Network: mainnet / testnet
- Relevant flags:
--full-node
Summary
When calling PUT /stewardship/{reference} with a non-zero Swarm-Redundancy-Level header, the stewardship service traverses and re-uploads all BMT trie chunks (data shards + RS parity shards) but silently skips re-creating the dispersed replicas for the root chunk. Dispersed replicas are SOC-wrapped copies of the root chunk spread across different Kademlia neighborhoods to provide resilience when the root chunk's own neighborhood degrades. After a reupload, these replicas remain absent or expired, leaving the content more vulnerable to retrieval failure than the requested redundancy level implies.
Expected behavior
A PUT /stewardship/{reference} call with Swarm-Redundancy-Level: N (where N > 0) should:
- Re-stamp and re-push all BMT trie chunks (data + RS parity) — already done.
- Re-create and push the
2^N dispersed replica SOC chunks for the root chunk to their target neighborhoods, consistent with what replicas.NewPutter does at original upload time.
This ensures the full redundancy guarantee for the given level is restored, not just the erasure-coded intermediate structure.
Actual behavior
Only the BMT trie chunks are re-uploaded. The dispersed replicas are not re-created.
Inspecting the implementation in pkg/steward/steward.go:
if err := s.traverser.Traverse(ctx, root, fn, rLevel); err != nil { ... }
return uploaderSession.Done(root)
traversal.Traverse → joiner.IterateChunkAddresses only walks the BMT trie. Dispersed replicas are SOC chunks outside the trie, created by replicas.NewPutter, and are never visited nor re-uploaded.
Calling the API:
curl -X PUT http://localhost:1633/stewardship/<reference> \
-H "Swarm-Postage-Batch-Id: <batch-id>" \
-H "Swarm-Redundancy-Level: 4"
Returns 200 OK with no error, but the dispersed replicas for the root chunk are not re-pushed to the network.
Steps to reproduce
- Upload a file with redundancy enabled:
curl -X POST http://localhost:1633/bzz \
-H "Swarm-Postage-Batch-Id: <batch-id>" \
-H "Swarm-Redundancy-Level: 4" \
-H "Content-Type: application/octet-stream" \
--data-binary @file.bin
# note the returned <reference>
- Wait for dispersed replica stamps to expire, or simulate their loss.
- Call reupload:
curl -X PUT http://localhost:1633/stewardship/<reference> \
-H "Swarm-Postage-Batch-Id: <new-batch-id>" \
-H "Swarm-Redundancy-Level: 4"
- Verify no dispersed replicas (SOC chunks with well-known owner
swarm.ReplicasOwner) have been pushed to the network by checking pushsync logs at level=trace.
Possible solution
After the traversal completes successfully, fetch the root chunk from local storage (already cached from traversal) and pass it through replicas.NewPutter with the requested rLevel:
The root chunk is already in local storage at this point (fetched during traversal), so no extra network retrieval is required.
AI Disclosure
Context
--full-nodeSummary
When calling
PUT /stewardship/{reference}with a non-zeroSwarm-Redundancy-Levelheader, the stewardship service traverses and re-uploads all BMT trie chunks (data shards + RS parity shards) but silently skips re-creating the dispersed replicas for the root chunk. Dispersed replicas are SOC-wrapped copies of the root chunk spread across different Kademlia neighborhoods to provide resilience when the root chunk's own neighborhood degrades. After a reupload, these replicas remain absent or expired, leaving the content more vulnerable to retrieval failure than the requested redundancy level implies.Expected behavior
A
PUT /stewardship/{reference}call withSwarm-Redundancy-Level: N(where N > 0) should:2^Ndispersed replica SOC chunks for the root chunk to their target neighborhoods, consistent with whatreplicas.NewPutterdoes at original upload time.This ensures the full redundancy guarantee for the given level is restored, not just the erasure-coded intermediate structure.
Actual behavior
Only the BMT trie chunks are re-uploaded. The dispersed replicas are not re-created.
Inspecting the implementation in
pkg/steward/steward.go:traversal.Traverse→joiner.IterateChunkAddressesonly walks the BMT trie. Dispersed replicas are SOC chunks outside the trie, created byreplicas.NewPutter, and are never visited nor re-uploaded.Calling the API:
Returns
200 OKwith no error, but the dispersed replicas for the root chunk are not re-pushed to the network.Steps to reproduce
swarm.ReplicasOwner) have been pushed to the network by checking pushsync logs atlevel=trace.Possible solution
After the traversal completes successfully, fetch the root chunk from local storage (already cached from traversal) and pass it through
replicas.NewPutterwith the requestedrLevel:The root chunk is already in local storage at this point (fetched during traversal), so no extra network retrieval is required.
AI Disclosure