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