consensus_types/
block_retrieval.rs1use crate::block::Block;
9use anyhow::ensure;
10use diem_crypto::hash::HashValue;
11use diem_types::validator_verifier::ValidatorVerifier;
12use serde::{Deserialize, Serialize};
13use short_hex_str::AsShortHexStr;
14use std::fmt;
15
16pub const MAX_BLOCKS_PER_REQUEST: u64 = 10;
17
18#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
21pub struct BlockRetrievalRequest {
22 block_id: HashValue,
23 num_blocks: u64,
24}
25
26impl BlockRetrievalRequest {
27 pub fn new(block_id: HashValue, num_blocks: u64) -> Self {
28 Self {
29 block_id,
30 num_blocks,
31 }
32 }
33
34 pub fn block_id(&self) -> HashValue { self.block_id }
35
36 pub fn num_blocks(&self) -> u64 { self.num_blocks }
37}
38
39impl fmt::Display for BlockRetrievalRequest {
40 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
41 write!(
42 f,
43 "[BlockRetrievalRequest starting from id {} with {} blocks]",
44 self.block_id, self.num_blocks
45 )
46 }
47}
48
49#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
50pub enum BlockRetrievalStatus {
51 Succeeded,
53 IdNotFound,
55 NotEnoughBlocks,
57}
58
59#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
61pub struct BlockRetrievalResponse {
62 status: BlockRetrievalStatus,
63 blocks: Vec<Block>,
64}
65
66impl BlockRetrievalResponse {
67 pub fn new(status: BlockRetrievalStatus, blocks: Vec<Block>) -> Self {
68 Self { status, blocks }
69 }
70
71 pub fn status(&self) -> BlockRetrievalStatus { self.status.clone() }
72
73 pub fn blocks(&self) -> &Vec<Block> { &self.blocks }
74
75 pub fn verify(
76 &self, block_id: HashValue, num_blocks: u64,
77 sig_verifier: &ValidatorVerifier,
78 ) -> anyhow::Result<()> {
79 ensure!(
80 self.status != BlockRetrievalStatus::Succeeded
81 || (self.blocks.len() as u64 <= num_blocks
82 && !self.blocks.is_empty()),
83 "not enough blocks returned, expect {}, get {}",
84 num_blocks,
85 self.blocks.len(),
86 );
87 self.blocks
88 .iter()
89 .try_fold(block_id, |expected_id, block| {
90 block.validate_signature(sig_verifier)?;
91 block.verify_well_formed()?;
92 ensure!(
93 block.id() == expected_id,
94 "blocks doesn't form a chain: expect {}, get {}",
95 expected_id,
96 block.id()
97 );
98 Ok(block.parent_id())
99 })
100 .map(|_| ())
101 }
102}
103
104impl fmt::Display for BlockRetrievalResponse {
105 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
106 match self.status() {
107 BlockRetrievalStatus::Succeeded => {
108 write!(
109 f,
110 "[BlockRetrievalResponse: status: {:?}, num_blocks: {}, block_ids: ",
111 self.status(),
112 self.blocks().len(),
113 )?;
114
115 f.debug_list()
116 .entries(self.blocks.iter().map(|b| b.id().short_str()))
117 .finish()?;
118
119 write!(f, "]")
120 }
121 _ => write!(
122 f,
123 "[BlockRetrievalResponse: status: {:?}]",
124 self.status()
125 ),
126 }
127 }
128}