1#![cfg_attr(not(feature="std"), no_std)]
30
31#[cfg(feature="std")]
32extern crate core;
33
34extern crate tiny_keccak;
35#[macro_use]
36extern crate crunchy;
37
38#[macro_use]
39extern crate fixed_hash;
40
41#[cfg(feature="serialize")]
42extern crate s_types_serialize;
43
44#[cfg(feature="serialize")]
45extern crate serde;
46
47#[cfg(feature="serialize")]
48use serde::{Serialize, Serializer, Deserialize, Deserializer};
49
50use core::{ops, mem};
51use tiny_keccak::keccak256;
52
53#[cfg(feature="std")]
54use core::str;
55
56const BLOOM_BITS: u32 = 3;
58const BLOOM_SIZE: usize = 256;
59
60construct_hash!(Bloom, BLOOM_SIZE);
61
62fn log2(x: usize) -> u32 {
64 if x <= 1 {
65 return 0;
66 }
67
68 let n = x.leading_zeros();
69 mem::size_of::<usize>() as u32 * 8 - n
70}
71
72pub enum Input<'a> {
73 Raw(&'a [u8]),
74 Hash(&'a [u8; 32]),
75}
76
77enum Hash<'a> {
78 Ref(&'a [u8; 32]),
79 Owned([u8; 32]),
80}
81
82impl<'a> From<Input<'a>> for Hash<'a> {
83 fn from(input: Input<'a>) -> Self {
84 match input {
85 Input::Raw(raw) => Hash::Owned(keccak256(raw)),
86 Input::Hash(hash) => Hash::Ref(hash),
87 }
88 }
89}
90
91impl<'a> ops::Index<usize> for Hash<'a> {
92 type Output = u8;
93
94 fn index(&self, index: usize) -> &u8 {
95 match *self {
96 Hash::Ref(r) => &r[index],
97 Hash::Owned(ref hash) => &hash[index],
98 }
99 }
100}
101
102impl<'a> Hash<'a> {
103 fn len(&self) -> usize {
104 match *self {
105 Hash::Ref(r) => r.len(),
106 Hash::Owned(ref hash) => hash.len(),
107 }
108 }
109}
110
111impl<'a> PartialEq<BloomRef<'a>> for Bloom {
112 fn eq(&self, other: &BloomRef<'a>) -> bool {
113 let s_ref: &[u8] = &self.0;
114 let o_ref: &[u8] = other.0;
115 s_ref.eq(o_ref)
116 }
117}
118
119impl<'a> From<Input<'a>> for Bloom {
120 fn from(input: Input<'a>) -> Bloom {
121 let mut bloom = Bloom::default();
122 bloom.accrue(input);
123 bloom
124 }
125}
126
127impl Bloom {
128 pub fn is_empty(&self) -> bool {
129 self.0.iter().all(|x| *x == 0)
130 }
131
132 pub fn contains_input<'a>(&self, input: Input<'a>) -> bool {
133 let bloom: Bloom = input.into();
134 self.contains_bloom(&bloom)
135 }
136
137 pub fn contains_bloom<'a, B>(&self, bloom: B) -> bool where BloomRef<'a>: From<B> {
138 let bloom_ref: BloomRef = bloom.into();
139 self.contains_bloom_ref(bloom_ref)
141 }
142
143 fn contains_bloom_ref(&self, bloom: BloomRef) -> bool {
144 let self_ref: BloomRef = self.into();
145 self_ref.contains_bloom(bloom)
146 }
147
148 pub fn accrue<'a>(&mut self, input: Input<'a>) {
149 let p = BLOOM_BITS;
150
151 let m = self.0.len();
152 let bloom_bits = m * 8;
153 let mask = bloom_bits - 1;
154 let bloom_bytes = (log2(bloom_bits) + 7) / 8;
155
156 let hash: Hash = input.into();
157
158 assert_eq!(m & (m - 1), 0);
160 assert!(p * bloom_bytes <= hash.len() as u32);
162
163 let mut ptr = 0;
164
165 assert_eq!(BLOOM_BITS, 3);
166 unroll! {
167 for i in 0..3 {
168 let _ = i;
169 let mut index = 0 as usize;
170 for _ in 0..bloom_bytes {
171 index = (index << 8) | hash[ptr] as usize;
172 ptr += 1;
173 }
174 index &= mask;
175 self.0[m - 1 - index / 8] |= 1 << (index % 8);
176 }
177 }
178 }
179
180 pub fn accrue_bloom<'a, B>(&mut self, bloom: B) where BloomRef<'a>: From<B> {
181 let bloom_ref: BloomRef = bloom.into();
182 assert_eq!(self.0.len(), BLOOM_SIZE);
183 assert_eq!(bloom_ref.0.len(), BLOOM_SIZE);
184 for i in 0..BLOOM_SIZE {
185 self.0[i] |= bloom_ref.0[i];
186 }
187 }
188
189 pub fn data(&self) -> &[u8; BLOOM_SIZE] {
190 &self.0
191 }
192}
193
194#[derive(Clone, Copy)]
195pub struct BloomRef<'a>(&'a [u8; BLOOM_SIZE]);
196
197impl<'a> BloomRef<'a> {
198 pub fn is_empty(&self) -> bool {
199 self.0.iter().all(|x| *x == 0)
200 }
201
202 pub fn contains_input<'b>(&self, input: Input<'b>) -> bool {
203 let bloom: Bloom = input.into();
204 self.contains_bloom(&bloom)
205 }
206
207 pub fn contains_bloom<'b, B>(&self, bloom: B) -> bool where BloomRef<'b>: From<B> {
208 let bloom_ref: BloomRef = bloom.into();
209 assert_eq!(self.0.len(), BLOOM_SIZE);
210 assert_eq!(bloom_ref.0.len(), BLOOM_SIZE);
211 for i in 0..BLOOM_SIZE {
212 let a = self.0[i];
213 let b = bloom_ref.0[i];
214 if (a & b) != b {
215 return false;
216 }
217 }
218 true
219 }
220
221 pub fn data(&self) -> &'a [u8; BLOOM_SIZE] {
222 self.0
223 }
224}
225
226impl<'a> From<&'a [u8; BLOOM_SIZE]> for BloomRef<'a> {
227 fn from(data: &'a [u8; BLOOM_SIZE]) -> Self {
228 BloomRef(data)
229 }
230}
231
232impl<'a> From<&'a Bloom> for BloomRef<'a> {
233 fn from(bloom: &'a Bloom) -> Self {
234 BloomRef(&bloom.0)
235 }
236}
237
238#[cfg(feature="serialize")]
239impl Serialize for Bloom {
240 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
241 let mut slice = [0u8; 2 + 2 * BLOOM_SIZE];
242 s_types_serialize::serialize(&mut slice, &self.0, serializer)
243 }
244}
245
246#[cfg(feature="serialize")]
247impl<'de> Deserialize<'de> for Bloom {
248 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
249 let mut bytes = [0; BLOOM_SIZE];
250 s_types_serialize::deserialize_check_len(deserializer, s_types_serialize::ExpectedLen::Exact(&mut bytes))?;
251 Ok(Bloom(bytes))
252 }
253}
254
255#[cfg(test)]
256mod tests {
257 extern crate rustc_hex;
258 use self::rustc_hex::FromHex;
259 use {Bloom, Input};
260
261 #[test]
262 fn it_works() {
263 let bloom: Bloom = "00000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000008000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into();
264 let address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".from_hex().unwrap();
265 let topic = "02c69be41d0b7e40352fc85be1cd65eb03d40ef8427a0ca4596b1ead9a00e9fc".from_hex().unwrap();
266
267 let mut my_bloom = Bloom::default();
268 assert!(!my_bloom.contains_input(Input::Raw(&address)));
269 assert!(!my_bloom.contains_input(Input::Raw(&topic)));
270
271 my_bloom.accrue(Input::Raw(&address));
272 assert!(my_bloom.contains_input(Input::Raw(&address)));
273 assert!(!my_bloom.contains_input(Input::Raw(&topic)));
274
275 my_bloom.accrue(Input::Raw(&topic));
276 assert!(my_bloom.contains_input(Input::Raw(&address)));
277 assert!(my_bloom.contains_input(Input::Raw(&topic)));
278 assert_eq!(my_bloom, bloom);
279 }
280}