1use super::Clause;
8use schemars::JsonSchema;
9use serde::{Deserialize, Serialize};
10use std::convert::TryFrom;
11use std::convert::TryInto;
12use std::default::Default;
13use std::fmt;
14use std::marker::PhantomData;
15use std::time::Duration;
16#[derive(Debug)]
18pub enum LockTimeError {
19 DurationTooLong(Duration),
21 TimeTooFarInPast(Duration),
23 HeightTooHigh(u32),
25 UnknownSeqType(u32),
27}
28
29pub mod type_tags {
32 pub trait Absolutivity {
34 const IS_ABSOLUTE: bool;
36 }
37 pub trait TimeType {
39 const IS_HEIGHT: bool;
41 }
42 use super::*;
43 #[derive(JsonSchema, Serialize, Deserialize, Copy, Clone, PartialOrd, Ord, Eq, PartialEq)]
45 pub struct Rel;
46 #[derive(JsonSchema, Serialize, Deserialize, Copy, Clone, PartialOrd, Ord, Eq, PartialEq)]
48 pub struct Abs;
49 #[derive(JsonSchema, Serialize, Deserialize, Copy, Clone, PartialOrd, Ord, Eq, PartialEq)]
51 pub struct Height;
52 #[derive(JsonSchema, Serialize, Deserialize, Copy, Clone, PartialOrd, Ord, Eq, PartialEq)]
54 pub struct MTP;
55}
56use type_tags::*;
57
58#[derive(JsonSchema, Serialize, Deserialize, Copy, Clone, PartialOrd, Ord, Eq, PartialEq)]
61#[serde(transparent)]
62pub struct LockTime<RelOrAbs: Absolutivity, HeightOrTime: TimeType>(
63 u32,
64 #[serde(skip)] PhantomData<(RelOrAbs, HeightOrTime)>,
65);
66#[derive(JsonSchema, Serialize, Deserialize, Copy, Clone, PartialOrd, Ord, Eq, PartialEq)]
67pub enum AnyRelTimeLock {
70 RH(RelHeight),
73 RT(RelTime),
76}
77
78#[derive(JsonSchema, Serialize, Deserialize, Copy, Clone, PartialOrd, Ord, Eq, PartialEq)]
79pub enum AnyAbsTimeLock {
82 AH(AbsHeight),
85 AT(AbsTime),
88}
89#[derive(JsonSchema, Serialize, Deserialize, Copy, Clone)]
90pub enum AnyTimeLock {
93 R(AnyRelTimeLock),
95 A(AnyAbsTimeLock),
97}
98
99mod alias {
101 use super::*;
102 pub type RelHeight = LockTime<Rel, Height>;
104 pub type RelTime = LockTime<Rel, MTP>;
106 pub type AbsHeight = LockTime<Abs, Height>;
108 pub type AbsTime = LockTime<Abs, MTP>;
110 pub const BIG_PAST_DATE: AbsTime = LockTime(1_600_000_000u32, PhantomData);
112 pub const START_OF_TIME: AbsTime = LockTime(500_000_000, PhantomData);
114}
115pub use alias::*;
116
117mod trait_impls {
118 use super::*;
119 impl Absolutivity for Rel {
120 const IS_ABSOLUTE: bool = false;
121 }
122 impl Absolutivity for Abs {
123 const IS_ABSOLUTE: bool = true;
124 }
125 impl TimeType for Height {
126 const IS_HEIGHT: bool = true;
127 }
128 impl TimeType for MTP {
129 const IS_HEIGHT: bool = false;
130 }
131
132 impl<A, TT> LockTime<A, TT>
133 where
134 A: Absolutivity,
135 TT: TimeType,
136 {
137 pub fn get(&self) -> u32 {
139 self.0
140 }
141 }
142 impl AnyRelTimeLock {
143 pub fn get(&self) -> u32 {
145 match self {
146 AnyRelTimeLock::RH(u) => u.get(),
147 AnyRelTimeLock::RT(u) => u.get(),
148 }
149 }
150 }
151
152 impl AnyAbsTimeLock {
153 pub fn get(&self) -> u32 {
155 match self {
156 AnyAbsTimeLock::AH(u) => u.get(),
157 AnyAbsTimeLock::AT(u) => u.get(),
158 }
159 }
160 }
161
162 impl AnyTimeLock {
163 pub fn get(&self) -> u32 {
165 match self {
166 AnyTimeLock::A(u) => u.get(),
167 AnyTimeLock::R(u) => u.get(),
168 }
169 }
170 }
171
172 impl<A, TT> From<LockTime<A, TT>> for Clause
173 where
174 A: Absolutivity,
175 TT: TimeType,
176 {
177 fn from(lt: LockTime<A, TT>) -> Clause {
178 match (A::IS_ABSOLUTE, TT::IS_HEIGHT) {
179 (true, true) => Clause::After(lt.0),
180 (true, false) => Clause::After(lt.0),
181 (false, true) => Clause::Older(lt.0),
182 (false, false) => Clause::Older(lt.0),
183 }
184 }
185 }
186
187 impl fmt::Display for LockTimeError {
188 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189 write!(f, "{:?}", self)
190 }
191 }
192 impl std::error::Error for LockTimeError {}
193
194 impl TryFrom<u32> for AbsTime {
195 type Error = LockTimeError;
196 fn try_from(t: u32) -> Result<Self, Self::Error> {
197 if t < START_OF_TIME.get() {
198 Err(LockTimeError::TimeTooFarInPast(Duration::from_secs(
199 t as u64,
200 )))
201 } else {
202 Ok(Self(t, Default::default()))
203 }
204 }
205 }
206 impl TryFrom<u32> for AbsHeight {
207 type Error = LockTimeError;
208 fn try_from(u: u32) -> Result<Self, Self::Error> {
209 if u < START_OF_TIME.get() {
210 Ok(Self(u, Default::default()))
211 } else {
212 Err(LockTimeError::HeightTooHigh(u))
213 }
214 }
215 }
216 impl From<u16> for RelTime {
217 fn from(u: u16) -> Self {
218 Self((u as u32) | (1 << 22), Default::default())
220 }
221 }
222 impl From<u16> for RelHeight {
223 fn from(u: u16) -> Self {
224 Self(u as u32, Default::default())
226 }
227 }
228
229 impl TryFrom<Duration> for RelTime {
230 type Error = LockTimeError;
231 fn try_from(u: Duration) -> Result<Self, Self::Error> {
232 u16::try_from(u.as_secs() / 512)
233 .or(Err(LockTimeError::DurationTooLong(u)))
234 .map(From::from)
235 }
236 }
237
238 impl TryFrom<Duration> for AbsTime {
239 type Error = LockTimeError;
240 fn try_from(u: Duration) -> Result<Self, Self::Error> {
241 u32::try_from(u.as_secs())
242 .or(Err(LockTimeError::DurationTooLong(u)))?
243 .try_into()
244 }
245 }
246
247 impl From<AnyRelTimeLock> for Clause {
248 fn from(lt: AnyRelTimeLock) -> Self {
249 match lt {
250 AnyRelTimeLock::RH(a) => a.into(),
251 AnyRelTimeLock::RT(a) => a.into(),
252 }
253 }
254 }
255 impl From<AnyAbsTimeLock> for Clause {
256 fn from(lt: AnyAbsTimeLock) -> Self {
257 match lt {
258 AnyAbsTimeLock::AH(a) => a.into(),
259 AnyAbsTimeLock::AT(a) => a.into(),
260 }
261 }
262 }
263 impl From<AnyTimeLock> for Clause {
264 fn from(lt: AnyTimeLock) -> Self {
265 match lt {
266 AnyTimeLock::A(a) => a.into(),
267 AnyTimeLock::R(a) => a.into(),
268 }
269 }
270 }
271
272 impl From<RelTime> for AnyRelTimeLock {
273 fn from(lt: RelTime) -> Self {
274 AnyRelTimeLock::RT(lt)
275 }
276 }
277 impl From<AbsHeight> for AnyAbsTimeLock {
278 fn from(lt: AbsHeight) -> Self {
279 AnyAbsTimeLock::AH(lt)
280 }
281 }
282 impl From<AbsTime> for AnyAbsTimeLock {
283 fn from(lt: AbsTime) -> Self {
284 AnyAbsTimeLock::AT(lt)
285 }
286 }
287
288 impl From<RelHeight> for AnyRelTimeLock {
289 fn from(lt: RelHeight) -> Self {
290 AnyRelTimeLock::RH(lt)
291 }
292 }
293
294 impl From<AnyAbsTimeLock> for AnyTimeLock {
295 fn from(lt: AnyAbsTimeLock) -> Self {
296 AnyTimeLock::A(lt)
297 }
298 }
299 impl From<AnyRelTimeLock> for AnyTimeLock {
300 fn from(lt: AnyRelTimeLock) -> Self {
301 AnyTimeLock::R(lt)
302 }
303 }
304}