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
crate::ix!();

pub trait ProcessGetCfHeaders {

    fn process_get_cf_headers(self: Arc<Self>, 
        peer: &mut AmoWriteGuard<Box<dyn NodeInterface>>,
        recv: &mut DataStream);
}

impl ProcessGetCfHeaders for PeerManager {

    /**
      | Handle a cfheaders request.
      | 
      | May disconnect from the peer in the case
      | of a bad request.
      | 
      | -----------
      | @param[in] peer
      | 
      | The peer that we received the request
      | from
      | ----------
      | @param[in] vRecv
      | 
      | The raw message received
      |
      */
    fn process_get_cf_headers(
        self:     Arc<Self>, 
        mut peer: &mut AmoWriteGuard<Box<dyn NodeInterface>>,
        recv:     &mut DataStream)  {

        let mut filter_type_ser = u8::default();
        let mut start_height    = u32::default();
        let mut stop_hash       = u256::default();

        recv.stream_into(&mut filter_type_ser);
        recv.stream_into(&mut start_height);
        recv.stream_into(&mut stop_hash);

        let filter_type = BlockFilterType::from(filter_type_ser);
        
        let mut stop_index:   Option<Arc<BlockIndex>> = None;
        let mut filter_index: Amo<BlockFilterIndex>   = amo_none();

        if !self.clone().prepare_block_filter_request(
            &mut peer,
            filter_type,
            start_height,
            &stop_hash,
            MAX_GETCFHEADERS_SIZE,
            &mut stop_index,
            &mut filter_index) 
        {
            return;
        }

        let mut prev_header = u256::default();

        if start_height > 0 {

            let prev_block: Option<Arc<BlockIndex>> 
            = stop_index
                .as_ref()
                .unwrap()
                .clone()
                .get_ancestor(start_height as i32 - 1);

            if !filter_index.get_mut().lookup_filter_header(prev_block, &mut prev_header) {

                log_print!(
                    LogFlags::NET, 
                    "Failed to find block filter header in index: filter_type=%s, block_hash=%s\n", 
                    block_filter_type_name(filter_type), 
                    (*prev_block).get_block_hash().to_string()
                );

                return;
            }
        }

        let mut filter_hashes: Vec<u256> = vec![];

        if !filter_index.get().lookup_filter_hash_range(
            start_height.try_into().unwrap(), 
            stop_index.clone(), 
            &mut filter_hashes) 
        {
            log_print!(
                LogFlags::NET, 
                "Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n", 
                block_filter_type_name(filter_type), 
                start_height, 
                stop_hash.to_string()
            );

            return;
        }

        let msg: SerializedNetMsg = 
        NetMsgMaker::new(peer.get_common_version())
            .make(
                NetMsgType::CFHEADERS, 
                &[
                    &filter_type_ser, 
                    &stop_index.as_ref().unwrap().get_block_hash(), 
                    &prev_header, 
                    &filter_hashes
                ]
            );

        self.connman.get_mut().push_message(&mut *peer, msg /* move */);
    }
}