Skip to content

fix: align bloom filter size/hash calculation with Dash Core#529

Open
xdustinface wants to merge 1 commit intov0.42-devfrom
fix/bloom-calculation
Open

fix: align bloom filter size/hash calculation with Dash Core#529
xdustinface wants to merge 1 commit intov0.42-devfrom
fix/bloom-calculation

Conversation

@xdustinface
Copy link
Collaborator

@xdustinface xdustinface commented Mar 13, 2026

Fix BloomFilter size calculation to compute filter size in bytes first (integer division), then convert to bits (bytes*8), matching how Dash Core implementation sizes the filter.

The previous code used ceil on bits directly, leading to wrong filter sizes and hash moduli that caused bloom filter mismatches.

Summary by CodeRabbit

  • Bug Fixes

    • Bloom filter size and hashing calculations now match Dash Core behavior, fixing edge cases (including 1-byte filters) for correct interoperability.
  • Tests

    • Added comprehensive tests validating Bloom filter serialization and operations against Dash Core reference vectors, including key insertion scenarios.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 13, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 07eb7930-673d-44c9-8c68-d3a9dcf19dfb

📥 Commits

Reviewing files that changed from the base of the PR and between b9c5d69 and a07f95c.

📒 Files selected for processing (1)
  • dash/src/bloom/filter.rs

📝 Walkthrough

Walkthrough

Rewrote Bloom filter sizing and hashing to align with Dash Core: compute filter_bits from elements and false_positive_rate, clamp to ≥8 bits, derive filter_bytes/aligned_bits, and recalculate n_hash_funcs from aligned_bits. Allocation, BitVec init, comments, and tests (including 1-byte edge cases and Dash Core vectors) were updated.

Changes

Cohort / File(s) Summary
BloomFilter Core & Tests
dash/src/bloom/filter.rs
Replaced previous filter_size logic with Dash-aligned computation: filter_bits → clamp ≥8 → filter_bytesaligned_bits; removed old division/rounding and prior n_hash_funcs calc; allocate using aligned_bits and adjust BitVec init. Added comments linking Dash Core, expanded tests (serialization vs Dash Core vectors, 1‑byte filter edge cases) and imports for PrivateKey/secp256k1 used in tests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I dug through bits and bytes anew,
Four and eight and hashes two,
Aligned my bytes to Dash's song,
Tiny filters hopping along,
Seeds and vectors hum—I've leapt so true. 🎉

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: aligning bloom filter size/hash calculation with Dash Core, which is the primary purpose of the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/bloom-calculation
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Fix `BloomFilter` size calculation to compute filter size in bytes first (integer division), then convert to bits (bytes*8), matching how Dash Core implementation sizes the filter.

The previous code used `ceil` on bits directly, leading to wrong filter sizes and hash moduli that caused bloom filter mismatches.
@xdustinface xdustinface force-pushed the fix/bloom-calculation branch from b9c5d69 to a07f95c Compare March 13, 2026 01:59
Copy link
Contributor

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@dash/src/bloom/filter.rs`:
- Around line 355-363: Replace the hardcoded private key bytes, SecretKey
creation, and the fixed Network::Mainnet use in the test: instead of building a
PrivateKey from privkey_bytes and calling PrivateKey::new_uncompressed(...
Network::Mainnet) (symbols: privkey_bytes, secret_key,
PrivateKey::new_uncompressed, pubkey, secp), use a non-sensitive test
fixture—either construct a PublicKey directly from a constant pubkey hex (e.g.,
PublicKey::from_slice(...)) so no private material is present, or derive a
deterministic SecretKey from a constant seed for test purposes and use a
test/regtest network constant (not Mainnet) pulled from test config; update
places that expect privkey/pubkey to accept the new fixture.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 31db95a8-722e-44f8-b6f0-20a2d1a1d441

📥 Commits

Reviewing files that changed from the base of the PR and between 33eb7b8 and b9c5d69.

📒 Files selected for processing (1)
  • dash/src/bloom/filter.rs

@codecov
Copy link

codecov bot commented Mar 13, 2026

Codecov Report

❌ Patch coverage is 97.26027% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.90%. Comparing base (d9d55ef) to head (a07f95c).
⚠️ Report is 1 commits behind head on v0.42-dev.

Files with missing lines Patch % Lines
dash/src/bloom/filter.rs 97.26% 2 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##           v0.42-dev     #529      +/-   ##
=============================================
- Coverage      66.92%   66.90%   -0.02%     
=============================================
  Files            313      313              
  Lines          64729    64877     +148     
=============================================
+ Hits           43322    43409      +87     
- Misses         21407    21468      +61     
Flag Coverage Δ *Carryforward flag
core 75.14% <97.26%> (+0.11%) ⬆️
dash-network 74.99% <ø> (-0.01%) ⬇️ Carriedforward from d9d55ef
dash-network-ffi 34.76% <ø> (ø) Carriedforward from d9d55ef
dash-spv 68.26% <ø> (ø) Carriedforward from d9d55ef
dash-spv-ffi 34.76% <ø> (ø) Carriedforward from d9d55ef
dashcore 74.99% <ø> (-0.01%) ⬇️ Carriedforward from d9d55ef
dashcore-private 74.99% <ø> (-0.01%) ⬇️ Carriedforward from d9d55ef
dashcore-rpc 19.92% <ø> (ø) Carriedforward from d9d55ef
dashcore-rpc-json 19.92% <ø> (ø) Carriedforward from d9d55ef
dashcore_hashes 74.99% <ø> (-0.01%) ⬇️ Carriedforward from d9d55ef
ffi 36.51% <ø> (+0.10%) ⬆️
key-wallet 65.65% <ø> (ø) Carriedforward from d9d55ef
key-wallet-ffi 34.76% <ø> (ø) Carriedforward from d9d55ef
key-wallet-manager 65.65% <ø> (ø) Carriedforward from d9d55ef
rpc 19.92% <ø> (ø)
spv 81.07% <ø> (-0.02%) ⬇️
wallet 65.68% <ø> (ø)

*This pull request uses carry forward flags. Click here to find out more.

Files with missing lines Coverage Δ
dash/src/bloom/filter.rs 90.51% <97.26%> (+6.17%) ⬆️

... and 17 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@xdustinface xdustinface requested a review from ZocoLini March 13, 2026 02:29
/// https://github.com/dashpay/dash/blob/b66b56c3019fe7ab0c9f35dd9894c0ded4d9d420/src/test/bloom_tests.cpp#L51-L74
#[test]
fn test_bloom_filter_dash_core_compatibility_with_tweak() {
let mut filter = BloomFilter::new(3, 0.01, 2147483649, BloomFlags::All).unwrap();
Copy link
Collaborator

Choose a reason for hiding this comment

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

I dont see difference beetwen this test and test_bloom_filter_dash_core_compatibility other than the filter constructor, maybe a for loop over a collection containing both bloom filters?? Maybe extract the logic into a function encapsulated in the test function and call it with both filters??

let aligned_bits = filter_bytes * 8;

let n_hash_funcs = (aligned_bits as f64 / elements as f64 * ln2) as u32;
let n_hash_funcs = n_hash_funcs.clamp(1, MAX_HASH_FUNCS);
Copy link
Collaborator

Choose a reason for hiding this comment

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

using clamp is kinda unnecessary, u32 cannot be less than 1 and the C++ code is not checking it either

let filter_size = filter_size.clamp(1, MAX_BLOOM_FILTER_SIZE * 8);
let filter_bits =
(-1.0 / ln2_squared * elements as f64 * false_positive_rate.ln()) as usize;
let filter_bits = filter_bits.clamp(8, MAX_BLOOM_FILTER_SIZE * 8);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I dont see the C++ code checking if the value is less than 8, and I dont know enough about BloomFilters implementation right now, so I have to trust you

/// Expected serialized bytes: "038fc16b080000000000000001"
#[test]
fn test_bloom_create_insert_key() {
let secp = secp256k1::Secp256k1::new();
Copy link
Collaborator

Choose a reason for hiding this comment

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

This unit test is testing the same paths (in BloomFilter) the test_bloom_filter_dash_core_compatibility function is testing, right??

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.

2 participants