// Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 use crate::block_processor::pruning::{ EVERYTHING_PRUNING_INTERVAL, EVERYTHING_PRUNING_KEEP_RECENT, }; use crate::helpers::MalformedDataError; use crate::storage::NyxdScraperStorageError; use tendermint::Hash; use thiserror::Error; use tokio::sync::mpsc::error::SendError; #[derive(Debug, Error)] pub enum ScraperError { #[error("storage error: {0}")] StorageError(#[from] NyxdScraperStorageError), #[error("the block scraper is already running")] ScraperAlreadyRunning, #[error("block information for height {height} is not available on the provided rpc endpoint")] BlocksUnavailable { height: u32 }, #[error("failed to establish websocket connection to {url}: {source}")] WebSocketConnectionFailure { url: String, #[source] source: Box, }, #[error("failed to establish rpc connection to {url}: {source}")] HttpConnectionFailure { url: String, #[source] source: Box, }, #[error("failed to create chain subscription: {source}")] ChainSubscriptionFailure { #[source] source: Box, }, #[error("could not obtain basic block information at height: {height}: {source}")] BlockQueryFailure { height: u32, #[source] source: Box, }, #[error("could not obtain block results information at height: {height}: {source}")] BlockResultsQueryFailure { height: u32, #[source] source: Box, }, #[error("could not obtain validators information at height: {height}: {source}")] ValidatorsQueryFailure { height: u32, #[source] source: Box, }, #[error("could not obtain tx results for tx: {hash}: {source}")] TxResultsQueryFailure { hash: Hash, #[source] source: Box, }, #[error("could not obtain current abci info: {source}")] AbciInfoQueryFailure { #[source] source: Box, }, #[error("could not parse tx {hash}: {source}")] TxParseFailure { hash: Hash, #[source] source: cosmrs::ErrorReport, }, #[error("could not parse msg of type {type_url}: {source}")] MsgParseFailure { type_url: String, #[source] source: cosmrs::ErrorReport, }, #[error( "received an invalid chain subscription event of kind {kind} while we were waiting for new block data (query: '{query}')" )] InvalidSubscriptionEvent { query: String, kind: String }, #[error("received block data was empty (query: '{query}')")] EmptyBlockData { query: String }, #[error("reached maximum number of allowed errors for subscription events")] MaximumWebSocketFailures, #[error("failed to begin storage tx: {source}")] StorageTxBeginFailure { #[source] source: NyxdScraperStorageError, }, #[error("failed to commit storage tx: {source}")] StorageTxCommitFailure { #[source] source: NyxdScraperStorageError, }, #[error("failed to send on a closed channel")] ClosedChannelError, #[error(transparent)] MalformedData(#[from] MalformedDataError), #[error( "could not find the block proposer ('{proposer}') for height {height} in the validator set" )] BlockProposerNotInValidatorSet { height: u32, proposer: String }, #[error( "pruning.interval must not be set to 0. If you want to disable pruning, select pruning.strategy = \"nothing\"" )] ZeroPruningInterval, #[error( "pruning.interval must not be smaller than {}. got: {interval}. for most aggressive pruning, select pruning.strategy = \"everything\"", EVERYTHING_PRUNING_INTERVAL )] TooSmallPruningInterval { interval: u32 }, #[error( "pruning.keep_recent must not be smaller than {}. got: {keep_recent}. for most aggressive pruning, select pruning.strategy = \"everything\"", EVERYTHING_PRUNING_KEEP_RECENT )] TooSmallKeepRecent { keep_recent: u32 }, #[error("'{type_url}' is not registered in the message registry")] MissingTypeUrlRegistration { type_url: String }, #[error("failed to decode message of type '{type_url}': {error}")] InvalidProtoRepresentation { type_url: String, #[source] error: prost::DecodeError, }, #[error("failed to encode message of type '{type_url}' to json: '{error}'")] JsonSerialisationFailure { type_url: String, #[source] error: serde_json::Error, }, #[error("serialisation of message of type '{type_url}' didn't result in an object!")] JsonSerialisationFailureNotObject { type_url: String }, #[error("field '{field}' in '{type_url}' is not a string")] JsonWasmSerialisationFailureNotString { field: String, type_url: String }, #[error("field '{field}' in '{type_url}' has invalid base64 encoding: {error}")] JsonWasmSerialisationFailureInvalidBase64Encoding { field: String, type_url: String, #[source] error: base64::DecodeError, }, #[error("no modules configured for the chain watcher")] NoModulesConfigured, #[error("no storage configured for the chain watcher")] NoStorageConfigured, } impl ScraperError { pub fn tx_begin_failure(source: NyxdScraperStorageError) -> ScraperError { ScraperError::StorageTxBeginFailure { source } } pub fn tx_commit_failure(source: NyxdScraperStorageError) -> ScraperError { ScraperError::StorageTxCommitFailure { source } } } impl From> for ScraperError { fn from(_: SendError) -> Self { ScraperError::ClosedChannelError } }