cfxcore/sync/message/
get_compact_blocks.rs1use crate::{
6 message::RequestId,
7 sync::{
8 message::{
9 msgid, Context, GetBlocks, GetCompactBlocksResponse, Handleable,
10 Key, KeyContainer,
11 },
12 request_manager::{AsAny, Request},
13 Error, ProtocolConfiguration,
14 },
15};
16use cfx_parameters::sync::{MAX_BLOCKS_TO_SEND, MAX_HEADERS_TO_SEND};
17use cfx_types::H256;
18use malloc_size_of_derive::MallocSizeOf as DeriveMallocSizeOf;
19use rlp_derive::{RlpDecodable, RlpEncodable};
20use std::{any::Any, time::Duration};
21
22#[derive(
23 Debug, PartialEq, Default, RlpDecodable, RlpEncodable, DeriveMallocSizeOf,
24)]
25pub struct GetCompactBlocks {
26 pub request_id: RequestId,
27 pub hashes: Vec<H256>,
28}
29
30impl AsAny for GetCompactBlocks {
31 fn as_any(&self) -> &dyn Any { self }
32
33 fn as_any_mut(&mut self) -> &mut dyn Any { self }
34}
35
36impl Request for GetCompactBlocks {
37 fn timeout(&self, conf: &ProtocolConfiguration) -> Duration {
38 conf.blocks_request_timeout
39 }
40
41 fn on_removed(&self, inflight_keys: &KeyContainer) {
42 let mut inflight_blocks = inflight_keys.write(msgid::GET_BLOCKS);
43 let mut net_inflight_blocks =
44 inflight_keys.write(msgid::NET_INFLIGHT_BLOCKS);
45 for hash in self.hashes.iter() {
46 inflight_blocks.remove(&Key::Hash(*hash));
47 net_inflight_blocks.remove(&Key::Hash(*hash));
48 }
49 }
50
51 fn with_inflight(&mut self, inflight_keys: &KeyContainer) {
52 let mut inflight_keys = inflight_keys.write(msgid::GET_BLOCKS);
53 self.hashes.retain(|h| inflight_keys.insert(Key::Hash(*h)));
54 }
55
56 fn is_empty(&self) -> bool { self.hashes.is_empty() }
57
58 fn resend(&self) -> Option<Box<dyn Request>> {
59 Some(Box::new(GetBlocks {
60 request_id: 0,
61 with_public: true,
62 hashes: self.hashes.iter().cloned().collect(),
63 preferred_node_type: None,
64 }))
65 }
66}
67
68impl Handleable for GetCompactBlocks {
69 fn handle(self, ctx: &Context) -> Result<(), Error> {
70 let mut compact_blocks = Vec::with_capacity(self.hashes.len());
71 let mut blocks = Vec::new();
72
73 for hash in self.hashes.iter() {
74 if let Some(compact_block) =
75 ctx.manager.graph.data_man.compact_block_by_hash(hash)
76 {
77 if (compact_blocks.len() as u64) < MAX_HEADERS_TO_SEND {
78 compact_blocks.push(compact_block);
79 }
80 } else if let Some(block) = ctx.manager.graph.block_by_hash(hash) {
81 debug!("Have complete block but no compact block, return complete block instead");
82 if (blocks.len() as u64) < MAX_BLOCKS_TO_SEND {
83 blocks.push(block.as_ref().clone());
84 }
85 } else {
86 debug!(
87 "Peer {} requested non-existent compact block {}",
88 ctx.node_id, hash
89 );
90 }
91 }
92
93 let response = GetCompactBlocksResponse {
94 request_id: self.request_id,
95 compact_blocks,
96 blocks,
97 };
98
99 ctx.send_response(&response)
100 }
101}