Skip to main content

pepper_sync/
error.rs

1//! Pepper sync error module
2
3use std::{array::TryFromSliceError, convert::Infallible};
4
5use shardtree::error::ShardTreeError;
6use zcash_primitives::{block::BlockHash, consensus::BlockHeight, transaction::TxId};
7use zcash_protocol::PoolType;
8
9use crate::wallet::OutputId;
10
11/// Top level error enumerating any error that may occur during sync
12#[derive(Debug, thiserror::Error)]
13pub enum SyncError<E>
14where
15    E: std::fmt::Debug + std::fmt::Display,
16{
17    /// Mempool error.
18    #[error("mempool error. {0}")]
19    MempoolError(#[from] MempoolError),
20    /// Scan error.
21    #[error("scan error. {0}")]
22    ScanError(#[from] ScanError),
23    /// Server error.
24    #[error("server error. {0}")]
25    ServerError(#[from] ServerError),
26    /// Sync mode error.
27    #[error("sync mode error. {0}")]
28    SyncModeError(#[from] SyncModeError),
29    /// Chain error.
30    #[error("wallet height {0} is more than {1} blocks ahead of best chain height {2}")]
31    ChainError(u32, u32, u32),
32    /// Birthday below sapling error.
33    #[error(
34        "birthday {0} below sapling activation height {1}. pre-sapling wallets are not supported!"
35    )]
36    BirthdayBelowSapling(u32, u32),
37    /// Shard tree error.
38    #[error("shard tree error. {0}")]
39    ShardTreeError(#[from] ShardTreeError<Infallible>),
40    /// Critical non-recoverable truncation error due to missing shard tree checkpoints.
41    #[error(
42        "critical non-recoverable truncation error at height {0} due to missing {1} shard tree checkpoints. wallet data cleared. rescan required."
43    )]
44    TruncationError(BlockHeight, PoolType),
45    /// Transparent address derivation error.
46    #[error("transparent address derivation error. {0}")]
47    TransparentAddressDerivationError(bip32::Error),
48    /// Wallet error.
49    #[error("wallet error. {0}")]
50    WalletError(E),
51}
52
53/// Sync status errors.
54#[derive(Debug, thiserror::Error)]
55pub enum SyncStatusError<E>
56where
57    E: std::fmt::Debug + std::fmt::Display,
58{
59    /// No sync data. Wallet has never been synced with the block chain.
60    #[error("No sync data. Wallet has never been synced with the block chain.")]
61    NoSyncData,
62    /// Wallet error.
63    #[error("wallet error. {0}")]
64    WalletError(E),
65}
66
67/// Mempool errors.
68#[derive(Debug, thiserror::Error)]
69pub enum MempoolError {
70    /// Server error.
71    #[error("server error. {0}")]
72    ServerError(#[from] ServerError),
73    /// Timed out fetching mempool stream during shutdown.
74    #[error(
75        "timed out fetching mempool stream during shutdown.\nNON-CRITICAL: sync completed successfully but may not have scanned transactions in the mempool."
76    )]
77    ShutdownWithoutStream,
78}
79
80/// Scan errors.
81#[derive(Debug, thiserror::Error)]
82pub enum ScanError {
83    /// Server error.
84    #[error("server error. {0}")]
85    ServerError(#[from] ServerError),
86    /// Continuity error.
87    #[error("continuity error. {0}")]
88    ContinuityError(#[from] ContinuityError),
89    /// Zcash client backend scan error
90    #[error("{0}")]
91    ZcbScanError(zcash_client_backend::scanning::ScanError),
92    /// Invalid sapling nullifier
93    #[error("invalid sapling nullifier. {0}")]
94    InvalidSaplingNullifier(#[from] TryFromSliceError),
95    /// Invalid orchard nullifier length
96    #[error("invalid orchard nullifier length. should be 32 bytes, found {0}")]
97    InvalidOrchardNullifierLength(usize),
98    /// Invalid orchard nullifier
99    #[error("invalid orchard nullifier")]
100    InvalidOrchardNullifier,
101    /// Invalid sapling output
102    // TODO: add output data
103    #[error("invalid sapling output")]
104    InvalidSaplingOutput,
105    /// Invalid orchard action
106    // TODO: add output data
107    #[error("invalid orchard action")]
108    InvalidOrchardAction,
109    /// Incorrect tree size
110    #[error(
111        "incorrect tree size. {shielded_protocol} tree size recorded in block metadata {block_metadata_size} does not match calculated size {calculated_size}"
112    )]
113    IncorrectTreeSize {
114        /// Shielded protocol
115        shielded_protocol: PoolType,
116        /// Block metadata size
117        block_metadata_size: u32,
118        /// Calculated size
119        calculated_size: u32,
120    },
121    /// Txid of transaction returned by the server does not match requested txid.
122    #[error(
123        "txid of transaction returned by the server does not match requested txid.\ntxid requested: {txid_requested}\ntxid returned: {txid_returned}"
124    )]
125    IncorrectTxid {
126        /// Txid requested
127        txid_requested: TxId,
128        /// Txid returned
129        txid_returned: TxId,
130    },
131    /// Decrypted note nullifier and position data not found.
132    #[error("decrypted note nullifier and position data not found. output id: {0:?}")]
133    DecryptedNoteDataNotFound(OutputId),
134    /// Invalid memo bytes..
135    #[error("invalid memo bytes. {0}")]
136    InvalidMemoBytes(#[from] zcash_protocol::memo::Error),
137    /// Failed to parse encoded address.
138    #[error("failed to parse encoded address. {0}")]
139    AddressParseError(#[from] zcash_address::unified::ParseError),
140}
141
142/// Block continuity errors.
143#[derive(Debug, thiserror::Error)]
144pub enum ContinuityError {
145    /// Height discontinuity.
146    #[error(
147        "height discontinuity. block with height {height} is not continuous with previous block height {previous_block_height}"
148    )]
149    HeightDiscontinuity {
150        /// Block height
151        height: BlockHeight,
152        /// Previous block height
153        previous_block_height: BlockHeight,
154    },
155    /// Hash discontinuity.
156    #[error(
157        "hash discontinuity. block prev_hash {prev_hash} with height {height} does not match previous block hash {previous_block_hash}"
158    )]
159    HashDiscontinuity {
160        /// Block height
161        height: BlockHeight,
162        /// Block's previous block hash data
163        prev_hash: BlockHash,
164        /// Actual previous block hash
165        previous_block_hash: BlockHash,
166    },
167}
168
169/// Server errors.
170///
171/// Errors associated with connecting to the server and receiving invalid data.
172#[derive(Debug, thiserror::Error)]
173pub enum ServerError {
174    /// Server request failed.
175    #[error("server request failed. {0}")]
176    RequestFailed(#[from] tonic::Status),
177    /// Server returned invalid frontier.
178    #[error("server returned invalid frontier. {0}")]
179    InvalidFrontier(std::io::Error),
180    /// Server returned invalid transaction.
181    #[error("server returned invalid transaction. {0}")]
182    InvalidTransaction(std::io::Error),
183    /// Server returned invalid subtree root.
184    // TODO: add more info
185    #[error("server returned invalid subtree root.")]
186    InvalidSubtreeRoot,
187    /// Server returned blocks that could not be verified against wallet block data. Exceeded max verification window.
188    #[error(
189        "server returned blocks that could not be verified against wallet block data. exceeded max verification window. wallet data has been cleared as shard tree data cannot be truncated further. wallet rescan required."
190    )]
191    ChainVerificationError,
192    /// Fetcher task was dropped.
193    #[error("fetcher task was dropped.")]
194    FetcherDropped,
195    /// Server reports only the genesis block exists.
196    #[error("server reports only the genesis block exists.")]
197    GenesisBlockOnly,
198}
199
200/// Sync mode error.
201#[derive(Debug, thiserror::Error)]
202pub enum SyncModeError {
203    /// Invalid sync mode.
204    #[error("invalid sync mode. {0}")]
205    InvalidSyncMode(u8),
206    /// Sync is already running.
207    #[error("sync is already running")]
208    SyncAlreadyRunning,
209    /// Sync is not running.
210    #[error("sync is not running")]
211    SyncNotRunning,
212    /// Sync is not paused.
213    #[error("sync is not paused")]
214    SyncNotPaused,
215}