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
crate::ix!();
    
pub trait ProcessGetCfCheckPt {

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

impl ProcessGetCfCheckPt for PeerManager {

    /**
      | Handle a getcfcheckpt 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_check_pt(self: Arc<Self>, 
        mut peer: &mut AmoWriteGuard<Box<dyn NodeInterface>>,
        recv:     &mut DataStream)  {

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

        recv.stream_into(&mut filter_type_ser);
        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::<BlockFilterIndex>::none();

        if !self.clone().prepare_block_filter_request(
            &mut peer,
            filter_type,
            /*start_height=*/ 0,
            &stop_hash,
            /*max_height_diff=*/ u32::MAX,
            &mut stop_index,
            &mut filter_index) 
        {
            return;
        }

        let mut headers: Vec::<u256> 
        = Vec::<u256>::with_capacity(
            usize::try_from(stop_index.as_ref().unwrap().n_height / CFCHECKPT_INTERVAL).unwrap()
        );

        //  Populate headers.
        let mut block_index: Option<Arc<BlockIndex>> = stop_index.clone();

        for i in (0..=headers.len() - 1).rev() {

            let height: i32 = ((i + 1) * usize::try_from(CFCHECKPT_INTERVAL).unwrap()).try_into().unwrap();

            block_index = match block_index {
                Some(index) => index.get_ancestor(height),
                None        => None,
            };

            if !filter_index.get_mut().lookup_filter_header(
                block_index.clone(), 
                &mut headers[i]
            ) {

                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), 
                    (*block_index).get_block_hash().to_string()
                );

                return;
            }
        }

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

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