use std::{array::TryFromSliceError, convert::Infallible};
use shardtree::error::ShardTreeError;
use zcash_primitives::{block::BlockHash, consensus::BlockHeight, transaction::TxId};
use zcash_protocol::PoolType;
use crate::wallet::OutputId;
#[derive(Debug, thiserror::Error)]
pub enum SyncError<E>
where
E: std::fmt::Debug + std::fmt::Display,
{
#[error("mempool error. {0}")]
MempoolError(#[from] MempoolError),
#[error("scan error. {0}")]
ScanError(#[from] ScanError),
#[error("server error. {0}")]
ServerError(#[from] ServerError),
#[error("sync mode error. {0}")]
SyncModeError(#[from] SyncModeError),
#[error("wallet height is more than {0} blocks ahead of best chain height")]
ChainError(u32),
#[error("shard tree error. {0}")]
ShardTreeError(#[from] ShardTreeError<Infallible>),
#[error("transparent address derivation error. {0}")]
TransparentAddressDerivationError(bip32::Error),
#[error("wallet error. {0}")]
WalletError(E),
}
#[derive(Debug, thiserror::Error)]
pub enum SyncStatusError<E>
where
E: std::fmt::Debug + std::fmt::Display,
{
#[error("No sync data. Wallet has never been synced with the block chain.")]
NoSyncData,
#[error("wallet error. {0}")]
WalletError(E),
}
#[derive(Debug, thiserror::Error)]
pub enum MempoolError {
#[error("server error. {0}")]
ServerError(#[from] ServerError),
#[error(
"timed out fetching mempool stream during shutdown.\nNON-CRITICAL: sync completed successfully but may not have scanned transactions in the mempool."
)]
ShutdownWithoutStream,
}
#[derive(Debug, thiserror::Error)]
pub enum ScanError {
#[error("server error. {0}")]
ServerError(#[from] ServerError),
#[error("continuity error. {0}")]
ContinuityError(#[from] ContinuityError),
#[error("{0}")]
ZcbScanError(zcash_client_backend::scanning::ScanError),
#[error("invalid sapling nullifier. {0}")]
InvalidSaplingNullifier(#[from] TryFromSliceError),
#[error("invalid orchard nullifier length. should be 32 bytes, found {0}")]
InvalidOrchardNullifierLength(usize),
#[error("invalid orchard nullifier")]
InvalidOrchardNullifier,
#[error("invalid sapling output")]
InvalidSaplingOutput,
#[error("invalid orchard action")]
InvalidOrchardAction,
#[error(
"incorrect tree size. {shielded_protocol} tree size recorded in block metadata {block_metadata_size} does not match calculated size {calculated_size}"
)]
IncorrectTreeSize {
shielded_protocol: PoolType,
block_metadata_size: u32,
calculated_size: u32,
},
#[error(
"txid of transaction returned by the server does not match requested txid.\ntxid requested: {txid_requested}\ntxid returned: {txid_returned}"
)]
IncorrectTxid {
txid_requested: TxId,
txid_returned: TxId,
},
#[error("decrypted note nullifier and position data not found. output id: {0:?}")]
DecryptedNoteDataNotFound(OutputId),
#[error("invalid memo bytes. {0}")]
InvalidMemoBytes(#[from] zcash_primitives::memo::Error),
#[error("failed to parse encoded address. {0}")]
AddressParseError(#[from] zcash_address::unified::ParseError),
}
#[derive(Debug, thiserror::Error)]
pub enum ContinuityError {
#[error(
"height discontinuity. block with height {height} is not continuous with previous block height {previous_block_height}"
)]
HeightDiscontinuity {
height: BlockHeight,
previous_block_height: BlockHeight,
},
#[error(
"hash discontinuity. block prev_hash {prev_hash} with height {height} does not match previous block hash {previous_block_hash}"
)]
HashDiscontinuity {
height: BlockHeight,
prev_hash: BlockHash,
previous_block_hash: BlockHash,
},
}
#[derive(Debug, thiserror::Error)]
pub enum ServerError {
#[error("server request failed. {0}")]
RequestFailed(#[from] tonic::Status),
#[error("server returned invalid frontier. {0}")]
InvalidFrontier(std::io::Error),
#[error("server returned invalid transaction. {0}")]
InvalidTransaction(std::io::Error),
#[error("server returned invalid subtree root")]
InvalidSubtreeRoot,
#[error(
"server returned blocks that could not be verified against wallet block data. exceeded max verification window."
)]
ChainVerificationError,
}
#[derive(Debug, thiserror::Error)]
pub enum SyncModeError {
#[error("invalid sync mode. {0}")]
InvalidSyncMode(u8),
#[error("sync is already running")]
SyncAlreadyRunning,
#[error("sync is not running")]
SyncNotRunning,
#[error("sync is not paused")]
SyncNotPaused,
}