casper_node/components/storage/
error.rs

1use std::{fmt::Debug, io, path::PathBuf};
2
3use casper_binary_port::RecordId;
4use thiserror::Error;
5use tracing::error;
6
7use casper_types::{
8    bytesrepr, crypto, BlockBody, BlockHash, BlockHeader, BlockValidationError, DeployHash, Digest,
9    EraId, FinalitySignature, FinalitySignatureId, TransactionHash,
10};
11
12use crate::types::VariantMismatch;
13use casper_storage::block_store::BlockStoreError;
14
15/// A fatal storage component error.
16///
17/// An error of this kinds indicates that storage is corrupted or otherwise irrecoverably broken, at
18/// least for the moment. It should usually be followed by swift termination of the node.
19#[derive(Debug, Error)]
20pub enum FatalStorageError {
21    /// Failure to create the root database directory.
22    #[error("failed to create database directory `{}`: {}", .0.display(), .1)]
23    CreateDatabaseDirectory(PathBuf, io::Error),
24    /// Found a duplicate switch-block-at-era-id index entry.
25    #[error("duplicate entries for switch block at era id {era_id}: {first} / {second}")]
26    DuplicateEraIdIndex {
27        /// Era ID at which duplicate was found.
28        era_id: EraId,
29        /// First block hash encountered at `era_id`.
30        first: BlockHash,
31        /// Second block hash encountered at `era_id`.
32        second: BlockHash,
33    },
34    /// An internal DB error - blocks should be overwritten.
35    #[error("failed overwriting block")]
36    FailedToOverwriteBlock,
37    /// Record specified in raw request has not been found in the storage module.
38    #[error("unable to find db for record: {0}")]
39    DatabaseNotFound(RecordId),
40    /// Filesystem error while trying to move file.
41    #[error("unable to move file {source_path} to {dest_path}: {original_error}")]
42    UnableToMoveFile {
43        /// The path to the file that should have been moved.
44        source_path: PathBuf,
45        /// The path where the file should have been moved to.
46        dest_path: PathBuf,
47        /// The original `io::Error` from `fs::rename`.
48        original_error: io::Error,
49    },
50    /// Mix of missing and found storage files.
51    #[error("expected files to exist: {missing_files:?}.")]
52    MissingStorageFiles {
53        /// The files that were not be found in the storage directory.
54        missing_files: Vec<PathBuf>,
55    },
56    /// Error when validating a block.
57    #[error(transparent)]
58    BlockValidation(#[from] BlockValidationError),
59    /// A block header was not stored under its hash.
60    #[error(
61        "Block header not stored under its hash. \
62         Queried block hash bytes: {queried_block_hash_bytes:x?}, \
63         Found block header hash bytes: {found_block_header_hash:x?}, \
64         Block header: {block_header}"
65    )]
66    BlockHeaderNotStoredUnderItsHash {
67        /// The queried block hash.
68        queried_block_hash_bytes: Vec<u8>,
69        /// The actual header of the block hash.
70        found_block_header_hash: BlockHash,
71        /// The block header found in storage.
72        block_header: Box<BlockHeader>,
73    },
74    /// Block body did not have a block header.
75    #[error(
76        "No block header corresponding to block body found in LMDB. \
77         Block body hash: {block_body_hash:?}, \
78         Block body: {block_body:?}"
79    )]
80    NoBlockHeaderForBlockBody {
81        /// The block body hash.
82        block_body_hash: Digest,
83        /// The block body.
84        block_body: Box<BlockBody>,
85    },
86    /// Could not verify finality signatures for block.
87    #[error("{0} in signature verification. Database is corrupted.")]
88    SignatureVerification(crypto::Error),
89    /// Corrupted block signature index.
90    #[error(
91        "Block signatures not indexed by their block hash. \
92         Key bytes in LMDB: {raw_key:x?}, \
93         Block hash bytes in record: {block_hash_bytes:x?}"
94    )]
95    CorruptedBlockSignatureIndex {
96        /// The key in the block signature index.
97        raw_key: Vec<u8>,
98        /// The block hash of the signatures found in the index.
99        block_hash_bytes: Vec<u8>,
100    },
101    /// Switch block does not contain era end.
102    #[error("switch block does not contain era end: {0:?}")]
103    InvalidSwitchBlock(Box<BlockHeader>),
104    /// A block body was found to have more parts than expected.
105    #[error(
106        "Found an unexpected part of a block body in the database: \
107        {part_hash:?}"
108    )]
109    UnexpectedBlockBodyPart {
110        /// The block body with the issue.
111        block_body_hash: Digest,
112        /// The hash of the superfluous body part.
113        part_hash: Digest,
114    },
115    /// Failed to serialize an item that was found in local storage.
116    #[error("failed to serialized stored item")]
117    StoredItemSerializationFailure(#[source] bincode::Error),
118    /// We tried to store finalized approvals for a nonexistent transaction.
119    #[error("Tried to store FinalizedApprovals for a nonexistent transaction {transaction_hash}")]
120    UnexpectedFinalizedApprovals {
121        /// The missing transaction hash.
122        transaction_hash: TransactionHash,
123    },
124    /// `ToBytes` serialization failure of an item that should never fail to serialize.
125    #[error("unexpected serialization failure: {0}")]
126    UnexpectedSerializationFailure(bytesrepr::Error),
127    /// `ToBytes` deserialization failure of an item that should never fail to serialize.
128    #[error("unexpected deserialization failure: {0}")]
129    UnexpectedDeserializationFailure(bytesrepr::Error),
130    /// Stored finalized approvals hashes count doesn't match number of deploys.
131    #[error(
132        "stored finalized approvals hashes count doesn't match number of deploys: \
133        block hash: {block_hash}, expected: {expected}, actual: {actual}"
134    )]
135    ApprovalsHashesLengthMismatch {
136        /// The block hash.
137        block_hash: BlockHash,
138        /// The number of deploys in the block.
139        expected: usize,
140        /// The number of approvals hashes.
141        actual: usize,
142    },
143    /// V1 execution results hashmap doesn't have exactly one entry.
144    #[error(
145        "stored v1 execution results doesn't have exactly one entry: deploy: {deploy_hash}, number \
146        of entries: {results_length}"
147    )]
148    InvalidExecutionResultsV1Length {
149        /// The deploy hash.
150        deploy_hash: DeployHash,
151        /// The number of execution results.
152        results_length: usize,
153    },
154    /// Error initializing metrics.
155    #[error("failed to initialize metrics for storage: {0}")]
156    Prometheus(#[from] prometheus::Error),
157    /// Type mismatch indicating programmer error.
158    #[error(transparent)]
159    VariantMismatch(#[from] VariantMismatch),
160    /// BlockStoreError
161    #[error(transparent)]
162    BlockStoreError(#[from] BlockStoreError),
163    /// BlockStoreError
164    #[error("unexpected record id {0}")]
165    UnexpectedRecordId(RecordId),
166}
167
168impl From<Box<BlockValidationError>> for FatalStorageError {
169    fn from(err: Box<BlockValidationError>) -> Self {
170        Self::BlockValidation(*err)
171    }
172}
173
174/// An error that may occur when handling a get request.
175///
176/// Wraps a fatal error, callers should check whether the variant is of the fatal or non-fatal kind.
177#[derive(Debug, Error)]
178pub(super) enum GetRequestError {
179    /// A fatal error occurred.
180    #[error(transparent)]
181    Fatal(#[from] FatalStorageError),
182    /// Failed to serialized an item ID on an incoming item request.
183    #[error("failed to deserialize incoming item id")]
184    MalformedIncomingItemId(#[source] bincode::Error),
185    #[error(
186        "id information not matching the finality signature: \
187        requested id: {requested_id},\
188        signature: {finality_signature}"
189    )]
190    FinalitySignatureIdMismatch {
191        // the ID requested
192        requested_id: Box<FinalitySignatureId>,
193        // the finality signature read from storage
194        finality_signature: Box<FinalitySignature>,
195    },
196}