mwc_bch/messages/
filter_load.rs

1use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
2use messages::message::Payload;
3use std::io;
4use std::io::{Read, Write};
5use util::{var_int, BloomFilter, Result, Serializable};
6
7/// Filter is not adjusted when a match is found
8pub const BLOOM_UPDATE_NONE: u8 = 0;
9/// Filter is updated to include the serialized outpoint if any data elements matched in its script pubkey
10pub const BLOOM_UPDATE_ALL: u8 = 1;
11/// Filter is updated simialr to BLOOM_UPDATE_ALL but only for P2PK or multisig transactions
12pub const BLOOM_UPDATE_P2PUBKEY_ONLY: u8 = 2;
13
14/// Loads a bloom filter using the specified parameters
15#[derive(Default, Debug, PartialEq, Eq, Hash, Clone)]
16pub struct FilterLoad {
17    /// Bloom filter
18    pub bloom_filter: BloomFilter,
19    /// Flags that control how matched items are added to the filter
20    pub flags: u8,
21}
22
23impl FilterLoad {
24    /// Returns whether the FilterLoad message is valid
25    pub fn validate(&self) -> Result<()> {
26        self.bloom_filter.validate()
27    }
28}
29
30impl Serializable<FilterLoad> for FilterLoad {
31    fn read(reader: &mut dyn Read) -> Result<FilterLoad> {
32        let num_filters = var_int::read(reader)?;
33        let mut filter = vec![0; num_filters as usize];
34        reader.read(&mut filter)?;
35        let num_hash_funcs = reader.read_u32::<LittleEndian>()? as usize;
36        let tweak = reader.read_u32::<LittleEndian>()?;
37        let flags = reader.read_u8()?;
38        Ok(FilterLoad {
39            bloom_filter: BloomFilter {
40                filter,
41                num_hash_funcs,
42                tweak,
43            },
44            flags,
45        })
46    }
47
48    fn write(&self, writer: &mut dyn Write) -> io::Result<()> {
49        var_int::write(self.bloom_filter.filter.len() as u64, writer)?;
50        writer.write(&self.bloom_filter.filter)?;
51        writer.write_u32::<LittleEndian>(self.bloom_filter.num_hash_funcs as u32)?;
52        writer.write_u32::<LittleEndian>(self.bloom_filter.tweak)?;
53        writer.write_u8(self.flags)?;
54        Ok(())
55    }
56}
57
58impl Payload<FilterLoad> for FilterLoad {
59    fn size(&self) -> usize {
60        var_int::size(self.bloom_filter.filter.len() as u64) + self.bloom_filter.filter.len() + 9
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67    use hex;
68    use std::io::Cursor;
69
70    #[test]
71    fn read_bytes() {
72        let b = hex::decode("02b50f0b0000000000000001".as_bytes()).unwrap();
73        let f = FilterLoad::read(&mut Cursor::new(&b)).unwrap();
74        assert!(f.bloom_filter.filter == vec![0xb5, 0x0f]);
75        assert!(f.bloom_filter.num_hash_funcs == 11);
76        assert!(f.bloom_filter.tweak == 0);
77        assert!(f.flags == BLOOM_UPDATE_ALL);
78    }
79
80    #[test]
81    fn write_read() {
82        let mut v = Vec::new();
83        let p = FilterLoad {
84            bloom_filter: BloomFilter {
85                filter: vec![0, 1, 2, 3, 4, 5],
86                num_hash_funcs: 3,
87                tweak: 100,
88            },
89            flags: 1,
90        };
91        p.write(&mut v).unwrap();
92        assert!(v.len() == p.size());
93        assert!(FilterLoad::read(&mut Cursor::new(&v)).unwrap() == p);
94    }
95}