Skip to main content

bitcoin_units/locktime/relative/
error.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Error types for the relative locktime module.
4
5use core::fmt;
6
7use internals::write_err;
8
9use super::{NumberOf512Seconds, NumberOfBlocks};
10
11/// Error returned when a sequence number is parsed as a lock time, but its
12/// "disable" flag is set.
13#[derive(Debug, Clone, Eq, PartialEq)]
14pub struct DisabledLockTimeError(pub(super) u32);
15
16impl DisabledLockTimeError {
17    /// Accessor for the `u32` whose "disable" flag was set, preventing
18    /// it from being parsed as a relative locktime.
19    #[inline]
20    pub fn disabled_locktime_value(&self) -> u32 { self.0 }
21}
22
23impl fmt::Display for DisabledLockTimeError {
24    #[inline]
25    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
26        write!(f, "lock time 0x{:08x} has disable flag set", self.0)
27    }
28}
29
30#[cfg(feature = "std")]
31impl std::error::Error for DisabledLockTimeError {}
32
33/// Error returned when attempting to satisfy lock fails.
34#[derive(Debug, Clone, Eq, PartialEq)]
35pub enum IsSatisfiedByError {
36    /// Error when attempting to satisfy lock by height.
37    Blocks(InvalidHeightError),
38    /// Error when attempting to satisfy lock by time.
39    Time(InvalidTimeError),
40}
41
42impl fmt::Display for IsSatisfiedByError {
43    #[inline]
44    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
45        match *self {
46            Self::Blocks(ref e) => write_err!(f, "blocks"; e),
47            Self::Time(ref e) => write_err!(f, "time"; e),
48        }
49    }
50}
51
52#[cfg(feature = "std")]
53impl std::error::Error for IsSatisfiedByError {
54    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
55        match *self {
56            Self::Blocks(ref e) => Some(e),
57            Self::Time(ref e) => Some(e),
58        }
59    }
60}
61
62/// Error returned when `is_satisfied_by_height` fails.
63#[derive(Debug, Clone, PartialEq, Eq)]
64pub enum IsSatisfiedByHeightError {
65    /// Satisfaction of the lock height value failed.
66    Satisfaction(InvalidHeightError),
67    /// Tried to satisfy a lock-by-height locktime using seconds.
68    // TODO: Hide inner value in a new struct error type.
69    Incompatible(NumberOf512Seconds),
70}
71
72impl fmt::Display for IsSatisfiedByHeightError {
73    #[inline]
74    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
75        match *self {
76            Self::Satisfaction(ref e) => write_err!(f, "satisfaction"; e),
77            Self::Incompatible(time) =>
78                write!(f, "tried to satisfy a lock-by-height locktime using seconds {}", time),
79        }
80    }
81}
82
83#[cfg(feature = "std")]
84impl std::error::Error for IsSatisfiedByHeightError {
85    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
86        match *self {
87            Self::Satisfaction(ref e) => Some(e),
88            Self::Incompatible(_) => None,
89        }
90    }
91}
92
93/// Error returned when `is_satisfied_by_time` fails.
94#[derive(Debug, Clone, PartialEq, Eq)]
95pub enum IsSatisfiedByTimeError {
96    /// Satisfaction of the lock time value failed.
97    Satisfaction(InvalidTimeError),
98    /// Tried to satisfy a lock-by-time locktime using number of blocks.
99    // TODO: Hide inner value in a new struct error type.
100    Incompatible(NumberOfBlocks),
101}
102
103impl fmt::Display for IsSatisfiedByTimeError {
104    #[inline]
105    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
106        match *self {
107            Self::Satisfaction(ref e) => write_err!(f, "satisfaction"; e),
108            Self::Incompatible(blocks) =>
109                write!(f, "tried to satisfy a lock-by-time locktime using blocks {}", blocks),
110        }
111    }
112}
113
114#[cfg(feature = "std")]
115impl std::error::Error for IsSatisfiedByTimeError {
116    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
117        match *self {
118            Self::Satisfaction(ref e) => Some(e),
119            Self::Incompatible(_) => None,
120        }
121    }
122}
123
124/// Error returned when the input time in seconds was too large to be encoded to a 16 bit 512 second interval.
125#[derive(Debug, Clone, PartialEq, Eq)]
126pub struct TimeOverflowError {
127    /// Time interval value in seconds that overflowed.
128    // Private because we maintain an invariant that the `seconds` value does actually overflow.
129    pub(crate) seconds: u32,
130}
131
132impl fmt::Display for TimeOverflowError {
133    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
134        write!(
135            f,
136            "{} seconds is too large to be encoded to a 16 bit 512 second interval",
137            self.seconds
138        )
139    }
140}
141
142#[cfg(feature = "std")]
143impl std::error::Error for TimeOverflowError {}
144
145/// Error returned when `NumberOfBlocks::is_satisfied_by` is incorrectly called.
146#[derive(Debug, Clone, PartialEq, Eq)]
147pub struct InvalidHeightError {
148    /// The `chain_tip` argument.
149    pub(crate) chain_tip: crate::BlockHeight,
150    /// The `utxo_mined_at` argument.
151    pub(crate) utxo_mined_at: crate::BlockHeight,
152}
153
154impl fmt::Display for InvalidHeightError {
155    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
156        write!(f, "is_satisfied_by arguments invalid (probably the wrong way around) chain_tip: {} utxo_mined_at: {}", self.chain_tip, self.utxo_mined_at
157        )
158    }
159}
160
161#[cfg(feature = "std")]
162impl std::error::Error for InvalidHeightError {}
163
164/// Error returned when `NumberOf512Seconds::is_satisfied_by` is incorrectly called.
165#[derive(Debug, Clone, PartialEq, Eq)]
166pub struct InvalidTimeError {
167    /// The `chain_tip` argument.
168    pub(crate) chain_tip: crate::BlockMtp,
169    /// The `utxo_mined_at` argument.
170    pub(crate) utxo_mined_at: crate::BlockMtp,
171}
172
173impl fmt::Display for InvalidTimeError {
174    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
175        write!(f, "is_satisfied_by arguments invalid (probably the wrong way around) chain_tip: {} utxo_mined_at: {}", self.chain_tip, self.utxo_mined_at
176        )
177    }
178}
179
180#[cfg(feature = "std")]
181impl std::error::Error for InvalidTimeError {}