Skip to content

Conversation

@zhangchiqing
Copy link
Member

@zhangchiqing zhangchiqing commented Dec 4, 2025

Add an experimental bitswap-bloom-cache-enabled flag (default: true) that controls whether the Bitswap bloom cache is used for Access/Execution/Observer nodes. When disabled, the blob service uses a new WithSkipBloomCache option to skip the cached blockstore and instead use a plain Pebble-backed blockstore, avoiding the CPU cost of building bloom filters at startup while still relying on Pebble’s SSTable bloom filters.

Summary by CodeRabbit

  • New Features

    • Added configurable Bloom filter caching for the blob service, controlled via the new --bitswap-bloom-cache-enabled command-line flag. This optimization improves performance for data retrieval and caching operations and is enabled by default.
  • Chores

    • Improved debug logging for execution data synchronization operations.

✏️ Tip: You can customize this high-level summary in your review settings.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 4, 2025

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@codecov-commenter
Copy link

codecov-commenter commented Dec 4, 2025

Codecov Report

❌ Patch coverage is 25.00000% with 21 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
network/p2p/blob/blob_service.go 0.00% 14 Missing ⚠️
cmd/scaffold.go 0.00% 4 Missing ⚠️
cmd/access/node_builder/access_node_builder.go 0.00% 1 Missing ⚠️
cmd/execution_builder.go 0.00% 1 Missing ⚠️
cmd/observer/node_builder/observer_builder.go 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@zhangchiqing zhangchiqing marked this pull request as ready for review December 8, 2025 23:32
@zhangchiqing zhangchiqing requested a review from a team as a code owner December 8, 2025 23:32
ComplianceConfig: compliance.DefaultConfig(),
DhtSystemEnabled: true,
BitswapReprovideEnabled: true,
BitswapBloomCacheEnabled: true, // default: use cached blockstore TODO leo: change default to false
Copy link
Member Author

Choose a reason for hiding this comment

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

The test cases also passed when I changed the default to false.

Copy link
Member

@fxamacker fxamacker left a comment

Choose a reason for hiding this comment

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

The condition for creating cachedBlockStore appears to be inverted. Specifically, we should check !SkipBloomCache before creating cachedBlockStore.

Also, it might be easier to follow if we use a positive flag UseBloomCache instead of a negative flag SkipBloomCache. This would make it more consistent with the new node flag BitswapBloomCacheEnabled.

@coderabbitai
Copy link

coderabbitai bot commented Jan 2, 2026

📝 Walkthrough

Walkthrough

Introduces a Bloom filter cache configuration option for the Bitswap service. Adds a new BitswapBloomCacheEnabled field to BaseConfig, exposes it via CLI flag --bitswap-bloom-cache-enabled, and integrates it across multiple node builders to conditionally enable Bloom cache wrapping in the BlobService.

Changes

Cohort / File(s) Summary
Configuration & CLI
cmd/node_builder.go, cmd/scaffold.go
Added public BitswapBloomCacheEnabled bool field to BaseConfig, defaulted to true. Added CLI flag --bitswap-bloom-cache-enabled with binding to propagate user configuration.
Blob Service Infrastructure
network/p2p/blob/blob_service.go
Introduced UseBloomCache field to BlobServiceConfig and public option WithUseBloomCache(use bool). Updated NewBlobService to conditionally wrap blockstore in CachedBlockstore after applying options, enabling lazy bloom cache initialization.
Node Builder Integration
cmd/access/node_builder/access_node_builder.go, cmd/execution_builder.go, cmd/observer/node_builder/observer_builder.go
Applied bloom cache option to BlobService initialization in BuildExecutionSyncComponents across Access, Execution, and Observer node builders by appending blob.WithUseBloomCache(builder.BitswapBloomCacheEnabled) to service options.
Test Logging
integration/tests/access/cohort3/execution_state_sync_test.go
Added debug logging in executionDataForHeight to capture fetch failures (height, block_id, error) and successful conversions (height, block_id, chunk count).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A bloom of cache, so bright and new,
Through builders it flows, tried and true,
Bitswap grins with filtered cheer,
Performance blooms throughout the sphere! 🌸

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: adding a flag to control the bitswap bloom cache feature across Access and Execution nodes.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
cmd/node_builder.go (1)

189-195: BitswapBloomCacheEnabled field and default look consistent (minor doc nit)

The new BitswapBloomCacheEnabled flag and its default of true line up with the blob service’s UseBloomCache default and how builders consume it. One small suggestion: observers also read this flag via their builders, so consider updating the comment (“only meaningful to Access and Execution nodes”) to include Observer nodes to avoid future confusion. Optional only.

Also applies to: 307-314

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e0a94e9 and 4d370bf.

📒 Files selected for processing (7)
  • cmd/access/node_builder/access_node_builder.go
  • cmd/execution_builder.go
  • cmd/node_builder.go
  • cmd/observer/node_builder/observer_builder.go
  • cmd/scaffold.go
  • integration/tests/access/cohort3/execution_state_sync_test.go
  • network/p2p/blob/blob_service.go
🧰 Additional context used
📓 Path-based instructions (5)
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/coding_conventions.mdc)

Follow Go coding conventions as documented in @docs/agents/CodingConventions.md

Follow Go coding standards and conventions as documented in @docs/agents/GoDocs.md

**/*.go: Follow the existing module structure in /module/, /engine/, /model/ and use dependency injection patterns for component composition
Implement proper interfaces before concrete types
Follow Go naming conventions and the project's coding style defined in /docs/CodingConventions.md
Use mock generators: run make generate-mocks after interface changes
All inputs must be considered potentially byzantine; error classification is context-dependent and no code path is safe unless explicitly proven and documented
Use comprehensive error wrapping for debugging; avoid fmt.Errorf, use irrecoverable package for exceptions
NEVER log and continue on best effort basis; ALWAYS explicitly handle errors
Uses golangci-lint with custom configurations (.golangci.yml) and custom linters for Flow-specific conventions (struct write checking)

Files:

  • network/p2p/blob/blob_service.go
  • cmd/access/node_builder/access_node_builder.go
  • cmd/execution_builder.go
  • integration/tests/access/cohort3/execution_state_sync_test.go
  • cmd/node_builder.go
  • cmd/scaffold.go
  • cmd/observer/node_builder/observer_builder.go
{network,engine,consensus}/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Network messages must be authenticated and validated

Files:

  • network/p2p/blob/blob_service.go
{module,engine,cmd}/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

All major processing components must implement the Component interface from /module/component/component.go to ensure consistent lifecycle management and graceful shutdown patterns

Files:

  • cmd/access/node_builder/access_node_builder.go
  • cmd/execution_builder.go
  • cmd/node_builder.go
  • cmd/scaffold.go
  • cmd/observer/node_builder/observer_builder.go
**/*_test.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*_test.go: Unit tests should be co-located with the code they test
Follow the existing pattern of *_test.go files for test naming
Use fixtures for realistic test data as defined in /utils/unittest/

Files:

  • integration/tests/access/cohort3/execution_state_sync_test.go
integration/tests/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Integration tests should go in /integration/tests/

Files:

  • integration/tests/access/cohort3/execution_state_sync_test.go
🧠 Learnings (1)
📚 Learning: 2025-12-23T00:28:41.005Z
Learnt from: CR
Repo: onflow/flow-go PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-23T00:28:41.005Z
Learning: Applies to {storage,ledger,execution,fvm}/**/*.go : State consistency is paramount; use proper synchronization primitives

Applied to files:

  • integration/tests/access/cohort3/execution_state_sync_test.go
🧬 Code graph analysis (4)
cmd/access/node_builder/access_node_builder.go (1)
network/p2p/blob/blob_service.go (1)
  • WithUseBloomCache (107-111)
cmd/execution_builder.go (1)
network/p2p/blob/blob_service.go (1)
  • WithUseBloomCache (107-111)
cmd/scaffold.go (1)
cmd/node_builder.go (1)
  • BaseConfig (140-197)
cmd/observer/node_builder/observer_builder.go (1)
network/p2p/blob/blob_service.go (1)
  • WithUseBloomCache (107-111)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (37)
  • GitHub Check: Lint (./insecure/)
  • GitHub Check: Lint (./)
  • GitHub Check: Lint (./integration/)
  • GitHub Check: Unit Tests (network/alsp)
  • GitHub Check: Unit Tests (others)
  • GitHub Check: Unit Tests (network/p2p/scoring)
  • GitHub Check: Unit Tests (network/p2p/node)
  • GitHub Check: Unit Tests (engine/common)
  • GitHub Check: Unit Tests (module)
  • GitHub Check: Unit Tests (network/test/cohort1)
  • GitHub Check: Unit Tests (engine/consensus)
  • GitHub Check: Unit Tests (engine/access)
  • GitHub Check: Unit Tests (network/p2p/connection)
  • GitHub Check: Unit Tests (engine/execution/computation)
  • GitHub Check: Unit Tests (engine/execution)
  • GitHub Check: Unit Tests (engine/verification)
  • GitHub Check: Unit Tests (module/dkg)
  • GitHub Check: Unit Tests (engine)
  • GitHub Check: Unit Tests (storage)
  • GitHub Check: Unit Tests (network)
  • GitHub Check: Unit Tests (network/test/cohort2)
  • GitHub Check: Unit Tests (network/p2p)
  • GitHub Check: Unit Tests (engine/execution/ingestion)
  • GitHub Check: Unit Tests (engine/collection)
  • GitHub Check: Unit Tests (utils)
  • GitHub Check: Unit Tests (cmd)
  • GitHub Check: Unit Tests (admin)
  • GitHub Check: Unit Tests (fvm)
  • GitHub Check: Unit Tests (consensus)
  • GitHub Check: Unit Tests (state)
  • GitHub Check: Unit Tests (ledger)
  • GitHub Check: Integration Tests Others (integration)
  • GitHub Check: Unit Tests Insecure (insecure)
  • GitHub Check: Unit Tests Insecure (insecure/integration/functional/test/gossipsub/scoring)
  • GitHub Check: Unit Tests Insecure (insecure/integration/functional/test/gossipsub/rpc_inspector)
  • GitHub Check: analyze-code (go)
  • GitHub Check: Docker Build
🔇 Additional comments (5)
integration/tests/access/cohort3/execution_state_sync_test.go (1)

200-216: ✅ Well-placed structured logging for better test observability.

The logging additions capture relevant details (height, block ID, chunk count, errors) and are appropriately positioned:

  • Error logging occurs before retry, aiding visibility into transient failures
  • Success logging occurs after successful data conversion, confirming the full flow succeeded

The structured fields using zerolog are idiomatic for Flow Go. Since these logs are within the retryNotFound callback, they may repeat on retries, which is expected and helpful for debugging integration test behavior.

cmd/observer/node_builder/observer_builder.go (1)

1195-1205: Observer execution data service correctly wired to Bloom cache flag

Appending blob.WithUseBloomCache(builder.BitswapBloomCacheEnabled) to the options here aligns observer behavior with access and execution nodes and keeps the toggle centralized in BaseConfig. No issues spotted with this wiring.

cmd/execution_builder.go (1)

398-418: Execution blob service now respects Bloom cache configuration

Appending blob.WithUseBloomCache(node.BitswapBloomCacheEnabled) ensures execution nodes honor the shared Bloom cache flag, consistent with other builders. The option placement alongside existing bitswap and reprovide options looks correct.

cmd/access/node_builder/access_node_builder.go (1)

646-666: Access execution data service correctly wired to Bloom cache flag

Using blob.WithUseBloomCache(builder.BitswapBloomCacheEnabled) here makes the execution data blob service on access nodes respect the shared Bloom cache toggle, mirroring execution and observer builders. The option ordering and usage look sound.

cmd/scaffold.go (1)

216-219: Approved. The flag binding is correct and properly uses DefaultBaseConfig() which initializes BitswapBloomCacheEnabled to true, matching the PR intent. The implementation is consistent with other bitswap-related flags and the help text clearly documents the experimental feature.

Comment on lines 55 to 59
type BlobServiceConfig struct {
ReprovideInterval time.Duration // the interval at which the DHT provider entries are refreshed
BitswapOptions []bitswap.Option // options to pass to the Bitswap service
UseBloomCache bool // if true, use the bloom cache (cached blockstore), otherwise use plain blockstore
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cd network/p2p/blob && wc -l blob_service.go

Repository: onflow/flow-go

Length of output: 77


🏁 Script executed:

cat -n network/p2p/blob/blob_service.go | head -160

Repository: onflow/flow-go

Length of output: 6605


🏁 Script executed:

# Verify the exact line where blockStore is used in CachedBlockstore call
sed -n '141,151p' network/p2p/blob/blob_service.go

Repository: onflow/flow-go

Length of output: 354


🏁 Script executed:

# Double-check WithRateLimit implementation to confirm it modifies bs.blockStore
sed -n '95,100p' network/p2p/blob/blob_service.go

Repository: onflow/flow-go

Length of output: 303


🏁 Script executed:

# Verify WithParentBlobService also modifies bs.blockStore
sed -n '75,80p' network/p2p/blob/blob_service.go

Repository: onflow/flow-go

Length of output: 334


Fix CachedBlockstore to wrap the final blockstore after applying options

When UseBloomCache is true, CachedBlockstore is called with the local blockStore variable created on line 125, instead of bs.blockStore. Since options like WithRateLimit and WithParentBlobService mutate only bs.blockStore (not the local variable), their effects are silently discarded. For example:

  • If WithRateLimit is applied, it wraps bs.blockStore, but CachedBlockstore then wraps the unwrapped local blockStore, and the rate limiter is lost.
  • If WithParentBlobService is applied, it replaces bs.blockStore with the parent's store, but CachedBlockstore wraps the new local blockStore instead, breaking the parent relationship.

Change line 144 to use bs.blockStore instead of blockStore:

Proposed fix
 	if bs.config.UseBloomCache {
 		cachedBlockStore, err := blockstore.CachedBlockstore(
 			context.Background(),
-			blockStore,
+			bs.blockStore,
 			blockstore.DefaultCacheOpts(),
 		)
 		if err != nil {
 			return nil, fmt.Errorf("failed to create cached blockstore: %w", err)
 		}
 		bs.blockStore = cachedBlockStore
 	}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In network/p2p/blob/blob_service.go around lines ~125-145, the CachedBlockstore
call wraps the local variable blockStore instead of bs.blockStore, causing any
option-wrapping (e.g. WithRateLimit, WithParentBlobService) applied to
bs.blockStore to be ignored; change the CachedBlockstore invocation to use
bs.blockStore (the final, possibly-wrapped store) so that all option mutations
are preserved and the parent/RateLimit wrappers remain effective.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants