1use crate::{block::BlockNumber, bytes::Bytes};
8use cfx_types::{Address, Bloom, BloomInput, Space, H256};
9use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
10use rlp::RlpStream;
11use serde_derive::{Deserialize, Serialize};
12use std::ops::Deref;
13
14#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
16pub struct LogEntry {
17 pub address: Address,
20 pub topics: Vec<H256>,
22 pub data: Bytes,
24 pub space: Space,
26}
27
28impl rlp::Encodable for LogEntry {
29 fn rlp_append(&self, s: &mut RlpStream) {
30 match self.space {
31 Space::Native => {
32 s.begin_list(3);
33 s.append(&self.address);
34 s.append_list(&self.topics);
35 s.append(&self.data);
36 }
37 Space::Ethereum => {
38 s.begin_list(4);
39 s.append(&self.address);
40 s.append_list(&self.topics);
41 s.append(&self.data);
42 s.append(&self.space);
43 }
44 }
45 }
46}
47
48impl rlp::Decodable for LogEntry {
52 fn decode(rlp: &rlp::Rlp) -> Result<Self, rlp::DecoderError> {
53 match rlp.item_count()? {
54 3 => Ok(LogEntry {
55 address: rlp.val_at(0)?,
56 topics: rlp.list_at(1)?,
57 data: rlp.val_at(2)?,
58 space: Space::Native,
59 }),
60 4 => Ok(LogEntry {
61 address: rlp.val_at(0)?,
62 topics: rlp.list_at(1)?,
63 data: rlp.val_at(2)?,
64 space: rlp.val_at(3)?,
65 }),
66 _ => Err(rlp::DecoderError::RlpInvalidLength),
67 }
68 }
69}
70
71impl MallocSizeOf for LogEntry {
72 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
73 self.topics.size_of(ops) + self.data.size_of(ops)
74 }
75}
76
77impl LogEntry {
78 pub fn bloom(&self) -> Bloom {
80 self.topics.iter().fold(
81 Bloom::from(BloomInput::Raw(self.address.as_bytes())),
82 |mut b, t| {
83 b.accrue(BloomInput::Raw(t.as_bytes()));
84 b
85 },
86 )
87 }
88}
89
90pub fn build_bloom(logs: &[LogEntry]) -> Bloom {
91 logs.iter()
92 .map(LogEntry::bloom)
93 .fold(Bloom::default(), |mut acc, bloom| {
94 acc.accrue_bloom(&bloom);
95 acc
96 })
97}
98
99#[derive(Default, Debug, PartialEq, Clone)]
101pub struct LocalizedLogEntry {
102 pub entry: LogEntry,
104 pub block_hash: H256,
106 pub epoch_number: BlockNumber,
108 pub block_timestamp: Option<u64>,
110 pub transaction_hash: H256,
112 pub transaction_index: usize,
114 pub log_index: usize,
116 pub transaction_log_index: usize,
118}
119
120impl Deref for LocalizedLogEntry {
121 type Target = LogEntry;
122
123 fn deref(&self) -> &Self::Target { &self.entry }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::LogEntry;
129 use crate::bytes::Bytes;
130 use cfx_types::{Address, Bloom, Space, H256};
131 use rlp_derive::RlpEncodable;
132
133 #[derive(PartialEq, Eq, RlpEncodable)]
134 pub struct LogEntryOld {
135 pub address: Address,
136 pub topics: Vec<H256>,
137 pub data: Bytes,
138 }
139
140 #[test]
141 fn test_empty_log_bloom() {
142 let bloom = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".parse::<Bloom>().unwrap();
143 let address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6"
144 .parse::<Address>()
145 .unwrap();
146 let log = LogEntry {
147 address,
148 topics: vec![],
149 data: vec![],
150 space: Space::Native,
151 };
152 assert_eq!(log.bloom(), bloom);
153 }
154
155 #[test]
156 fn test_rlp() {
157 let address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6"
158 .parse::<Address>()
159 .unwrap();
160
161 let log = LogEntry {
163 address,
164 topics: vec![],
165 data: vec![],
166 space: Space::Ethereum,
167 };
168
169 assert_eq!(log, rlp::decode(&rlp::encode(&log)).unwrap());
170
171 let log_old = LogEntryOld {
173 address,
174 topics: vec![],
175 data: vec![],
176 };
177
178 let log_new: LogEntry = rlp::decode(&rlp::encode(&log_old)).unwrap();
179
180 assert_eq!(
181 log_new,
182 LogEntry {
183 address,
184 topics: vec![],
185 data: vec![],
186 space: Space::Native,
187 }
188 );
189 }
190}