From 67a0b9a8f7591e49cfbd75f416a63d38d7237fa3 Mon Sep 17 00:00:00 2001 From: Aryan Tikarya Date: Tue, 9 Jun 2026 14:45:55 +0530 Subject: [PATCH 1/3] fix: eth block returns correctly filled log bloom field --- src/rpc/methods/eth.rs | 86 +++++++++++++++++++++++++++++-- src/rpc/methods/eth/filter/mod.rs | 25 +++++++-- 2 files changed, 104 insertions(+), 7 deletions(-) diff --git a/src/rpc/methods/eth.rs b/src/rpc/methods/eth.rs index c8cac3138e1..70945192e1d 100644 --- a/src/rpc/methods/eth.rs +++ b/src/rpc/methods/eth.rs @@ -550,6 +550,9 @@ impl Block { full_transactions.push(tx); } + let logs_bloom = + compute_block_logs_bloom(state_manager, &tipset, &executed_messages).await?; + Ok(Arc::new(Block { hash: block_hash, number: block_number, @@ -563,6 +566,7 @@ impl Block { .into(), gas_used: EthUint64(gas_used), transactions: Transactions::Full(full_transactions), + logs_bloom, ..Block::new(has_transactions, tipset.len()) })) }) @@ -1372,10 +1376,7 @@ async fn new_eth_tx_receipt( let mut bloom = Bloom::default(); for log in tx_receipt.logs.iter() { - for topic in log.topics.iter() { - bloom.accrue(topic.0.as_bytes()); - } - bloom.accrue(log.address.0.as_bytes()); + accrue_eth_log(&mut bloom, &log.address, &log.topics); } tx_receipt.logs_bloom = bloom.into(); @@ -3237,6 +3238,43 @@ fn eth_filter_logs_from_events( Ok(logs) } +/// Accrues a single Ethereum log's address and topics into `bloom` using the standard `M3:2048` scheme. +fn accrue_eth_log(bloom: &mut Bloom, address: &EthAddress, topics: &[EthHash]) { + for topic in topics { + bloom.accrue(topic.0.as_bytes()); + } + bloom.accrue(address.0.as_bytes()); +} + +async fn compute_block_logs_bloom( + state_manager: &StateManager, + tipset: &Tipset, + executed_messages: &[ExecutedMessage], +) -> Result { + let mut events = vec![]; + EthEventHandler::collect_events_from_messages( + state_manager, + tipset, + executed_messages, + None::<&EthFilterSpec>, + SkipEvent::OnUnresolvedAddress, + &mut events, + ) + .await?; + + let mut bloom = Bloom::default(); + for event in &events { + let Some((_data, topics)) = eth_log_from_event(&event.entries) else { + continue; + }; + let Ok(address) = EthAddress::from_filecoin_address(&event.emitter_addr) else { + continue; + }; + accrue_eth_log(&mut bloom, &address, &topics); + } + Ok(bloom) +} + fn eth_filter_result_from_events( ctx: &Ctx, events: &[CollectedEvent], @@ -4547,6 +4585,46 @@ mod test { assert!(eth_log_from_event(&entries).is_none()); } + #[test] + fn test_accrue_eth_log_and_block_bloom_decomposition() { + let empty = Bloom::default(); + let full = Bloom(ethereum_types::Bloom(FULL_BLOOM)); + + // No logs yields the all-zeros bloom — the "definitely no events here" case + // indexers rely on. + assert_eq!(empty.0.0, EMPTY_BLOOM); + + let addr_a = EthAddress(ethereum_types::H160::from_slice(&[0x11; ADDRESS_LENGTH])); + let topic_a = EthHash(ethereum_types::H256::from_slice(&[0x22; EVM_WORD_LENGTH])); + let addr_b = EthAddress(ethereum_types::H160::from_slice(&[0x33; ADDRESS_LENGTH])); + let topic_b = EthHash(ethereum_types::H256::from_slice(&[0x44; EVM_WORD_LENGTH])); + + // A real log sets some bits, but not all of them. + let mut bloom_a = empty.clone(); + accrue_eth_log(&mut bloom_a, &addr_a, std::slice::from_ref(&topic_a)); + assert_ne!(bloom_a, empty); + assert_ne!(bloom_a, full); + + let mut bloom_b = empty.clone(); + accrue_eth_log(&mut bloom_b, &addr_b, std::slice::from_ref(&topic_b)); + + // The block bloom (both logs) equals the bitwise OR of the two individual + // (receipt) blooms. + let mut combined = bloom_a.clone(); + accrue_eth_log(&mut combined, &addr_b, std::slice::from_ref(&topic_b)); + + let mut expected = bloom_a.0.0; + for (out, b) in expected.iter_mut().zip(bloom_b.0.0.iter()) { + *out |= *b; + } + assert_eq!(combined.0.0, expected); + + // Accruing the same log twice equals accruing it once. + let mut twice = bloom_a.clone(); + accrue_eth_log(&mut twice, &addr_a, std::slice::from_ref(&topic_a)); + assert_eq!(twice, bloom_a); + } + #[test] fn test_from_bytes_valid() { let zero_bytes = [0u8; 32]; diff --git a/src/rpc/methods/eth/filter/mod.rs b/src/rpc/methods/eth/filter/mod.rs index b97a14bf7a3..59ca525984e 100644 --- a/src/rpc/methods/eth/filter/mod.rs +++ b/src/rpc/methods/eth/filter/mod.rs @@ -341,12 +341,31 @@ impl EthEventHandler { skip_event: SkipEvent, collected_events: &mut Vec, ) -> anyhow::Result<()> { - let msg_cid_filter = spec.and_then(|s| s.msg_cid_filter()).copied(); - let height = tipset.epoch(); - let tipset_key = tipset.key(); let ExecutedTipset { executed_messages, .. } = state_manager.load_executed_tipset_for_rpc(tipset).await?; + Self::collect_events_from_messages( + state_manager, + tipset, + &executed_messages, + spec, + skip_event, + collected_events, + ) + .await + } + + pub async fn collect_events_from_messages( + state_manager: &StateManager, + tipset: &Tipset, + executed_messages: &[ExecutedMessage], + spec: Option<&impl Matcher>, + skip_event: SkipEvent, + collected_events: &mut Vec, + ) -> anyhow::Result<()> { + let msg_cid_filter = spec.and_then(|s| s.msg_cid_filter()).copied(); + let height = tipset.epoch(); + let tipset_key = tipset.key(); let mut resolved_id_addrs = HashMap::default(); let mut event_count = 0; for ( From dba659be30bb36d1d49efca2cc5107afbdd213e1 Mon Sep 17 00:00:00 2001 From: Aryan Tikarya Date: Tue, 9 Jun 2026 21:26:36 +0530 Subject: [PATCH 2/3] update the changelog entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89a0b17906d..fcac9589f24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,8 @@ - [#6975](https://github.com/ChainSafe/forest/issues/6975): Fixed `Filecoin.MpoolSelect` to not remove the messages from the live pool, only simulate the head change. +- [#7156](https://github.com/ChainSafe/forest/pull/7156): Fixed the block-level bloom is now computed from the block's logs. + ## Forest v0.33.6 "Ebb" Non-mandatory release for all node operators. It fixes a critical memory leak in `v0.33.5`. (Earlier releases are not affected) From 96b6e9c45d72be0f2e286a0c3ef21e23e1a9541c Mon Sep 17 00:00:00 2001 From: Aryan Tikarya Date: Fri, 19 Jun 2026 22:11:10 +0530 Subject: [PATCH 3/3] add snapshot tests and update the filter list --- scripts/tests/api_compare/filter-list | 2 -- scripts/tests/api_compare/filter-list-gateway | 3 --- src/tool/subcommands/api_cmd/test_snapshots.txt | 6 +++--- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/scripts/tests/api_compare/filter-list b/scripts/tests/api_compare/filter-list index 02dc8cafde9..d000c65e9aa 100644 --- a/scripts/tests/api_compare/filter-list +++ b/scripts/tests/api_compare/filter-list @@ -3,5 +3,3 @@ !Filecoin.StateGetNetworkParams !Filecoin.EthEstimateGas -!Filecoin.EthGetBlockByHash -!Filecoin.EthGetBlockByNumber diff --git a/scripts/tests/api_compare/filter-list-gateway b/scripts/tests/api_compare/filter-list-gateway index 24acbdc7b0e..ff376a280ba 100644 --- a/scripts/tests/api_compare/filter-list-gateway +++ b/scripts/tests/api_compare/filter-list-gateway @@ -69,6 +69,3 @@ !Filecoin.StateGetNetworkParams # https://github.com/filecoin-project/lotus/pull/13644 !Filecoin.EthEstimateGas -# https://github.com/filecoin-project/lotus/pull/13618 -!Filecoin.EthGetBlockByHash -!Filecoin.EthGetBlockByNumber diff --git a/src/tool/subcommands/api_cmd/test_snapshots.txt b/src/tool/subcommands/api_cmd/test_snapshots.txt index c7e08f24d96..94409661cd8 100644 --- a/src/tool/subcommands/api_cmd/test_snapshots.txt +++ b/src/tool/subcommands/api_cmd/test_snapshots.txt @@ -66,9 +66,9 @@ filecoin_ethgetbalance_v2_latest_1770291948779489.rpcsnap.json.zst filecoin_ethgetbalance_v2_pending_1770291949065157.rpcsnap.json.zst filecoin_ethgetbalance_v2_safe_1770291948803158.rpcsnap.json.zst filecoin_ethgetbalance_v2_unknown_addr_1770287845559744.rpcsnap.json.zst -filecoin_ethgetblockbyhash_1781166100013912.rpcsnap.json.zst -filecoin_ethgetblockbynumber_1737446676696328.rpcsnap.json.zst -filecoin_ethgetblockbynumber_v2_1781166100024105.rpcsnap.json.zst +filecoin_ethgetblockbyhash_1781886021508619.rpcsnap.json.zst +filecoin_ethgetblockbynumber_1781887507408523.rpcsnap.json.zst +filecoin_ethgetblockbynumber_v2_1781887507413486.rpcsnap.json.zst filecoin_ethgetblockreceipts_1781166100049979.rpcsnap.json.zst filecoin_ethgetblockreceipts_v2_1781166100038659.rpcsnap.json.zst filecoin_ethgetblockreceiptslimited_1781166100061549.rpcsnap.json.zst