iuna

iuna

iuna - experimental mainnet-candidate protocol
git clone https://getiuna.org/git/iuna.git
Log | Files | Refs | README | LICENSE

error.rs (3658B)


      1 use std::{error::Error, fmt};
      2 
      3 /// Validation failures whose identity drives behavior outside the domain layer.
      4 ///
      5 /// Keep ordinary validation messages as `anyhow` errors until a caller needs to
      6 /// branch on them; variants here are a control-flow contract, not an exhaustive
      7 /// catalog of every validation failure.
      8 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
      9 pub(crate) enum ValidationError {
     10     BlockConflictsWithLocalChain { height: u64 },
     11     UnexpectedBlockHeight { expected: u64, actual: u64 },
     12     BlockDoesNotExtendLocalTip,
     13     BlockBeforeFinalizerRankSlot { rank: u32, min_timestamp: u64 },
     14     BlockTimestampTooFarInFuture,
     15     BurnBundleParentMismatch,
     16     BurnAnchorOutsidePendingWindow,
     17     MineAnchorNotOnChain,
     18     MineAnchorLimitReached,
     19 }
     20 
     21 impl ValidationError {
     22     pub(crate) fn requests_fork_recovery(self) -> bool {
     23         matches!(
     24             self,
     25             Self::BlockConflictsWithLocalChain { .. }
     26                 | Self::UnexpectedBlockHeight { .. }
     27                 | Self::BlockDoesNotExtendLocalTip
     28         )
     29     }
     30 
     31     pub(crate) fn is_fork_relative(self) -> bool {
     32         matches!(
     33             self,
     34             Self::BlockConflictsWithLocalChain { .. }
     35                 | Self::UnexpectedBlockHeight { .. }
     36                 | Self::BlockDoesNotExtendLocalTip
     37                 | Self::BurnBundleParentMismatch
     38                 | Self::BurnAnchorOutsidePendingWindow
     39                 | Self::MineAnchorNotOnChain
     40         )
     41     }
     42 
     43     pub(crate) fn is_temporal(self) -> bool {
     44         matches!(
     45             self,
     46             Self::BlockBeforeFinalizerRankSlot { .. } | Self::BlockTimestampTooFarInFuture
     47         )
     48     }
     49 }
     50 
     51 impl fmt::Display for ValidationError {
     52     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
     53         match self {
     54             Self::BlockConflictsWithLocalChain { height } => {
     55                 write!(
     56                     formatter,
     57                     "block at height {height} conflicts with local chain"
     58                 )
     59             }
     60             Self::UnexpectedBlockHeight { expected, actual } => {
     61                 write!(formatter, "expected block height {expected}, got {actual}")
     62             }
     63             Self::BlockDoesNotExtendLocalTip => {
     64                 formatter.write_str("block does not extend local tip")
     65             }
     66             Self::BlockBeforeFinalizerRankSlot {
     67                 rank,
     68                 min_timestamp,
     69             } => write!(
     70                 formatter,
     71                 "block timestamp is before finalizer rank {rank} time slot {min_timestamp}"
     72             ),
     73             Self::BlockTimestampTooFarInFuture => {
     74                 formatter.write_str("block timestamp is too far in the future")
     75             }
     76             Self::BurnBundleParentMismatch => {
     77                 formatter.write_str("burn bundle parent hash is invalid")
     78             }
     79             Self::BurnAnchorOutsidePendingWindow => formatter.write_str(
     80                 "burn transaction anchor is not valid for either of the next two block heights",
     81             ),
     82             Self::MineAnchorNotOnChain => {
     83                 formatter.write_str("mine transaction anchor is not on this chain")
     84             }
     85             Self::MineAnchorLimitReached => {
     86                 formatter.write_str("mine transaction anchor limit reached")
     87             }
     88         }
     89     }
     90 }
     91 
     92 impl Error for ValidationError {}
     93 
     94 pub(crate) fn error_has_validation(
     95     error: &anyhow::Error,
     96     predicate: impl Fn(ValidationError) -> bool,
     97 ) -> bool {
     98     error.chain().any(|cause| {
     99         cause
    100             .downcast_ref::<ValidationError>()
    101             .copied()
    102             .is_some_and(&predicate)
    103     })
    104 }