Skip to main content

near_chain_primitives/
error.rs

1use near_primitives::block::BlockValidityError;
2use near_primitives::challenge::{ChunkProofs, MaybeEncodedShardChunk};
3use near_primitives::errors::{
4    ChunkAccessError, EpochError, InvalidSpiceCoreStatementsError, StorageError,
5};
6use near_primitives::shard_layout::ShardLayoutError;
7use near_primitives::sharding::{BadHeaderForProtocolVersionError, ChunkHash, ShardChunkHeader};
8use near_primitives::types::{BlockHeight, EpochId, ShardId, ShardIndex};
9use near_time::Utc;
10use std::io;
11
12#[derive(thiserror::Error, Debug)]
13pub enum QueryError {
14    #[error("Account ID {requested_account_id} is invalid")]
15    InvalidAccount {
16        requested_account_id: near_primitives::types::AccountId,
17        block_height: near_primitives::types::BlockHeight,
18        block_hash: near_primitives::hash::CryptoHash,
19    },
20    #[error("Account {requested_account_id} does not exist while viewing")]
21    UnknownAccount {
22        requested_account_id: near_primitives::types::AccountId,
23        block_height: near_primitives::types::BlockHeight,
24        block_hash: near_primitives::hash::CryptoHash,
25    },
26    #[error(
27        "Contract code for contract ID {contract_account_id} has never been observed on the node"
28    )]
29    NoContractCode {
30        contract_account_id: near_primitives::types::AccountId,
31        block_height: near_primitives::types::BlockHeight,
32        block_hash: near_primitives::hash::CryptoHash,
33    },
34    #[error("Access key for public key {public_key} does not exist while viewing")]
35    UnknownAccessKey {
36        public_key: near_crypto::PublicKey,
37        block_height: near_primitives::types::BlockHeight,
38        block_hash: near_primitives::hash::CryptoHash,
39    },
40    #[error("Gas key for public key {public_key} does not exist while viewing")]
41    UnknownGasKey {
42        public_key: near_crypto::PublicKey,
43        block_height: near_primitives::types::BlockHeight,
44        block_hash: near_primitives::hash::CryptoHash,
45    },
46    #[error("Internal error occurred: {error_message}")]
47    InternalError {
48        error_message: String,
49        block_height: near_primitives::types::BlockHeight,
50        block_hash: near_primitives::hash::CryptoHash,
51    },
52    #[error("Function call returned an error: {error_message}")]
53    ContractExecutionError {
54        error_message: String,
55        error: near_primitives::errors::FunctionCallError,
56        block_height: near_primitives::types::BlockHeight,
57        block_hash: near_primitives::hash::CryptoHash,
58    },
59    #[error("The state of account {requested_account_id} is too large")]
60    TooLargeContractState {
61        requested_account_id: near_primitives::types::AccountId,
62        block_height: near_primitives::types::BlockHeight,
63        block_hash: near_primitives::hash::CryptoHash,
64    },
65    #[error(
66        "Global contract code with identifier {identifier:?} has never been observed on the node"
67    )]
68    NoGlobalContractCode {
69        identifier: near_primitives::action::GlobalContractIdentifier,
70        block_height: near_primitives::types::BlockHeight,
71        block_hash: near_primitives::hash::CryptoHash,
72    },
73}
74
75#[derive(Debug, thiserror::Error)]
76pub enum Error {
77    /// The block is already known
78    #[error("Block is known: {0}")]
79    BlockKnown(#[from] BlockKnownError),
80    #[error("Too many blocks being processed")]
81    TooManyProcessingBlocks,
82    /// Orphan block.
83    #[error("Orphan")]
84    Orphan,
85    /// Chunk is missing.
86    #[error("Chunk Missing (unavailable on the node): {0:?}")]
87    ChunkMissing(ChunkHash),
88    /// Chunks missing with header info.
89    #[error("Chunks Missing: {0:?}")]
90    ChunksMissing(Vec<ShardChunkHeader>),
91    /// Block is pending optimistic block execution.
92    #[error("Block Pending Optimistic Execution")]
93    BlockPendingOptimisticExecution,
94    /// Block time is before parent block time.
95    #[error("Invalid Block Time: block time {1} before previous {0}")]
96    InvalidBlockPastTime(Utc, Utc),
97    /// Block time is from too much in the future.
98    #[error("Invalid Block Time: Too far in the future: {0}")]
99    InvalidBlockFutureTime(Utc),
100    /// Block height is invalid (not previous + 1).
101    #[error("Invalid Block Height {0}")]
102    InvalidBlockHeight(BlockHeight),
103    /// Invalid block proposed signature.
104    #[error("Invalid Block Proposer Signature")]
105    InvalidBlockProposer,
106    /// Invalid state root hash.
107    #[error("Invalid State Root Hash")]
108    InvalidStateRoot,
109    /// Invalid merkle root hash.
110    #[error("Invalid Chunk Encoded Merkle Root Hash")]
111    InvalidChunkEncodedMerkleRoot,
112    /// Invalid merkle root hash.
113    #[error("Invalid Chunk Encoded Merkle Length")]
114    InvalidChunkEncodedLength,
115    /// Invalid block tx root hash.
116    #[error("Invalid Block Tx Root Hash")]
117    InvalidTxRoot,
118    /// Invalid chunk receipts root hash.
119    #[error("Invalid Chunk Receipts Root Hash")]
120    InvalidChunkReceiptsRoot,
121    /// Invalid chunk headers root hash.
122    #[error("Invalid Chunk Headers Root Hash")]
123    InvalidChunkHeadersRoot,
124    /// Invalid chunk tx root hash.
125    #[error("Invalid Chunk Tx Root Hash")]
126    InvalidChunkTxRoot,
127    /// Invalid receipts proof.
128    #[error("Invalid Receipts Proof")]
129    InvalidReceiptsProof,
130    /// Invalid outcomes proof.
131    #[error("Invalid Outcomes Proof")]
132    InvalidOutcomesProof,
133    /// Invalid state payload on state sync.
134    #[error("Invalid State Payload")]
135    InvalidStatePayload,
136    /// Invalid transactions in the block.
137    #[error("Invalid Transactions")]
138    InvalidTransactions,
139    /// Invalid challenge (wrong signature or format).
140    #[error("Invalid Challenge")]
141    InvalidChallenge,
142    /// Incorrect number of chunk headers
143    #[error("Incorrect Number of Chunk Headers")]
144    IncorrectNumberOfChunkHeaders,
145    /// Invalid chunk.
146    #[error("Invalid Chunk")]
147    InvalidChunk(String),
148    /// One of the chunks has invalid transactions order
149    #[error("Invalid Chunk Transactions Order")]
150    InvalidChunkTransactionsOrder(Box<MaybeEncodedShardChunk>),
151    /// One of the chunks has invalid proofs
152    #[error("Invalid Chunk Proofs")]
153    InvalidChunkProofs(Box<ChunkProofs>),
154    #[error("Invalid Chunk State Witness: {0}")]
155    InvalidChunkStateWitness(String),
156    #[error("Invalid Partial Chunk State Witness: {0}")]
157    InvalidPartialChunkStateWitness(String),
158    #[error("Invalid Chunk Endorsement")]
159    InvalidChunkEndorsement,
160    /// Invalid chunk mask
161    #[error("Invalid Chunk Endorsement Bitmap")]
162    InvalidChunkEndorsementBitmap(String),
163    /// Invalid chunk mask
164    #[error("Invalid Chunk Mask")]
165    InvalidChunkMask,
166    /// Invalid epoch hash
167    #[error("Invalid Epoch Hash")]
168    InvalidEpochHash,
169    /// `next_bps_hash` doesn't correspond to the actual next block producers set
170    #[error("Invalid Next BP Hash")]
171    InvalidNextBPHash,
172    /// The block has a protocol version that's outdated
173    #[error("Invalid protocol version")]
174    InvalidProtocolVersion,
175    /// The block doesn't have approvals from 50% of the block producers
176    #[error("Not enough approvals")]
177    NotEnoughApprovals,
178    /// The information about the last final block is incorrect
179    #[error("Invalid finality info")]
180    InvalidFinalityInfo,
181    /// Invalid validator proposals in the block.
182    #[error("Invalid Validator Proposals")]
183    InvalidValidatorProposals,
184    /// Invalid Signature
185    #[error("Invalid Signature")]
186    InvalidSignature,
187    /// Invalid Approvals
188    #[error("Invalid Approvals")]
189    InvalidApprovals,
190    /// Invalid Gas Limit
191    #[error("Invalid Gas Limit")]
192    InvalidGasLimit,
193    /// Invalid Gas Price
194    #[error("Invalid Gas Price")]
195    InvalidGasPrice,
196    /// Invalid Gas Used
197    #[error("Invalid Gas Used")]
198    InvalidGasUsed,
199    /// Invalid Balance Burnt
200    #[error("Invalid Balance Burnt")]
201    InvalidBalanceBurnt,
202    /// Invalid Total Supply
203    #[error("Invalid Total Supply")]
204    InvalidTotalSupply,
205    /// Invalid Congestion Info
206    #[error("Invalid Congestion Info: {0}")]
207    InvalidCongestionInfo(String),
208    /// Invalid bandwidth requests
209    #[error("Invalid bandwidth requests - chunk extra doesn't match chunk header: {0}")]
210    InvalidBandwidthRequests(String),
211    /// Invalid proposed_split in chunk header
212    #[error("Invalid proposed_split in chunk header: {0}")]
213    InvalidChunkHeaderShardSplit(String),
214    /// Invalid shard_split in block header
215    #[error("Invalid shard_split in block header: {0}")]
216    InvalidBlockHeaderShardSplit(String),
217    /// Invalid shard id
218    #[error("Shard id {0} does not exist")]
219    InvalidShardId(ShardId),
220    #[error("Shard index {0} does not exist")]
221    InvalidShardIndex(ShardIndex),
222    #[error("Shard id {0} does not have a parent")]
223    NoParentShardId(ShardId),
224    #[error("Cannot derive shard layout")]
225    CannotDeriveLayout,
226    /// Invalid shard id
227    #[error("Invalid state request: {0}")]
228    InvalidStateRequest(String),
229    /// Invalid VRF proof, or incorrect random_output in the header
230    #[error("Invalid Randomness Beacon Output")]
231    InvalidRandomnessBeaconOutput,
232    /// Invalid block merkle root.
233    #[error("Invalid Block Merkle Root")]
234    InvalidBlockMerkleRoot,
235    /// Invalid block ordinal.
236    #[error("Invalid Block Ordinal")]
237    InvalidBlockOrdinal,
238    /// Invalid epoch sync data hash.
239    #[error("Invalid Epoch Sync Data Hash")]
240    InvalidEpochSyncDataHash,
241    /// Invalid split shard ids.
242    #[error("Invalid Split Shard Ids when resharding. shard_id: {0}, parent_shard_id: {1}")]
243    InvalidSplitShardsIds(ShardId, ShardId),
244    /// Someone is not a validator. Usually happens in signature verification
245    #[error("Not A Validator: {0}")]
246    NotAValidator(String),
247    /// Someone is not a chunk validator. Happens if we're asked to validate a chunk we're not
248    /// supposed to validate, or to verify a chunk approval signed by a validator that isn't
249    /// supposed to validate the chunk.
250    #[error("Not A Chunk Validator")]
251    NotAChunkValidator,
252    /// Validator error.
253    #[error("Validator Error: {0}")]
254    ValidatorError(String),
255    /// Epoch out of bounds. Usually if received block is too far in the future or alternative fork.
256    #[error("Epoch Out Of Bounds: {:?}", _0)]
257    EpochOutOfBounds(EpochId),
258    /// Block cannot be finalized.
259    #[error("Block cannot be finalized")]
260    CannotBeFinalized,
261    /// IO Error.
262    #[error("IO Error: {0}")]
263    IOErr(#[from] io::Error),
264    /// Not found record in the DB.
265    #[error("DB Not Found Error: {0}")]
266    DBNotFoundErr(String),
267    /// Storage error. Used for internal passing the error.
268    #[error("Storage Error: {0}")]
269    StorageError(#[from] StorageError),
270    /// GC error.
271    #[error("GC Error: {0}")]
272    GCError(String),
273    /// Resharding error.
274    #[error("Resharding Error: {0}")]
275    ReshardingError(String),
276    /// EpochSyncProof validation error.
277    #[error("EpochSyncProof Validation Error: {0}")]
278    InvalidEpochSyncProof(String),
279    /// Invalid chunk header version for protocol version
280    #[error(transparent)]
281    BadHeaderForProtocolVersion(#[from] BadHeaderForProtocolVersionError),
282    /// Invalid spice core statements in block.
283    #[error("Invalid spice core statements in block: {0}")]
284    InvalidSpiceCoreStatements(#[from] Box<InvalidSpiceCoreStatementsError>),
285    /// `prev_last_certified_block_epoch_id` on a spice block header doesn't
286    /// match the epoch id of the last fully certified block as of prev.
287    #[error("Invalid prev_last_certified_block_epoch_id: {0}")]
288    InvalidPrevLastCertifiedBlockEpochId(String),
289    /// `spice_chunk_endorsement_stats` on a spice block header doesn't match the
290    /// value recomputed from the chain.
291    #[error("Invalid spice_chunk_endorsement_stats: {0}")]
292    InvalidSpiceChunkEndorsementStats(String),
293    /// Anything else
294    #[error("Other Error: {0}")]
295    Other(String),
296}
297
298/// For now StorageError can happen at any time from ViewClient because of
299/// the used isolation level + running ViewClient in a separate thread.
300pub trait LogTransientStorageError {
301    fn log_storage_error(self, message: &str) -> Self;
302}
303
304impl<T> LogTransientStorageError for Result<T, Error> {
305    fn log_storage_error(self, message: &str) -> Self {
306        if let Err(err) = &self {
307            tracing::error!(target: "chain", %message, ?err, "transient storage error");
308        }
309        self
310    }
311}
312
313impl Error {
314    pub fn is_bad_data(&self) -> bool {
315        match self {
316            Error::BlockKnown(_)
317            | Error::TooManyProcessingBlocks
318            | Error::Orphan
319            | Error::ChunkMissing(_)
320            | Error::ChunksMissing(_)
321            | Error::BlockPendingOptimisticExecution
322            | Error::IOErr(_)
323            | Error::Other(_)
324            | Error::ValidatorError(_)
325            | Error::EpochOutOfBounds(_)
326            | Error::CannotBeFinalized
327            | Error::StorageError(_)
328            | Error::GCError(_)
329            | Error::ReshardingError(_)
330            | Error::DBNotFoundErr(_) => false,
331            Error::InvalidBlockPastTime(_, _)
332            | Error::InvalidBlockFutureTime(_)
333            | Error::InvalidBlockHeight(_)
334            | Error::InvalidBlockProposer
335            | Error::InvalidChunk(_)
336            | Error::InvalidChunkTransactionsOrder(_)
337            | Error::InvalidChunkProofs(_)
338            | Error::InvalidChunkStateWitness(_)
339            | Error::InvalidPartialChunkStateWitness(_)
340            | Error::InvalidChunkEndorsement
341            | Error::InvalidChunkEndorsementBitmap(_)
342            | Error::InvalidChunkMask
343            | Error::InvalidStateRoot
344            | Error::InvalidChunkEncodedMerkleRoot
345            | Error::InvalidChunkEncodedLength
346            | Error::InvalidTxRoot
347            | Error::InvalidChunkReceiptsRoot
348            | Error::InvalidOutcomesProof
349            | Error::InvalidChunkHeadersRoot
350            | Error::InvalidChunkTxRoot
351            | Error::InvalidReceiptsProof
352            | Error::InvalidStatePayload
353            | Error::InvalidTransactions
354            | Error::InvalidChallenge
355            | Error::InvalidSplitShardsIds(_, _)
356            | Error::IncorrectNumberOfChunkHeaders
357            | Error::InvalidEpochHash
358            | Error::InvalidEpochSyncProof(_)
359            | Error::InvalidNextBPHash
360            | Error::NotEnoughApprovals
361            | Error::InvalidFinalityInfo
362            | Error::InvalidValidatorProposals
363            | Error::InvalidSignature
364            | Error::InvalidApprovals
365            | Error::InvalidGasLimit
366            | Error::InvalidGasPrice
367            | Error::InvalidGasUsed
368            | Error::InvalidBalanceBurnt
369            | Error::InvalidTotalSupply
370            | Error::InvalidCongestionInfo(_)
371            | Error::InvalidBandwidthRequests(_)
372            | Error::InvalidChunkHeaderShardSplit(_)
373            | Error::InvalidBlockHeaderShardSplit(_)
374            | Error::InvalidShardId(_)
375            | Error::InvalidShardIndex(_)
376            | Error::NoParentShardId(_)
377            | Error::CannotDeriveLayout
378            | Error::InvalidStateRequest(_)
379            | Error::InvalidRandomnessBeaconOutput
380            | Error::InvalidBlockMerkleRoot
381            | Error::InvalidBlockOrdinal
382            | Error::InvalidEpochSyncDataHash
383            | Error::InvalidProtocolVersion
384            | Error::NotAValidator(_)
385            | Error::NotAChunkValidator
386            | Error::BadHeaderForProtocolVersion(_)
387            | Error::InvalidSpiceCoreStatements(_)
388            | Error::InvalidPrevLastCertifiedBlockEpochId(_)
389            | Error::InvalidSpiceChunkEndorsementStats(_) => true,
390        }
391    }
392
393    pub fn is_error(&self) -> bool {
394        match self {
395            Error::IOErr(_) | Error::Other(_) | Error::DBNotFoundErr(_) => true,
396            _ => false,
397        }
398    }
399
400    /// Some blockchain errors are reported in the prometheus metrics. In such cases a report might
401    /// contain a label that specifies the type of error that has occurred. For example when the node
402    /// receives a block with an invalid signature this would be reported as:
403    ///  `near_num_invalid_blocks{error="invalid_signature"}`.
404    /// This function returns the value of the error label for a specific instance of Error.
405    pub fn prometheus_label_value(&self) -> &'static str {
406        match self {
407            Error::BlockKnown(_) => "block_known",
408            Error::TooManyProcessingBlocks => "too_many_processing_blocks",
409            Error::Orphan => "orphan",
410            Error::ChunkMissing(_) => "chunk_missing",
411            Error::ChunksMissing(_) => "chunks_missing",
412            Error::BlockPendingOptimisticExecution => "block_pending_optimistic_execution",
413            Error::IOErr(_) => "io_err",
414            Error::Other(_) => "other",
415            Error::ValidatorError(_) => "validator_error",
416            Error::EpochOutOfBounds(_) => "epoch_out_of_bounds",
417            Error::CannotBeFinalized => "cannot_be_finalized",
418            Error::StorageError(_) => "storage_error",
419            Error::GCError(_) => "gc_error",
420            Error::DBNotFoundErr(_) => "db_not_found_err",
421            Error::InvalidBlockPastTime(_, _) => "invalid_block_past_time",
422            Error::InvalidBlockFutureTime(_) => "invalid_block_future_time",
423            Error::InvalidBlockHeight(_) => "invalid_block_height",
424            Error::InvalidBlockProposer => "invalid_block_proposer",
425            Error::InvalidChunk(_) => "invalid_chunk",
426            Error::InvalidChunkTransactionsOrder(_) => "invalid_chunk_transactions_order",
427            Error::InvalidChunkProofs(_) => "invalid_chunk_proofs",
428            Error::InvalidChunkStateWitness(_) => "invalid_chunk_state_witness",
429            Error::InvalidPartialChunkStateWitness(_) => "invalid_partial_chunk_state_witness",
430            Error::InvalidChunkEndorsement => "invalid_chunk_endorsement",
431            Error::InvalidChunkEndorsementBitmap(_) => "invalid_chunk_endorsement_bitmap",
432            Error::InvalidChunkMask => "invalid_chunk_mask",
433            Error::InvalidStateRoot => "invalid_state_root",
434            Error::InvalidChunkEncodedMerkleRoot => "invalid_chunk_encoded_merkle_root",
435            Error::InvalidChunkEncodedLength => "invalid_chunk_encoded_length",
436            Error::InvalidTxRoot => "invalid_tx_root",
437            Error::InvalidChunkReceiptsRoot => "invalid_chunk_receipts_root",
438            Error::InvalidOutcomesProof => "invalid_outcomes_proof",
439            Error::InvalidChunkHeadersRoot => "invalid_chunk_headers_root",
440            Error::InvalidChunkTxRoot => "invalid_chunk_tx_root",
441            Error::InvalidReceiptsProof => "invalid_receipts_proof",
442            Error::InvalidStatePayload => "invalid_state_payload",
443            Error::InvalidTransactions => "invalid_transactions",
444            Error::InvalidChallenge => "invalid_challenge",
445            Error::InvalidSplitShardsIds(_, _) => "invalid_split_shard_ids",
446            Error::IncorrectNumberOfChunkHeaders => "incorrect_number_of_chunk_headers",
447            Error::InvalidEpochHash => "invalid_epoch_hash",
448            Error::InvalidEpochSyncProof(_) => "invalid_epoch_sync_proof",
449            Error::InvalidNextBPHash => "invalid_next_bp_hash",
450            Error::NotEnoughApprovals => "not_enough_approvals",
451            Error::InvalidFinalityInfo => "invalid_finality_info",
452            Error::InvalidValidatorProposals => "invalid_validator_proposals",
453            Error::InvalidSignature => "invalid_signature",
454            Error::InvalidApprovals => "invalid_approvals",
455            Error::InvalidGasLimit => "invalid_gas_limit",
456            Error::InvalidGasPrice => "invalid_gas_price",
457            Error::InvalidGasUsed => "invalid_gas_used",
458            Error::InvalidBalanceBurnt => "invalid_balance_burnt",
459            Error::InvalidTotalSupply => "invalid_total_supply",
460            Error::InvalidCongestionInfo(_) => "invalid_congestion_info",
461            Error::InvalidBandwidthRequests(_) => "invalid_bandwidth_requests",
462            Error::InvalidChunkHeaderShardSplit(_) => "invalid_chunk_header_shard_split",
463            Error::InvalidBlockHeaderShardSplit(_) => "invalid_block_header_shard_split",
464            Error::InvalidShardId(_) => "invalid_shard_id",
465            Error::InvalidShardIndex(_) => "invalid_shard_index",
466            Error::NoParentShardId(_) => "no_parent_shard_id",
467            Error::CannotDeriveLayout => "derive_layout",
468            Error::InvalidStateRequest(_) => "invalid_state_request",
469            Error::InvalidRandomnessBeaconOutput => "invalid_randomness_beacon_output",
470            Error::InvalidBlockMerkleRoot => "invalid_block_merkle_root",
471            Error::InvalidBlockOrdinal => "invalid_block_ordinal",
472            Error::InvalidEpochSyncDataHash => "invalid_epoch_sync_data_hash",
473            Error::InvalidProtocolVersion => "invalid_protocol_version",
474            Error::NotAValidator(_) => "not_a_validator",
475            Error::NotAChunkValidator => "not_a_chunk_validator",
476            Error::ReshardingError(_) => "resharding_error",
477            Error::BadHeaderForProtocolVersion(_) => "bad_header_for_protocol_version",
478            Error::InvalidSpiceCoreStatements(_) => "invalid_spice_core_statements",
479            Error::InvalidPrevLastCertifiedBlockEpochId(_) => {
480                "invalid_prev_last_certified_block_epoch_id"
481            }
482            Error::InvalidSpiceChunkEndorsementStats(_) => "invalid_spice_chunk_endorsement_stats",
483        }
484    }
485}
486
487impl From<EpochError> for Error {
488    fn from(error: EpochError) -> Self {
489        match error {
490            EpochError::EpochOutOfBounds(epoch_id) => Error::EpochOutOfBounds(epoch_id),
491            EpochError::MissingBlock(h) => Error::DBNotFoundErr(format!("epoch block: {h}")),
492            EpochError::NotAValidator(account_id, epoch_id) => {
493                Error::NotAValidator(format!("account_id: {account_id}, epoch_id: {epoch_id:?}"))
494            }
495            EpochError::ChunkProducerNotInDB(h, s) => {
496                Error::DBNotFoundErr(format!("chunk producer for block {h} shard {s}"))
497            }
498            err => Error::ValidatorError(err.to_string()),
499        }
500    }
501}
502
503pub trait EpochErrorResultToChainError<T> {
504    fn into_chain_error(self) -> Result<T, Error>;
505}
506
507impl<T> EpochErrorResultToChainError<T> for Result<T, EpochError> {
508    fn into_chain_error(self: Result<T, EpochError>) -> Result<T, Error> {
509        self.map_err(|err| err.into())
510    }
511}
512
513impl From<ShardLayoutError> for Error {
514    fn from(error: ShardLayoutError) -> Self {
515        match error {
516            ShardLayoutError::InvalidShardId { shard_id } => Error::InvalidShardId(shard_id),
517            ShardLayoutError::InvalidShardIndex { shard_index } => {
518                Error::InvalidShardIndex(shard_index)
519            }
520            ShardLayoutError::NoParent { shard_id } => Error::NoParentShardId(shard_id),
521            ShardLayoutError::CannotDeriveLayout => Error::CannotDeriveLayout,
522            ShardLayoutError::DuplicateBoundaryAccount { .. } => Error::CannotDeriveLayout,
523        }
524    }
525}
526
527impl From<BlockValidityError> for Error {
528    fn from(error: BlockValidityError) -> Self {
529        match error {
530            BlockValidityError::InvalidStateRoot => Error::InvalidStateRoot,
531            BlockValidityError::InvalidReceiptRoot => Error::InvalidChunkReceiptsRoot,
532            BlockValidityError::InvalidTransactionRoot => Error::InvalidTxRoot,
533            BlockValidityError::InvalidChunkHeaderRoot => Error::InvalidChunkHeadersRoot,
534            BlockValidityError::InvalidChunkMask => Error::InvalidChunkMask,
535        }
536    }
537}
538
539impl From<ChunkAccessError> for Error {
540    fn from(error: ChunkAccessError) -> Self {
541        match error {
542            ChunkAccessError::ChunkMissing(chunk_hash) => Error::ChunkMissing(chunk_hash),
543        }
544    }
545}
546
547#[derive(Clone, Eq, PartialEq, Debug, thiserror::Error)]
548pub enum BlockKnownError {
549    #[error("already known in header")]
550    KnownInHeader,
551    #[error("already known in head")]
552    KnownInHead,
553    #[error("already known in orphan")]
554    KnownInOrphan,
555    #[error("already known in missing chunks")]
556    KnownInMissingChunks,
557    #[error("already known in store")]
558    KnownInStore,
559    #[error("already known in blocks in processing")]
560    KnownInProcessing,
561    #[error("already known in invalid blocks")]
562    KnownAsInvalid,
563}