stratus/eth/primitives/
logs_bloom.rs

1use std::ops::Deref;
2use std::ops::DerefMut;
3
4use alloy_primitives::Bloom;
5use alloy_primitives::BloomInput;
6
7use crate::eth::primitives::Log;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize, Default)]
10#[serde(transparent)]
11pub struct LogsBloom(pub Bloom);
12
13impl LogsBloom {
14    pub fn accrue_log(&mut self, log: &Log) {
15        self.accrue(BloomInput::Raw(log.address.as_ref()));
16        for topic in log.topics_non_empty() {
17            self.accrue(BloomInput::Raw(topic.as_ref()));
18        }
19    }
20}
21
22impl Deref for LogsBloom {
23    type Target = Bloom;
24
25    fn deref(&self) -> &Self::Target {
26        &self.0
27    }
28}
29
30impl DerefMut for LogsBloom {
31    fn deref_mut(&mut self) -> &mut Self::Target {
32        &mut self.0
33    }
34}
35
36// -----------------------------------------------------------------------------
37// Conversions: Other -> Self
38// -----------------------------------------------------------------------------
39
40impl From<[u8; 256]> for LogsBloom {
41    fn from(value: [u8; 256]) -> Self {
42        Self(Bloom::from(value))
43    }
44}
45
46impl From<Bloom> for LogsBloom {
47    fn from(value: Bloom) -> Self {
48        let bytes: [u8; 256] = *value.0;
49        Self(Bloom::from(bytes))
50    }
51}
52
53// -----------------------------------------------------------------------------
54// Conversions: Self -> Other
55// -----------------------------------------------------------------------------
56
57impl From<LogsBloom> for Bloom {
58    fn from(value: LogsBloom) -> Self {
59        value.0
60    }
61}
62
63impl From<LogsBloom> for [u8; 256] {
64    fn from(value: LogsBloom) -> Self {
65        value.0.into_array()
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use hex_literal::hex;
72
73    use super::*;
74
75    #[test]
76    fn compute_bloom() {
77        let log1 = Log {
78            address: hex!("c6d1efd908ef6b69da0749600f553923c465c812").into(),
79            topic0: Some(hex!("ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef").into()),
80            topic1: Some(hex!("000000000000000000000000d1ff9b395856e5a6810f626eca09d61d34fce3b8").into()),
81            topic2: Some(hex!("000000000000000000000000081d2c5b26db6f6e0944e4725b3b61b26e25dd8a").into()),
82            topic3: None,
83            data: hex!("0000000000000000000000000000000000000000000000000000000005f5e100").as_ref().into(),
84        };
85        let log2 = Log {
86            address: hex!("b1f571b3254c99a0a562124738f0193de2b2b2a9").into(),
87            topic0: Some(hex!("8d995e7fbf7a5ef41cee9e6936368925d88e07af89306bb78a698551562e683c").into()),
88            topic1: Some(hex!("000000000000000000000000081d2c5b26db6f6e0944e4725b3b61b26e25dd8a").into()),
89            topic2: None,
90            topic3: None,
91            data: hex!(
92                "0000000000000000000000000000000000000000000000000000000000004dca00000000\
93                0000000000000000000000000000000000000000000000030c9281f0"
94            )
95            .as_ref()
96            .into(),
97        };
98        let mut bloom = LogsBloom::default();
99        bloom.accrue_log(&log1);
100        bloom.accrue_log(&log2);
101
102        let expected: LogsBloom = hex!(
103            "000000000400000000000000000000000000000000000000000000000000\
104        00000000000000000000000000000000000000080000000000000000000000000000000000000000000000000008\
105        00008400202000000000002000000000000000000000000000000010000000000000000000000000040000000000\
106        00100000000000000000000000000000000000000000000000000000000000000000000000001000000000000100\
107        00000000000000000000000000000000000000000000080000000002000000000000000000000000000000002000\
108        000000440000000000000000000000000000000000000000000000000000000000000000000000000000"
109        )
110        .into();
111
112        assert_eq!(bloom, expected);
113    }
114}