Skip to content

docs: auto-update for PR #2970 — fix(sync): bound inbound blob stream and discard on hash mismatch#2987

Draft
meroreviewer[bot] wants to merge 2 commits into
masterfrom
docs/auto-pr2970-b70e276
Draft

docs: auto-update for PR #2970 — fix(sync): bound inbound blob stream and discard on hash mismatch#2987
meroreviewer[bot] wants to merge 2 commits into
masterfrom
docs/auto-pr2970-b70e276

Conversation

@meroreviewer

@meroreviewer meroreviewer Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Automatic Documentation Update

Opened automatically after PR #2970 merged.

Each block shows the documentation change as a diff (added lines in green, removed in red); expand "Why this changed" for the source rationale.

Documentation changes

architecture/crates/node.html — Add MAX_BLOB_STREAM_SIZE_BYTES constant (500 MiB); Always pass a size limit to add_blob, capping unknown-size streams; Delete persisted blob on hash mismatch to avoid storing corrupt data

 Full snapshot transfer — heaviest fallback protocol
 sync/blobs.rs
-Blob sharing protocol
+Blob sharing protocol. Inbound blobs are always bounded by
+MAX_BLOB_STREAM_SIZE_BYTES (500 MiB): when the peer advertises a non-zero size
+the limit is min(advertised, MAX_BLOB_STREAM_SIZE_BYTES); when the peer
+advertises size 0 (unknown) the limit is MAX_BLOB_STREAM_SIZE_BYTES itself.
+Some(size_limit) is always passed to add_blob — no inbound blob stream is ever
+accepted without an upper bound. After the full receive, if the computed blob-id
+does not match the advertised blob-id, delete_blob is called to remove the
+corrupt entry before returning an error; a warning log is emitted containing the
+expected id, the received id, and the advertised size, with a secondary warning
+if the delete itself fails.
 sync/helpers.rs
 Sync helper utilities; includes local_scope_root — looks up the group owning a …

 What the node crate depends on and what depends on it.
 calimero-node depends on
+Sync blob size cap — MAX_BLOB_STREAM_SIZE_BYTES
+A constant MAX_BLOB_STREAM_SIZE_BYTES (500 MiB, typed u64) defined in
+constants.rs acts as a hard ceiling on every blob received over the sync wire
+protocol. Regardless of what the peer advertises,
+SyncManager::initiate_blob_share_process computes a size_limit and always passes
+Some(size_limit) to add_blob. If the received blob's hash does not match the
+advertised blob-id, delete_blob is called immediately to remove the corrupt
+entry, and an error (with warning log) is returned. No blob stream is ever
+accepted without an upper bound.
 calimero-context
 ContextManager actor — started by node during bootstrap
Why this changed (source: PR #2970)

A new u64 constant MAX_BLOB_STREAM_SIZE_BYTES (500 MiB) is introduced in constants.rs to serve as a hard ceiling on any single blob received over the sync wire protocol. It is typed u64 to match the wire-protocol size: u64 field and avoid truncation on 32-bit targets.

Previously, when a peer advertised size==0 (meaning 'unknown'), expected_size was set to None and passed to add_blob, leaving the receive loop with no upper bound on accepted data. Now a size_limit is computed unconditionally: the advertised size capped at MAX_BLOB_STREAM_SIZE_BYTES when size>0, or MAX_BLOB_STREAM_SIZE_BYTES itself when size==0. Some(size_limit) is always passed to add_blob.

After a full blob receive, if the computed blob-id does not match the advertised blob-id, the code now calls delete_blob on the incorrectly-hashed blob before returning an error. A warning log is emitted that includes the expected id, the received id, and the advertised size. A secondary warning is logged if the delete itself fails.

architecture/crates/sync.html — Add MAX_BLOB_STREAM_SIZE_BYTES constant (500 MiB); Always pass a size limit to add_blob, capping unknown-size streams; Delete persisted blob on hash mismatch to avoid storing corrupt data

 Transport
 The sync transport layer wraps libp2p streams with framing, encryption, and aut…
+Blob Receive Size Cap — MAX_BLOB_STREAM_SIZE_BYTES (500 MiB)
+A new constant MAX_BLOB_STREAM_SIZE_BYTES (500 MiB, typed u64 to match the wire-
+protocol size: u64 field and avoid truncation on 32-bit targets) is defined in
+constants.rs and enforced in SyncManager::initiate_blob_share_process as a hard
+ceiling on any single blob received over the sync wire protocol.
+Previously, when a peer advertised size == 0 (meaning "unknown"), expected_size
+was set to None and passed to add_blob, leaving the receive loop with no upper
+bound on accepted data. Now a size_limit is computed unconditionally:
+When size > 0 — the advertised size capped at MAX_BLOB_STREAM_SIZE_BYTES.
+When size == 0 — MAX_BLOB_STREAM_SIZE_BYTES itself.
+Some(size_limit) is always passed to add_blob; a None limit is never used.
+After a full blob receive, if the computed blob-id does not match the advertised
+blob-id, delete_blob is called on the incorrectly-hashed blob before the error
+is returned, preventing corrupt data from being persisted. A WARN log is emitted
+including the expected id, the received id, and the advertised size. A secondary
+warning is logged if the delete_blob call itself fails.
+// constants.rs — hard ceiling for any single inbound sync blob
+pub const MAX_BLOB_STREAM_SIZE_BYTES: u64 = 500 * 1024 * 1024; // 500 MiB
+// size_limit is always Some — unknown-size (size==0) uses the constant
+let size_limit = if size > 0 {
+size.min(MAX_BLOB_STREAM_SIZE_BYTES)
+} else {
+MAX_BLOB_STREAM_SIZE_BYTES
+};
+// add_blob is always called with Some(size_limit)
+let received_id = store.add_blob(stream, Some(size_limit)).await?;
+// Hash mismatch — delete corrupt blob before returning error
+if received_id != advertised_blob_id {
+warn!(expected = %advertised_blob_id, received = %received_id, size, /*...*/);
+if let Err(e) = store.delete_blob(&received_id).await {
+warn!("failed to delete corrupt blob: {e}");
+}
+return Err(...)
+}
+Operators: Every inbound sync blob is now capped at 500 MiB regardless of what
+the peer advertises, including peers that report an unknown size. Blobs whose
+computed hash does not match the advertised id are deleted from the store
+immediately and never left in a corrupt state. No configuration knob exposes
Why this changed (source: PR #2970)

A new u64 constant MAX_BLOB_STREAM_SIZE_BYTES (500 MiB) is introduced in constants.rs to serve as a hard ceiling on any single blob received over the sync wire protocol. It is typed u64 to match the wire-protocol size: u64 field and avoid truncation on 32-bit targets.

Previously, when a peer advertised size==0 (meaning 'unknown'), expected_size was set to None and passed to add_blob, leaving the receive loop with no upper bound on accepted data. Now a size_limit is computed unconditionally: the advertised size capped at MAX_BLOB_STREAM_SIZE_BYTES when size>0, or MAX_BLOB_STREAM_SIZE_BYTES itself when size==0. Some(size_limit) is always passed to add_blob.

After a full blob receive, if the computed blob-id does not match the advertised blob-id, the code now calls delete_blob on the incorrectly-hashed blob before returning an error. A warning log is emitted that includes the expected id, the received id, and the advertised size. A secondary warning is logged if the delete itself fails.


Generated by ai-reviewer update-docs. Nothing was auto-merged.

@meroreviewer meroreviewer Bot added automated-docs documentation Improvements or additions to documentation labels Jun 27, 2026

@meroreviewer meroreviewer Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI Code Reviewer

Reviewed by 1 agents | Quality score: 85% | Review time: 28.8s


✅ No Issues Found

All agents reviewed the code and found no issues. LGTM! 🎉


🤖 Generated by AI Code Reviewer | Review ID: review-a40847b6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automated-docs documentation Improvements or additions to documentation external

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant