casper_client/
validation.rs1use thiserror::Error;
2
3use casper_hashing::Digest;
4use casper_types::bytesrepr;
5
6use crate::{
7 rpcs::{common::BlockIdentifier, results::GetBlockResult},
8 types::{self, Block, BlockHash},
9};
10
11#[derive(Error, Debug)]
13pub enum ValidateResponseError {
14 #[error("failed to marshall value {0}")]
16 BytesRepr(bytesrepr::Error),
17
18 #[error(transparent)]
20 Serde(#[from] serde_json::Error),
21
22 #[error("validate response failed to parse")]
24 ValidateResponseFailedToParse,
25
26 #[error(
28 "block header has incorrect body hash. \
29 actual block body hash: {actual_block_body_hash}, \
30 block: {block}"
31 )]
32 BodyHashMismatch {
33 block: Box<Block>,
35 actual_block_body_hash: Digest,
37 },
38
39 #[error(
41 "block has incorrect block hash. \
42 actual block body hash: {actual_block_header_hash}, \
43 block: {block}"
44 )]
45 BlockHashMismatch {
46 block: Box<Block>,
48 actual_block_header_hash: BlockHash,
50 },
51
52 #[error("serialized value not contained in proof")]
54 SerializedValueNotContainedInProof,
55
56 #[error("no block in response")]
58 NoBlockInResponse,
59
60 #[error("block hash requested does not correspond to response")]
62 UnexpectedBlockHash,
63
64 #[error("block height was not as requested")]
66 UnexpectedBlockHeight,
67
68 #[error("invalid combination of state identifier and block header in response")]
70 InvalidGlobalStateResponse,
71}
72
73impl From<bytesrepr::Error> for ValidateResponseError {
74 fn from(e: bytesrepr::Error) -> Self {
75 ValidateResponseError::BytesRepr(e)
76 }
77}
78
79pub(crate) fn validate_get_block_result(
80 maybe_block_identifier: Option<BlockIdentifier>,
81 result: &GetBlockResult,
82) -> Result<(), ValidateResponseError> {
83 let block = if let Some(block) = result.block.as_ref() {
84 block
85 } else {
86 return Ok(());
87 };
88
89 match types::validate_block_hashes_v1(block) {
90 Ok(()) => {}
91 Err(v1_error) => match types::validate_block_hashes_v2(block) {
92 Ok(()) => {}
93 Err(_v2_error) => return Err(v1_error),
94 },
95 }
96
97 match maybe_block_identifier {
98 Some(BlockIdentifier::Hash(block_hash)) => {
99 if block_hash.inner() != block.hash().inner() {
100 return Err(ValidateResponseError::UnexpectedBlockHash);
101 }
102 }
103 Some(BlockIdentifier::Height(height)) => {
104 if height != block.header().height() {
106 return Err(ValidateResponseError::UnexpectedBlockHeight);
107 }
108 }
109 None => (),
113 }
114 Ok(())
115}