1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use std::ops::Deref;
use util::{H256, Address, Bytes, HeapSizeOf, Hashable};
use util::bloom::Bloomable;
use rlp::*;
use basic_types::LogBloom;
use header::BlockNumber;
use ethjson;
#[derive(Default, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct LogEntry {
pub address: Address,
pub topics: Vec<H256>,
pub data: Bytes,
}
impl Encodable for LogEntry {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(3);
s.append(&self.address);
s.append(&self.topics);
s.append(&self.data);
}
}
impl Decodable for LogEntry {
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
let d = decoder.as_rlp();
let entry = LogEntry {
address: d.val_at(0)?,
topics: d.val_at(1)?,
data: d.val_at(2)?,
};
Ok(entry)
}
}
impl HeapSizeOf for LogEntry {
fn heap_size_of_children(&self) -> usize {
self.topics.heap_size_of_children() + self.data.heap_size_of_children()
}
}
impl LogEntry {
pub fn bloom(&self) -> LogBloom {
self.topics.iter().fold(LogBloom::from_bloomed(&self.address.sha3()), |b, t| b.with_bloomed(&t.sha3()))
}
}
impl From<ethjson::state::Log> for LogEntry {
fn from(l: ethjson::state::Log) -> Self {
LogEntry {
address: l.address.into(),
topics: l.topics.into_iter().map(Into::into).collect(),
data: l.data.into(),
}
}
}
#[derive(Default, Debug, PartialEq, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub struct LocalizedLogEntry {
pub entry: LogEntry,
pub block_hash: H256,
pub block_number: BlockNumber,
pub transaction_hash: H256,
pub transaction_index: usize,
pub log_index: usize,
pub transaction_log_index: usize,
}
impl Deref for LocalizedLogEntry {
type Target = LogEntry;
fn deref(&self) -> &Self::Target {
&self.entry
}
}
#[cfg(test)]
mod tests {
use util::*;
use super::LogEntry;
#[test]
fn test_empty_log_bloom() {
let bloom = H2048::from_str("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
let log = LogEntry {
address: address,
topics: vec![],
data: vec![]
};
assert_eq!(log.bloom(), bloom);
}
}