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 transactions = block.transactions.iter();
79 let tx_resp = self
80 .index_skips
81 .iter()
82 .map(|index_skip| {
83 transactions
84 .nth(*index_skip)
85 .map(|tx| tx.transaction.clone())
86 })
87 .collect::<Option<Vec<_>>>()
88 .ok_or_else(|| {
89 warn!(
90 "Request tx index out of bound, peer={}, hash={}",
91 ctx.node_id,
92 block.hash()
93 );
94 Error::InvalidGetBlockTxn("index out-of-bound".into())
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}