fix(manifest): infer refBytesSize at marshal time when never set#5484
Open
mfw78 wants to merge 1 commit into
Open
fix(manifest): infer refBytesSize at marshal time when never set#5484mfw78 wants to merge 1 commit into
mfw78 wants to merge 1 commit into
Conversation
`Add()` defers setting `n.refBytesSize` until the first non-empty entry is
added. When the only adds against a node use an empty entry (e.g. the
bzz endpoint's `m.Add(ctx, manifest.RootPath, manifest.NewEntry(swarm.ZeroAddress, rootMetadata))`
at `pkg/api/bzz.go:266`), the field stays at zero. If such a node is then
populated with non-empty children, `MarshalBinary` writes a header with
`refBytesSize = 0` while the fork bodies still carry full-width refs, and
the v0.2 `UnmarshalBinary` early-return at the (previous) `marshal.go:285`
silently drops every fork. The mantaray-js reference impl documents this
with an explicit FIXME ("in Bee, if one uploads a file on the bzz endpoint,
the node under `/` gets 0 refsize"); downstream Rust consumers (nectar,
isheika) hit it in the wild and have to add bee-tolerance paths in their
decoders.
Infer the correct width at the top of `MarshalBinary`: use the node's own
entry width if present, else the first child ref's width. The early-return
guard in `UnmarshalBinary` is left in place as backward-compat for any
already-persisted manifests that pre-date this fix.
Adds `TestPersistDirectoryOnlyAdds` exercising the directory-only-adds
path; without the inference, the test fails with `entry on 'foo': not found`
after save+reload (silent fork loss).
8 tasks
mfw78
added a commit
to nxm-rs/nectar
that referenced
this pull request
Jun 1, 2026
## What does this PR do? Tolerates bee's `ref_size = 0` mantaray wire form on decode so nectar can read real-world bee-produced manifests. ## Changes - Add `decode_empty_terminal_node` to handle `ref_size = 0`; invoked from both `decode_v01` and `decode_v02`. Accepts the shape only when the forks bitfield is empty; rejects `ref_size = 0` with non-empty forks as malformed. - Tag every tolerance site with grep-able `BEE-WORKAROUND(bee#5483)`. Documents the convention in `crates/mantaray/src/lib.rs` so future maintainers can enumerate sites with `git grep -n BEE-WORKAROUND` once the upstream bee fix has propagated. - Four new regression tests: empty terminal node decode for v0.1 and v0.2; rejection of `ref_size = 0` plus non-empty forks; an encoder pin asserting nectar never emits `ref_size = 0`. ## Breaking changes None. The encoder is unchanged; the decoder strictly broadens what it accepts. ## Testing - [x] Unit tests pass (56/56 in `nectar-mantaray --lib`, 4 of them new) - [x] Integration and doctests pass - [x] Behaviour cross-verified against the bee root-cause fix at ethersphere/bee#5484 ## Related issues - Fixes #36 - Upstream root cause: ethersphere/bee#5483 (fix in ethersphere/bee#5484) ## AI assistance disclosure AI Assistance: Claude Code used for the architectural review (parallel agents reading bee Go, nectar Rust, and the spec / mantaray-js reference), drafting the patch, writing tests, and authoring this PR description. ## Notes for reviewers - The uniform-ref-width rule (`ref_size` governs both entry slot and every fork ref slot) is what the bee spec doc (`bee/pkg/manifest/mantaray/docs/format/node.md`) and every reference impl (bee, mantaray-js, nectar) say; the HAZMAT block above `decode_empty_terminal_node` captures the context. - Decode tolerance is bounded: only the empty-forks-bitfield case. Anything else with `ref_size = 0` errors out rather than silently dropping forks like bee's v0.2 reader does. ## Checklist - [x] Code follows project style - [x] Self-review completed - [x] Tests added (4 new regression tests) - [x] No debug code left behind - [x] PR title is descriptive
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.
Fixes #5483.
Add()defers settingn.refBytesSizeuntil the first non-empty entry is added. Bee callsAddwith an empty entry atpkg/api/bzz.go:266for root metadata; if that node accumulates forks,MarshalBinarywritesrefBytesSize = 0while the fork bodies still carry full-width refs, and the v0.2 reader atmarshal.go:280silently drops them on reload.This patch infers
refBytesSizeat the top ofMarshalBinary— from the node's own entry width if present, else the first child fork's saved ref width. The existing v0.2 read-side guard is left in place as backward-compat for already-persisted manifests.TestPersistDirectoryOnlyAddscovers the directory-only-adds path; it fails on master withentry on 'foo' ('666f6f'): not found(silent fork loss) and passes here.Checklist
make buildcleango test ./pkg/manifest/...passesgolangci-lint run ./pkg/manifest/mantaray/...cleangofumptclean on touched linesAI Disclosure