cfxcore/sync/message/
get_block_txn.rs1use crate::{
6 message::RequestId,
7 sync::{
8 message::{
9 msgid, Context, GetBlockTxnResponse, GetBlocks, Handleable, Key,
10 KeyContainer,
11 },
12 request_manager::{AsAny, Request},
13 Error, ProtocolConfiguration,
14 },
15};
16use cfx_types::H256;
17use malloc_size_of_derive::MallocSizeOf as DeriveMallocSizeOf;
18use rlp_derive::{RlpDecodable, RlpEncodable};
19use std::{any::Any, time::Duration};
20
21#[derive(
22 Debug,
23 PartialEq,
24 Default,
25 RlpDecodable,
26 RlpEncodable,
27 Clone,
28 DeriveMallocSizeOf,
29)]
30pub struct GetBlockTxn {
31 pub request_id: RequestId,
32 pub block_hash: H256,
33 pub index_skips: Vec<usize>,
34}
35
36impl AsAny for GetBlockTxn {
37 fn as_any(&self) -> &dyn Any { self }
38
39 fn as_any_mut(&mut self) -> &mut dyn Any { self }
40}
41
42impl Request for GetBlockTxn {
43 fn timeout(&self, conf: &ProtocolConfiguration) -> Duration {
44 conf.blocks_request_timeout
45 }
46
47 fn on_removed(&self, inflight_keys: &KeyContainer) {
48 let mut inflight_blocks = inflight_keys.write(msgid::GET_BLOCKS);
49 let mut net_inflight_blocks =
50 inflight_keys.write(msgid::NET_INFLIGHT_BLOCKS);
51 inflight_blocks.remove(&Key::Hash(self.block_hash.clone()));
52 net_inflight_blocks.remove(&Key::Hash(self.block_hash.clone()));
53 }
54
55 fn with_inflight(&mut self, _inflight_keys: &KeyContainer) {
56 }
58
59 fn is_empty(&self) -> bool { false }
60
61 fn resend(&self) -> Option<Box<dyn Request>> {
62 Some(Box::new(GetBlocks {
63 request_id: 0,
64 with_public: false,
67 hashes: vec![self.block_hash.clone()],
68 preferred_node_type: None,
69 }))
70 }
71}
72
73impl Handleable for GetBlockTxn {
74 fn handle(self, ctx: &Context) -> Result<(), Error> {
75 match ctx.manager.graph.block_by_hash(&self.block_hash) {
76 Some(block) => {
77 debug!("Process get_blocktxn hash={:?}", block.hash());
78 let mut tx_resp = Vec::with_capacity(self.index_skips.len());
79 let mut last = 0;
80 for index_skip in self.index_skips.iter() {
81 last += *index_skip;
82 if last >= block.transactions.len() {
83 warn!(
84 "Request tx index out of bound, peer={}, hash={}",
85 ctx.node_id,
86 block.hash()
87 );
88 return Err(Error::InvalidGetBlockTxn(
89 "index out-of-bound".into(),
90 )
91 .into());
92 }
93 tx_resp.push(block.transactions[last].transaction.clone());
94 last += 1;
95 }
96 let response = GetBlockTxnResponse {
97 request_id: self.request_id,
98 block_hash: self.block_hash,
99 block_txn: tx_resp,
100 };
101
102 ctx.send_response(&response)
103 }
104 None => {
105 warn!(
106 "Get blocktxn request of non-existent block, hash={}",
107 self.block_hash
108 );
109
110 let response = GetBlockTxnResponse {
111 request_id: self.request_id,
112 block_hash: H256::default(),
113 block_txn: Vec::new(),
114 };
115
116 ctx.send_response(&response)
117 }
118 }
119 }
120}