ethers_core/types/
filter.rs

1use crate::{
2    abi::ethereum_types::BloomInput,
3    types::{Address, BlockNumber, Bloom, Log, H160, H256, U256, U64},
4    utils::keccak256,
5};
6use serde::{
7    de::{DeserializeOwned, MapAccess, Visitor},
8    ser::SerializeStruct,
9    Deserialize, Deserializer, Serialize, Serializer,
10};
11use std::ops::{Range, RangeFrom, RangeTo};
12
13pub type BloomFilter = Vec<Option<Bloom>>;
14
15/// A single topic
16pub type Topic = ValueOrArray<Option<H256>>;
17
18/// Represents the target range of blocks for the filter
19#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
20pub enum FilterBlockOption {
21    Range { from_block: Option<BlockNumber>, to_block: Option<BlockNumber> },
22    AtBlockHash(H256),
23}
24
25impl FilterBlockOption {
26    pub fn get_to_block(&self) -> Option<&BlockNumber> {
27        match self {
28            FilterBlockOption::Range { to_block, .. } => to_block.as_ref(),
29            FilterBlockOption::AtBlockHash(_) => None,
30        }
31    }
32
33    pub fn get_from_block(&self) -> Option<&BlockNumber> {
34        match self {
35            FilterBlockOption::Range { from_block, .. } => from_block.as_ref(),
36            FilterBlockOption::AtBlockHash(_) => None,
37        }
38    }
39}
40
41impl From<BlockNumber> for FilterBlockOption {
42    fn from(block: BlockNumber) -> Self {
43        let block = Some(block);
44        FilterBlockOption::Range { from_block: block, to_block: block }
45    }
46}
47
48impl From<U64> for FilterBlockOption {
49    fn from(block: U64) -> Self {
50        BlockNumber::from(block).into()
51    }
52}
53
54impl From<u64> for FilterBlockOption {
55    fn from(block: u64) -> Self {
56        BlockNumber::from(block).into()
57    }
58}
59
60impl<T: Into<BlockNumber>> From<Range<T>> for FilterBlockOption {
61    fn from(r: Range<T>) -> Self {
62        let from_block = Some(r.start.into());
63        let to_block = Some(r.end.into());
64        FilterBlockOption::Range { from_block, to_block }
65    }
66}
67
68impl<T: Into<BlockNumber>> From<RangeTo<T>> for FilterBlockOption {
69    fn from(r: RangeTo<T>) -> Self {
70        let to_block = Some(r.end.into());
71        FilterBlockOption::Range { from_block: Some(BlockNumber::Earliest), to_block }
72    }
73}
74
75impl<T: Into<BlockNumber>> From<RangeFrom<T>> for FilterBlockOption {
76    fn from(r: RangeFrom<T>) -> Self {
77        let from_block = Some(r.start.into());
78        FilterBlockOption::Range { from_block, to_block: Some(BlockNumber::Latest) }
79    }
80}
81
82impl From<H256> for FilterBlockOption {
83    fn from(hash: H256) -> Self {
84        FilterBlockOption::AtBlockHash(hash)
85    }
86}
87
88impl Default for FilterBlockOption {
89    fn default() -> Self {
90        FilterBlockOption::Range { from_block: None, to_block: None }
91    }
92}
93
94impl FilterBlockOption {
95    #[must_use]
96    pub fn set_from_block(&self, block: BlockNumber) -> Self {
97        let to_block =
98            if let FilterBlockOption::Range { to_block, .. } = self { *to_block } else { None };
99
100        FilterBlockOption::Range { from_block: Some(block), to_block }
101    }
102
103    #[must_use]
104    pub fn set_to_block(&self, block: BlockNumber) -> Self {
105        let from_block =
106            if let FilterBlockOption::Range { from_block, .. } = self { *from_block } else { None };
107
108        FilterBlockOption::Range { from_block, to_block: Some(block) }
109    }
110
111    #[must_use]
112    pub fn set_hash(&self, hash: H256) -> Self {
113        FilterBlockOption::AtBlockHash(hash)
114    }
115}
116
117/// Filter for
118#[derive(Default, Debug, PartialEq, Eq, Clone, Hash)]
119pub struct Filter {
120    /// Filter block options, specifying on which blocks the filter should
121    /// match.
122    // https://eips.ethereum.org/EIPS/eip-234
123    pub block_option: FilterBlockOption,
124
125    /// Address
126    pub address: Option<ValueOrArray<Address>>,
127
128    /// Topics
129    // TODO: We could improve the low level API here by using ethabi's RawTopicFilter
130    // and/or TopicFilter
131    pub topics: [Option<Topic>; 4],
132}
133
134impl Filter {
135    pub fn new() -> Self {
136        Self::default()
137    }
138
139    /// Sets the inner filter object
140    ///
141    /// *NOTE:* ranges are always inclusive
142    ///
143    /// # Examples
144    ///
145    /// Match only a specific block
146    ///
147    /// ```rust
148    /// # use ethers_core::types::Filter;
149    /// # fn main() {
150    /// let filter = Filter::new().select(69u64);
151    /// # }
152    /// ```
153    /// This is the same as `Filter::new().from_block(1337u64).to_block(1337u64)`
154    ///
155    /// Match the latest block only
156    ///
157    /// ```rust
158    /// # use ethers_core::types::{Filter, BlockNumber};
159    /// # fn main() {
160    /// let filter = Filter::new().select(BlockNumber::Latest);
161    /// # }
162    /// ```
163    ///
164    /// Match a block by its hash
165    ///
166    /// ```rust
167    /// # use ethers_core::types::{Filter, H256};
168    /// # fn main() {
169    /// let filter = Filter::new().select(H256::zero());
170    /// # }
171    /// ```
172    /// This is the same as `at_block_hash`
173    ///
174    /// Match a range of blocks
175    ///
176    /// ```rust
177    /// # use ethers_core::types::{Filter, H256};
178    /// # fn main() {
179    /// let filter = Filter::new().select(0u64..100u64);
180    /// # }
181    /// ```
182    ///
183    /// Match all blocks in range `(1337..BlockNumber::Latest)`
184    ///
185    /// ```rust
186    /// # use ethers_core::types::{Filter, H256};
187    /// # fn main() {
188    /// let filter = Filter::new().select(1337u64..);
189    /// # }
190    /// ```
191    ///
192    /// Match all blocks in range `(BlockNumber::Earliest..1337)`
193    ///
194    /// ```rust
195    /// # use ethers_core::types::{Filter, H256};
196    /// # fn main() {
197    /// let filter = Filter::new().select(..1337u64);
198    /// # }
199    /// ```
200    #[must_use]
201    pub fn select(mut self, filter: impl Into<FilterBlockOption>) -> Self {
202        self.block_option = filter.into();
203        self
204    }
205
206    #[allow(clippy::wrong_self_convention)]
207    #[must_use]
208    pub fn from_block<T: Into<BlockNumber>>(mut self, block: T) -> Self {
209        self.block_option = self.block_option.set_from_block(block.into());
210        self
211    }
212
213    #[allow(clippy::wrong_self_convention)]
214    #[must_use]
215    pub fn to_block<T: Into<BlockNumber>>(mut self, block: T) -> Self {
216        self.block_option = self.block_option.set_to_block(block.into());
217        self
218    }
219
220    #[allow(clippy::wrong_self_convention)]
221    #[must_use]
222    pub fn at_block_hash<T: Into<H256>>(mut self, hash: T) -> Self {
223        self.block_option = self.block_option.set_hash(hash.into());
224        self
225    }
226    /// Sets the inner filter object
227    ///
228    /// *NOTE:* ranges are always inclusive
229    ///
230    /// # Examples
231    ///
232    /// Match only a specific address `("0xAc4b3DacB91461209Ae9d41EC517c2B9Cb1B7DAF")`
233    ///
234    /// ```rust
235    /// # use ethers_core::types::{Filter, Address};
236    /// # fn main() {
237    /// let filter = Filter::new().address("0xAc4b3DacB91461209Ae9d41EC517c2B9Cb1B7DAF".parse::<Address>().unwrap());
238    /// # }
239    /// ```
240    ///
241    /// Match all addresses in array `(vec!["0xAc4b3DacB91461209Ae9d41EC517c2B9Cb1B7DAF",
242    /// "0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8"])`
243    ///
244    /// ```rust
245    /// # use ethers_core::types::{Filter, Address, ValueOrArray};
246    /// # fn main() {
247    /// let addresses = vec!["0xAc4b3DacB91461209Ae9d41EC517c2B9Cb1B7DAF".parse::<Address>().unwrap(),"0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8".parse::<Address>().unwrap()];
248    /// let filter = Filter::new().address(addresses);
249    /// # }
250    /// ```
251    #[must_use]
252    pub fn address<T: Into<ValueOrArray<Address>>>(mut self, address: T) -> Self {
253        self.address = Some(address.into());
254        self
255    }
256
257    /// Given the event signature in string form, it hashes it and adds it to the topics to monitor
258    #[must_use]
259    pub fn event(self, event_name: &str) -> Self {
260        let hash = H256::from(keccak256(event_name.as_bytes()));
261        self.topic0(hash)
262    }
263
264    /// Hashes all event signatures and sets them as array to topic0
265    #[must_use]
266    pub fn events(self, events: impl IntoIterator<Item = impl AsRef<[u8]>>) -> Self {
267        let events =
268            events.into_iter().map(|e| H256::from(keccak256(e.as_ref()))).collect::<Vec<_>>();
269        self.topic0(events)
270    }
271
272    /// Sets topic0 (the event name for non-anonymous events)
273    #[must_use]
274    pub fn topic0<T: Into<Topic>>(mut self, topic: T) -> Self {
275        self.topics[0] = Some(topic.into());
276        self
277    }
278
279    /// Sets the 1st indexed topic
280    #[must_use]
281    pub fn topic1<T: Into<Topic>>(mut self, topic: T) -> Self {
282        self.topics[1] = Some(topic.into());
283        self
284    }
285
286    /// Sets the 2nd indexed topic
287    #[must_use]
288    pub fn topic2<T: Into<Topic>>(mut self, topic: T) -> Self {
289        self.topics[2] = Some(topic.into());
290        self
291    }
292
293    /// Sets the 3rd indexed topic
294    #[must_use]
295    pub fn topic3<T: Into<Topic>>(mut self, topic: T) -> Self {
296        self.topics[3] = Some(topic.into());
297        self
298    }
299
300    pub fn is_paginatable(&self) -> bool {
301        self.get_from_block().is_some()
302    }
303
304    /// Returns the numeric value of the `toBlock` field
305    pub fn get_to_block(&self) -> Option<U64> {
306        self.block_option.get_to_block().and_then(|b| b.as_number())
307    }
308
309    /// Returns the numeric value of the `fromBlock` field
310    pub fn get_from_block(&self) -> Option<U64> {
311        self.block_option.get_from_block().and_then(|b| b.as_number())
312    }
313
314    /// Returns the numeric value of the `fromBlock` field
315    pub fn get_block_hash(&self) -> Option<H256> {
316        match self.block_option {
317            FilterBlockOption::AtBlockHash(hash) => Some(hash),
318            FilterBlockOption::Range { .. } => None,
319        }
320    }
321
322    /// Flattens the topics using the cartesian product
323    fn flatten(&self) -> Vec<ValueOrArray<Option<H256>>> {
324        fn cartesian(lists: &[Vec<Option<H256>>]) -> Vec<Vec<Option<H256>>> {
325            let mut res = Vec::new();
326            let mut list_iter = lists.iter();
327            if let Some(first_list) = list_iter.next() {
328                for &i in first_list {
329                    res.push(vec![i]);
330                }
331            }
332            for l in list_iter {
333                let mut tmp = Vec::new();
334                for r in res {
335                    for &el in l {
336                        let mut tmp_el = r.clone();
337                        tmp_el.push(el);
338                        tmp.push(tmp_el);
339                    }
340                }
341                res = tmp;
342            }
343            res
344        }
345        let mut out = Vec::new();
346        let mut tmp = Vec::new();
347        for v in self.topics.iter() {
348            let v = if let Some(v) = v {
349                match v {
350                    ValueOrArray::Value(s) => {
351                        vec![*s]
352                    }
353                    ValueOrArray::Array(s) => s.clone(),
354                }
355            } else {
356                vec![None]
357            };
358            tmp.push(v);
359        }
360        for v in cartesian(&tmp) {
361            out.push(ValueOrArray::Array(v));
362        }
363        out
364    }
365
366    /// Returns an iterator over all existing topics
367    pub fn topics(&self) -> impl Iterator<Item = &Topic> + '_ {
368        self.topics.iter().flatten()
369    }
370
371    /// Returns true if at least one topic is set
372    pub fn has_topics(&self) -> bool {
373        self.topics.iter().any(|t| t.is_some())
374    }
375}
376
377impl Serialize for Filter {
378    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
379    where
380        S: Serializer,
381    {
382        let mut s = serializer.serialize_struct("Filter", 5)?;
383        match self.block_option {
384            FilterBlockOption::Range { from_block, to_block } => {
385                if let Some(ref from_block) = from_block {
386                    s.serialize_field("fromBlock", from_block)?;
387                }
388
389                if let Some(ref to_block) = to_block {
390                    s.serialize_field("toBlock", to_block)?;
391                }
392            }
393
394            FilterBlockOption::AtBlockHash(ref h) => s.serialize_field("blockHash", h)?,
395        }
396
397        if let Some(ref address) = self.address {
398            s.serialize_field("address", address)?;
399        }
400
401        let mut filtered_topics = Vec::new();
402        for i in 0..4 {
403            if self.topics[i].is_some() {
404                filtered_topics.push(&self.topics[i]);
405            } else {
406                // TODO: This can be optimized
407                if self.topics[i + 1..].iter().any(|x| x.is_some()) {
408                    filtered_topics.push(&None);
409                }
410            }
411        }
412        s.serialize_field("topics", &filtered_topics)?;
413
414        s.end()
415    }
416}
417
418impl<'de> Deserialize<'de> for Filter {
419    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
420    where
421        D: Deserializer<'de>,
422    {
423        struct FilterVisitor;
424
425        impl<'de> Visitor<'de> for FilterVisitor {
426            type Value = Filter;
427
428            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
429                formatter.write_str("Filter object")
430            }
431
432            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
433            where
434                A: MapAccess<'de>,
435            {
436                let mut from_block: Option<Option<BlockNumber>> = None;
437                let mut to_block: Option<Option<BlockNumber>> = None;
438                let mut block_hash: Option<Option<H256>> = None;
439                let mut address: Option<Option<ValueOrArray<Address>>> = None;
440                let mut topics: Option<Option<Vec<Option<Topic>>>> = None;
441
442                while let Some(key) = map.next_key::<String>()? {
443                    match key.as_str() {
444                        "fromBlock" => {
445                            if from_block.is_some() {
446                                return Err(serde::de::Error::duplicate_field("fromBlock"))
447                            }
448                            if block_hash.is_some() {
449                                return Err(serde::de::Error::custom(
450                                    "fromBlock not allowed with blockHash",
451                                ))
452                            }
453                            from_block = Some(map.next_value()?)
454                        }
455                        "toBlock" => {
456                            if to_block.is_some() {
457                                return Err(serde::de::Error::duplicate_field("toBlock"))
458                            }
459                            if block_hash.is_some() {
460                                return Err(serde::de::Error::custom(
461                                    "toBlock not allowed with blockHash",
462                                ))
463                            }
464                            to_block = Some(map.next_value()?)
465                        }
466                        "blockHash" => {
467                            if block_hash.is_some() {
468                                return Err(serde::de::Error::duplicate_field("blockHash"))
469                            }
470                            if from_block.is_some() || to_block.is_some() {
471                                return Err(serde::de::Error::custom(
472                                    "fromBlock,toBlock not allowed with blockHash",
473                                ))
474                            }
475                            block_hash = Some(map.next_value()?)
476                        }
477                        "address" => {
478                            if address.is_some() {
479                                return Err(serde::de::Error::duplicate_field("address"))
480                            }
481                            address = Some(map.next_value()?)
482                        }
483                        "topics" => {
484                            if topics.is_some() {
485                                return Err(serde::de::Error::duplicate_field("topics"))
486                            }
487                            topics = Some(map.next_value()?)
488                        }
489
490                        key => {
491                            return Err(serde::de::Error::unknown_field(
492                                key,
493                                &["fromBlock", "toBlock", "address", "topics", "blockHash"],
494                            ))
495                        }
496                    }
497                }
498
499                let from_block = from_block.unwrap_or_default();
500                let to_block = to_block.unwrap_or_default();
501                let block_hash = block_hash.unwrap_or_default();
502                let address = address.unwrap_or_default();
503                let topics_vec = topics.flatten().unwrap_or_default();
504
505                // maximum allowed filter len
506                if topics_vec.len() > 4 {
507                    return Err(serde::de::Error::custom("exceeded maximum topics len"))
508                }
509                let mut topics: [Option<Topic>; 4] = [None, None, None, None];
510                for (idx, topic) in topics_vec.into_iter().enumerate() {
511                    topics[idx] = topic;
512                }
513
514                let block_option = if let Some(block_hash) = block_hash {
515                    FilterBlockOption::AtBlockHash(block_hash)
516                } else {
517                    FilterBlockOption::Range { from_block, to_block }
518                };
519
520                Ok(Filter { block_option, address, topics })
521            }
522        }
523
524        deserializer.deserialize_any(FilterVisitor)
525    }
526}
527
528/// Union type for representing a single value or a vector of values inside a filter
529#[derive(Debug, PartialEq, Eq, Clone, Hash)]
530pub enum ValueOrArray<T> {
531    /// A single value
532    Value(T),
533    /// A vector of values
534    Array(Vec<T>),
535}
536
537impl From<H160> for ValueOrArray<H160> {
538    fn from(src: H160) -> Self {
539        ValueOrArray::Value(src)
540    }
541}
542
543impl From<Vec<H160>> for ValueOrArray<H160> {
544    fn from(src: Vec<H160>) -> Self {
545        ValueOrArray::Array(src)
546    }
547}
548
549impl From<H256> for Topic {
550    fn from(src: H256) -> Self {
551        ValueOrArray::Value(Some(src))
552    }
553}
554
555impl From<Vec<H256>> for ValueOrArray<H256> {
556    fn from(src: Vec<H256>) -> Self {
557        ValueOrArray::Array(src)
558    }
559}
560
561impl From<ValueOrArray<H256>> for Topic {
562    fn from(src: ValueOrArray<H256>) -> Self {
563        match src {
564            ValueOrArray::Value(val) => ValueOrArray::Value(Some(val)),
565            ValueOrArray::Array(arr) => arr.into(),
566        }
567    }
568}
569
570impl<I: Into<H256>> From<Vec<I>> for Topic {
571    fn from(src: Vec<I>) -> Self {
572        ValueOrArray::Array(src.into_iter().map(Into::into).map(Some).collect())
573    }
574}
575
576impl From<Address> for Topic {
577    fn from(src: Address) -> Self {
578        let mut bytes = [0; 32];
579        bytes[12..32].copy_from_slice(src.as_bytes());
580        ValueOrArray::Value(Some(H256::from(bytes)))
581    }
582}
583
584impl From<U256> for Topic {
585    fn from(src: U256) -> Self {
586        let mut bytes = [0; 32];
587        src.to_big_endian(&mut bytes);
588        ValueOrArray::Value(Some(H256::from(bytes)))
589    }
590}
591
592impl<T> Serialize for ValueOrArray<T>
593where
594    T: Serialize,
595{
596    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
597    where
598        S: Serializer,
599    {
600        match self {
601            ValueOrArray::Value(inner) => inner.serialize(serializer),
602            ValueOrArray::Array(inner) => inner.serialize(serializer),
603        }
604    }
605}
606
607impl<'a, T> Deserialize<'a> for ValueOrArray<T>
608where
609    T: DeserializeOwned,
610{
611    fn deserialize<D>(deserializer: D) -> Result<ValueOrArray<T>, D::Error>
612    where
613        D: Deserializer<'a>,
614    {
615        let value = serde_json::Value::deserialize(deserializer)?;
616
617        if value.is_null() {
618            return Ok(ValueOrArray::Array(Vec::new()))
619        }
620
621        #[derive(Deserialize)]
622        #[serde(untagged)]
623        enum Variadic<T> {
624            Value(T),
625            Array(Vec<T>),
626        }
627
628        match serde_json::from_value::<Variadic<T>>(value).map_err(|err| {
629            serde::de::Error::custom(format!("Invalid variadic value or array type: {err}"))
630        })? {
631            Variadic::Value(val) => Ok(ValueOrArray::Value(val)),
632            Variadic::Array(arr) => Ok(ValueOrArray::Array(arr)),
633        }
634    }
635}
636
637/// Support for matching [Filter]s
638#[derive(Debug, Default)]
639pub struct FilteredParams {
640    pub filter: Option<Filter>,
641    pub flat_topics: Vec<ValueOrArray<Option<H256>>>,
642}
643
644impl FilteredParams {
645    pub fn new(filter: Option<Filter>) -> Self {
646        if let Some(filter) = filter {
647            let flat_topics = filter.flatten();
648            FilteredParams { filter: Some(filter), flat_topics }
649        } else {
650            Default::default()
651        }
652    }
653
654    /// Returns the [BloomFilter] for the given address
655    pub fn address_filter(address: &Option<ValueOrArray<Address>>) -> BloomFilter {
656        address.as_ref().map(address_to_bloom_filter).unwrap_or_default()
657    }
658
659    /// Returns the [BloomFilter] for the given topics
660    pub fn topics_filter(topics: &Option<Vec<ValueOrArray<Option<H256>>>>) -> Vec<BloomFilter> {
661        let mut output = Vec::new();
662        if let Some(topics) = topics {
663            output.extend(topics.iter().map(topics_to_bloom_filter));
664        }
665        output
666    }
667
668    /// Returns `true` if the bloom matches the topics
669    pub fn matches_topics(bloom: Bloom, topic_filters: &[BloomFilter]) -> bool {
670        if topic_filters.is_empty() {
671            return true
672        }
673
674        // returns true if a filter matches
675        for filter in topic_filters.iter() {
676            let mut is_match = false;
677            for maybe_bloom in filter {
678                is_match = maybe_bloom.as_ref().map(|b| bloom.contains_bloom(b)).unwrap_or(true);
679                if !is_match {
680                    break
681                }
682            }
683            if is_match {
684                return true
685            }
686        }
687        false
688    }
689
690    /// Returns `true` if the bloom contains the address
691    pub fn matches_address(bloom: Bloom, address_filter: &BloomFilter) -> bool {
692        if address_filter.is_empty() {
693            return true
694        } else {
695            for maybe_bloom in address_filter {
696                if maybe_bloom.as_ref().map(|b| bloom.contains_bloom(b)).unwrap_or(true) {
697                    return true
698                }
699            }
700        }
701        false
702    }
703
704    /// Replace None values - aka wildcards - for the log input value in that position.
705    pub fn replace(&self, log: &Log, topic: Topic) -> Option<Vec<H256>> {
706        let mut out: Vec<H256> = Vec::new();
707        match topic {
708            ValueOrArray::Value(value) => {
709                if let Some(value) = value {
710                    out.push(value);
711                }
712            }
713            ValueOrArray::Array(value) => {
714                for (k, v) in value.into_iter().enumerate() {
715                    if let Some(v) = v {
716                        out.push(v);
717                    } else {
718                        out.push(log.topics[k]);
719                    }
720                }
721            }
722        };
723        if out.is_empty() {
724            return None
725        }
726        Some(out)
727    }
728
729    pub fn filter_block_range(&self, block_number: u64) -> bool {
730        if self.filter.is_none() {
731            return true
732        }
733        let filter = self.filter.as_ref().unwrap();
734        let mut res = true;
735
736        if let Some(BlockNumber::Number(num)) = filter.block_option.get_from_block() {
737            if num.as_u64() > block_number {
738                res = false;
739            }
740        }
741
742        if let Some(to) = filter.block_option.get_to_block() {
743            match to {
744                BlockNumber::Number(num) => {
745                    if num.as_u64() < block_number {
746                        res = false;
747                    }
748                }
749                BlockNumber::Earliest => {
750                    res = false;
751                }
752                _ => {}
753            }
754        }
755        res
756    }
757
758    pub fn filter_block_hash(&self, block_hash: H256) -> bool {
759        if let Some(h) = self.filter.as_ref().and_then(|f| f.get_block_hash()) {
760            if h != block_hash {
761                return false
762            }
763        }
764        true
765    }
766
767    pub fn filter_address(&self, log: &Log) -> bool {
768        if let Some(input_address) = &self.filter.as_ref().and_then(|f| f.address.clone()) {
769            match input_address {
770                ValueOrArray::Value(x) => {
771                    if log.address != *x {
772                        return false
773                    }
774                }
775                ValueOrArray::Array(x) => {
776                    if x.is_empty() {
777                        return true
778                    }
779                    if !x.contains(&log.address) {
780                        return false
781                    }
782                }
783            }
784        }
785        true
786    }
787
788    pub fn filter_topics(&self, log: &Log) -> bool {
789        let mut out: bool = true;
790        for topic in self.flat_topics.iter().cloned() {
791            match topic {
792                ValueOrArray::Value(single) => {
793                    if let Some(single) = single {
794                        if !log.topics.starts_with(&[single]) {
795                            out = false;
796                        }
797                    }
798                }
799                ValueOrArray::Array(multi) => {
800                    if multi.is_empty() {
801                        out = true;
802                        continue
803                    }
804                    // Shrink the topics until the last item is Some.
805                    let mut new_multi = multi;
806                    while new_multi.iter().last().unwrap_or(&Some(H256::default())).is_none() {
807                        new_multi.pop();
808                    }
809                    // We can discard right away any logs with lesser topics than the filter.
810                    if new_multi.len() > log.topics.len() {
811                        out = false;
812                        break
813                    }
814                    let replaced: Option<Vec<H256>> =
815                        self.replace(log, ValueOrArray::Array(new_multi));
816                    if let Some(replaced) = replaced {
817                        out = false;
818                        if log.topics.starts_with(&replaced[..]) {
819                            out = true;
820                            break
821                        }
822                    }
823                }
824            }
825        }
826        out
827    }
828}
829
830fn topics_to_bloom_filter(topics: &ValueOrArray<Option<H256>>) -> BloomFilter {
831    let mut blooms = BloomFilter::new();
832    match topics {
833        ValueOrArray::Value(topic) => {
834            if let Some(topic) = topic {
835                let bloom: Bloom = BloomInput::Raw(topic.as_ref()).into();
836                blooms.push(Some(bloom));
837            } else {
838                blooms.push(None);
839            }
840        }
841        ValueOrArray::Array(topics) => {
842            if topics.is_empty() {
843                blooms.push(None);
844            } else {
845                for topic in topics.iter() {
846                    if let Some(topic) = topic {
847                        let bloom: Bloom = BloomInput::Raw(topic.as_ref()).into();
848                        blooms.push(Some(bloom));
849                    } else {
850                        blooms.push(None);
851                    }
852                }
853            }
854        }
855    }
856    blooms
857}
858
859fn address_to_bloom_filter(address: &ValueOrArray<Address>) -> BloomFilter {
860    let mut blooms = BloomFilter::new();
861    match address {
862        ValueOrArray::Value(address) => {
863            let bloom: Bloom = BloomInput::Raw(address.as_ref()).into();
864            blooms.push(Some(bloom))
865        }
866        ValueOrArray::Array(addresses) => {
867            if addresses.is_empty() {
868                blooms.push(None);
869            } else {
870                for address in addresses.iter() {
871                    let bloom: Bloom = BloomInput::Raw(address.as_ref()).into();
872                    blooms.push(Some(bloom));
873                }
874            }
875        }
876    }
877    blooms
878}
879
880#[cfg(test)]
881mod tests {
882    use super::*;
883    use crate::utils::serialize;
884    use serde_json::json;
885
886    #[test]
887    fn can_serde_value_or_array() {
888        #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
889        struct Item {
890            value: ValueOrArray<U256>,
891        }
892
893        let item = Item { value: ValueOrArray::Value(U256::one()) };
894        let json = serde_json::to_value(item.clone()).unwrap();
895        let deserialized: Item = serde_json::from_value(json).unwrap();
896        assert_eq!(item, deserialized);
897
898        let item = Item { value: ValueOrArray::Array(vec![U256::one(), U256::zero()]) };
899        let json = serde_json::to_value(item.clone()).unwrap();
900        let deserialized: Item = serde_json::from_value(json).unwrap();
901        assert_eq!(item, deserialized);
902    }
903
904    #[test]
905    fn filter_serialization_test() {
906        let t1 = "9729a6fbefefc8f6005933898b13dc45c3a2c8b7".parse::<Address>().unwrap();
907        let t2 = H256::from([0; 32]);
908        let t3 = U256::from(123);
909
910        let t1_padded = H256::from(t1);
911        let t3_padded = H256::from({
912            let mut x = [0; 32];
913            x[31] = 123;
914            x
915        });
916
917        let event = "ValueChanged(address,string,string)";
918        let t0 = H256::from(keccak256(event.as_bytes()));
919        let addr: Address = "f817796F60D268A36a57b8D2dF1B97B14C0D0E1d".parse().unwrap();
920        let filter = Filter::new();
921
922        let ser = serialize(&filter);
923        assert_eq!(ser, json!({ "topics": [] }));
924
925        let filter = filter.address(ValueOrArray::Value(addr));
926
927        let ser = serialize(&filter);
928        assert_eq!(ser, json!({"address" : addr, "topics": []}));
929
930        let filter = filter.event(event);
931
932        // 0
933        let ser = serialize(&filter);
934        assert_eq!(ser, json!({ "address" : addr, "topics": [t0]}));
935
936        // 1
937        let ser = serialize(&filter.clone().topic1(t1));
938        assert_eq!(ser, json!({ "address" : addr, "topics": [t0, t1_padded]}));
939
940        // 2
941        let ser = serialize(&filter.clone().topic2(t2));
942        assert_eq!(ser, json!({ "address" : addr, "topics": [t0, null, t2]}));
943
944        // 3
945        let ser = serialize(&filter.clone().topic3(t3));
946        assert_eq!(ser, json!({ "address" : addr, "topics": [t0, null, null, t3_padded]}));
947
948        // 1 & 2
949        let ser = serialize(&filter.clone().topic1(t1).topic2(t2));
950        assert_eq!(ser, json!({ "address" : addr, "topics": [t0, t1_padded, t2]}));
951
952        // 1 & 3
953        let ser = serialize(&filter.clone().topic1(t1).topic3(t3));
954        assert_eq!(ser, json!({ "address" : addr, "topics": [t0, t1_padded, null, t3_padded]}));
955
956        // 2 & 3
957        let ser = serialize(&filter.clone().topic2(t2).topic3(t3));
958        assert_eq!(ser, json!({ "address" : addr, "topics": [t0, null, t2, t3_padded]}));
959
960        // 1 & 2 & 3
961        let ser = serialize(&filter.topic1(t1).topic2(t2).topic3(t3));
962        assert_eq!(ser, json!({ "address" : addr, "topics": [t0, t1_padded, t2, t3_padded]}));
963    }
964
965    fn build_bloom(address: Address, topic1: H256, topic2: H256) -> Bloom {
966        let mut block_bloom = Bloom::default();
967        block_bloom.accrue(BloomInput::Raw(&address[..]));
968        block_bloom.accrue(BloomInput::Raw(&topic1[..]));
969        block_bloom.accrue(BloomInput::Raw(&topic2[..]));
970        block_bloom
971    }
972
973    fn topic_filter(
974        topic1: H256,
975        topic2: H256,
976        topic3: H256,
977    ) -> (Filter, Option<Vec<ValueOrArray<Option<H256>>>>) {
978        let filter = Filter {
979            block_option: Default::default(),
980            address: None,
981            topics: [
982                Some(ValueOrArray::Value(Some(topic1))),
983                Some(ValueOrArray::Array(vec![Some(topic2), Some(topic3)])),
984                None,
985                None,
986            ],
987        };
988        let filtered_params = FilteredParams::new(Some(filter.clone()));
989
990        (filter, Some(filtered_params.flat_topics))
991    }
992
993    #[test]
994    fn can_detect_different_topics() {
995        let topic1 = H256::random();
996        let topic2 = H256::random();
997        let topic3 = H256::random();
998
999        let (_, topics) = topic_filter(topic1, topic2, topic3);
1000        let topics_bloom = FilteredParams::topics_filter(&topics);
1001        assert!(!FilteredParams::matches_topics(
1002            build_bloom(Address::random(), H256::random(), H256::random()),
1003            &topics_bloom
1004        ));
1005    }
1006
1007    #[test]
1008    fn can_match_topic() {
1009        let topic1 = H256::random();
1010        let topic2 = H256::random();
1011        let topic3 = H256::random();
1012
1013        let (_, topics) = topic_filter(topic1, topic2, topic3);
1014        let _topics_bloom = FilteredParams::topics_filter(&topics);
1015
1016        let topics_bloom = FilteredParams::topics_filter(&topics);
1017        assert!(FilteredParams::matches_topics(
1018            build_bloom(Address::random(), topic1, topic2),
1019            &topics_bloom
1020        ));
1021    }
1022
1023    #[test]
1024    fn can_match_empty_topics() {
1025        let filter =
1026            Filter { block_option: Default::default(), address: None, topics: Default::default() };
1027
1028        let filtered_params = FilteredParams::new(Some(filter));
1029        let topics = Some(filtered_params.flat_topics);
1030
1031        let topics_bloom = FilteredParams::topics_filter(&topics);
1032        assert!(FilteredParams::matches_topics(
1033            build_bloom(Address::random(), H256::random(), H256::random()),
1034            &topics_bloom
1035        ));
1036    }
1037
1038    #[test]
1039    fn can_match_address_and_topics() {
1040        let rng_address = Address::random();
1041        let topic1 = H256::random();
1042        let topic2 = H256::random();
1043        let topic3 = H256::random();
1044
1045        let filter = Filter {
1046            block_option: Default::default(),
1047            address: Some(ValueOrArray::Value(rng_address)),
1048            topics: [
1049                Some(ValueOrArray::Value(Some(topic1))),
1050                Some(ValueOrArray::Array(vec![Some(topic2), Some(topic3)])),
1051                None,
1052                None,
1053            ],
1054        };
1055        let filtered_params = FilteredParams::new(Some(filter.clone()));
1056        let topics = Some(filtered_params.flat_topics);
1057        let address_filter = FilteredParams::address_filter(&filter.address);
1058        let topics_filter = FilteredParams::topics_filter(&topics);
1059        assert!(
1060            FilteredParams::matches_address(
1061                build_bloom(rng_address, topic1, topic2),
1062                &address_filter
1063            ) && FilteredParams::matches_topics(
1064                build_bloom(rng_address, topic1, topic2),
1065                &topics_filter
1066            )
1067        );
1068    }
1069
1070    #[test]
1071    fn can_match_topics_wildcard() {
1072        let topic1 = H256::random();
1073        let topic2 = H256::random();
1074        let topic3 = H256::random();
1075
1076        let filter = Filter {
1077            block_option: Default::default(),
1078            address: None,
1079            topics: [None, Some(ValueOrArray::Array(vec![Some(topic2), Some(topic3)])), None, None],
1080        };
1081        let filtered_params = FilteredParams::new(Some(filter));
1082        let topics = Some(filtered_params.flat_topics);
1083        let topics_bloom = FilteredParams::topics_filter(&topics);
1084        assert!(FilteredParams::matches_topics(
1085            build_bloom(Address::random(), topic1, topic2),
1086            &topics_bloom
1087        ));
1088    }
1089
1090    #[test]
1091    fn can_match_topics_wildcard_mismatch() {
1092        let filter = Filter {
1093            block_option: Default::default(),
1094            address: None,
1095            topics: [
1096                None,
1097                Some(ValueOrArray::Array(vec![Some(H256::random()), Some(H256::random())])),
1098                None,
1099                None,
1100            ],
1101        };
1102        let filtered_params = FilteredParams::new(Some(filter));
1103        let topics_input = Some(filtered_params.flat_topics);
1104        let topics_bloom = FilteredParams::topics_filter(&topics_input);
1105        assert!(!FilteredParams::matches_topics(
1106            build_bloom(Address::random(), H256::random(), H256::random()),
1107            &topics_bloom
1108        ));
1109    }
1110
1111    #[test]
1112    fn can_match_address_filter() {
1113        let rng_address = Address::random();
1114        let filter = Filter {
1115            block_option: Default::default(),
1116            address: Some(ValueOrArray::Value(rng_address)),
1117            topics: Default::default(),
1118        };
1119        let address_bloom = FilteredParams::address_filter(&filter.address);
1120        assert!(FilteredParams::matches_address(
1121            build_bloom(rng_address, H256::random(), H256::random(),),
1122            &address_bloom
1123        ));
1124    }
1125
1126    #[test]
1127    fn can_detect_different_address() {
1128        let bloom_address = Address::random();
1129        let rng_address = Address::random();
1130        let filter = Filter {
1131            block_option: Default::default(),
1132            address: Some(ValueOrArray::Value(rng_address)),
1133            topics: Default::default(),
1134        };
1135        let address_bloom = FilteredParams::address_filter(&filter.address);
1136        assert!(!FilteredParams::matches_address(
1137            build_bloom(bloom_address, H256::random(), H256::random(),),
1138            &address_bloom
1139        ));
1140    }
1141
1142    #[test]
1143    fn can_convert_to_ethers_filter() {
1144        let json = json!(
1145                    {
1146          "fromBlock": "0x429d3b",
1147          "toBlock": "0x429d3b",
1148          "address": "0xb59f67a8bff5d8cd03f6ac17265c550ed8f33907",
1149          "topics": [
1150          "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
1151          "0x00000000000000000000000000b46c2526e227482e2ebb8f4c69e4674d262e75",
1152          "0x00000000000000000000000054a2d42a40f51259dedd1978f6c118a0f0eff078"
1153          ]
1154        }
1155            );
1156
1157        let filter: Filter = serde_json::from_value(json).unwrap();
1158        assert_eq!(
1159            filter,
1160            Filter {
1161                block_option: FilterBlockOption::Range {
1162                    from_block: Some(4365627u64.into()),
1163                    to_block: Some(4365627u64.into()),
1164                },
1165                address: Some(ValueOrArray::Value(
1166                    "0xb59f67a8bff5d8cd03f6ac17265c550ed8f33907".parse().unwrap()
1167                )),
1168                topics: [
1169                    Some(ValueOrArray::Value(Some(
1170                        "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
1171                            .parse()
1172                            .unwrap(),
1173                    ))),
1174                    Some(ValueOrArray::Value(Some(
1175                        "0x00000000000000000000000000b46c2526e227482e2ebb8f4c69e4674d262e75"
1176                            .parse()
1177                            .unwrap(),
1178                    ))),
1179                    Some(ValueOrArray::Value(Some(
1180                        "0x00000000000000000000000054a2d42a40f51259dedd1978f6c118a0f0eff078"
1181                            .parse()
1182                            .unwrap(),
1183                    ))),
1184                    None,
1185                ],
1186            }
1187        );
1188    }
1189
1190    #[test]
1191    fn can_convert_to_ethers_filter_with_null_fields() {
1192        let json = json!(
1193                    {
1194          "fromBlock": "0x429d3b",
1195          "toBlock": "0x429d3b",
1196          "address": null,
1197          "topics": null
1198        }
1199            );
1200
1201        let filter: Filter = serde_json::from_value(json).unwrap();
1202        assert_eq!(
1203            filter,
1204            Filter {
1205                block_option: FilterBlockOption::Range {
1206                    from_block: Some(4365627u64.into()),
1207                    to_block: Some(4365627u64.into()),
1208                },
1209                address: None,
1210                topics: [None, None, None, None,],
1211            }
1212        );
1213    }
1214}