bitcoin_units/
sequence.rs1#[cfg(feature = "encoding")]
18use core::convert::Infallible;
19use core::fmt;
20
21#[cfg(feature = "arbitrary")]
22use arbitrary::{Arbitrary, Unstructured};
23#[cfg(feature = "encoding")]
24use internals::write_err;
25#[cfg(feature = "serde")]
26use serde::{Deserialize, Serialize};
27
28use crate::locktime::relative::error::TimeOverflowError;
29use crate::locktime::relative::{self, NumberOf512Seconds};
30use crate::parse_int::{self, PrefixedHexError, UnprefixedHexError};
31
32#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
34#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
35pub struct Sequence(pub u32);
36
37impl Sequence {
38 pub const MAX: Self = Self(0xFFFF_FFFF);
42 pub const ZERO: Self = Self(0);
46 pub const FINAL: Self = Self::MAX;
48 pub const ENABLE_LOCKTIME_NO_RBF: Self = Self::MIN_NO_RBF;
51 #[deprecated(since = "1.0.0-rc.0", note = "use `ENABLE_LOCKTIME_AND_RBF` instead")]
54 pub const ENABLE_RBF_NO_LOCKTIME: Self = Self(0xFFFF_FFFD);
55 pub const ENABLE_LOCKTIME_AND_RBF: Self = Self(0xFFFF_FFFD);
60
61 pub const SIZE: usize = 4; const MIN_NO_RBF: Self = Self(0xFFFF_FFFE);
72 const LOCK_TIME_DISABLE_FLAG_MASK: u32 = 0x8000_0000;
74 pub(super) const LOCK_TYPE_MASK: u32 = 0x0040_0000;
76
77 #[inline]
79 pub fn enables_absolute_lock_time(self) -> bool { self != Self::MAX }
80
81 #[inline]
101 pub fn is_final(self) -> bool { !self.enables_absolute_lock_time() }
102
103 #[inline]
108 pub fn is_rbf(self) -> bool { self < Self::MIN_NO_RBF }
109
110 #[inline]
112 pub fn is_relative_lock_time(self) -> bool { self.0 & Self::LOCK_TIME_DISABLE_FLAG_MASK == 0 }
113
114 #[inline]
116 pub fn is_height_locked(self) -> bool {
117 self.is_relative_lock_time() && (self.0 & Self::LOCK_TYPE_MASK == 0)
118 }
119
120 #[inline]
122 pub fn is_time_locked(self) -> bool {
123 self.is_relative_lock_time() && (self.0 & Self::LOCK_TYPE_MASK > 0)
124 }
125
126 #[inline]
133 pub fn from_hex(s: &str) -> Result<Self, PrefixedHexError> {
134 let lock_time = parse_int::hex_u32_prefixed(s)?;
135 Ok(Self::from_consensus(lock_time))
136 }
137
138 #[inline]
145 pub fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError> {
146 let lock_time = parse_int::hex_u32_unprefixed(s)?;
147 Ok(Self::from_consensus(lock_time))
148 }
149
150 #[inline]
152 pub fn from_height(height: u16) -> Self { Self(u32::from(height)) }
153
154 #[inline]
159 pub fn from_512_second_intervals(intervals: u16) -> Self {
160 Self(u32::from(intervals) | Self::LOCK_TYPE_MASK)
161 }
162
163 #[inline]
173 pub fn from_seconds_floor(seconds: u32) -> Result<Self, TimeOverflowError> {
174 let intervals = NumberOf512Seconds::from_seconds_floor(seconds)?;
175 Ok(Self::from_512_second_intervals(intervals.to_512_second_intervals()))
176 }
177
178 #[inline]
188 pub fn from_seconds_ceil(seconds: u32) -> Result<Self, TimeOverflowError> {
189 let intervals = NumberOf512Seconds::from_seconds_ceil(seconds)?;
190 Ok(Self::from_512_second_intervals(intervals.to_512_second_intervals()))
191 }
192
193 #[inline]
195 pub fn from_consensus(n: u32) -> Self { Self(n) }
196
197 #[inline]
199 pub const fn to_consensus_u32(self) -> u32 { self.0 }
200
201 #[cfg(feature = "alloc")]
203 #[inline]
204 #[deprecated(since = "1.0.0-rc.0", note = "use `format!(\"{var:x}\")` instead")]
205 pub fn to_hex(self) -> alloc::string::String { alloc::format!("{:x}", self) }
206
207 #[inline]
209 pub fn to_relative_lock_time(self) -> Option<relative::LockTime> {
210 use crate::locktime::relative::{LockTime, NumberOfBlocks};
211
212 if !self.is_relative_lock_time() {
213 return None;
214 }
215
216 let lock_value = self.low_u16();
217
218 if self.is_time_locked() {
219 Some(LockTime::from(NumberOf512Seconds::from_512_second_intervals(lock_value)))
220 } else {
221 Some(LockTime::from(NumberOfBlocks::from(lock_value)))
222 }
223 }
224
225 #[inline]
229 const fn low_u16(self) -> u16 { self.0 as u16 }
230}
231
232crate::internal_macros::impl_fmt_traits_for_u32_wrapper!(Sequence);
233
234impl Default for Sequence {
235 #[inline]
237 fn default() -> Self { Self::MAX }
238}
239
240impl From<Sequence> for u32 {
241 #[inline]
242 fn from(sequence: Sequence) -> Self { sequence.0 }
243}
244
245impl fmt::Display for Sequence {
246 #[inline]
247 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
248}
249
250impl fmt::Debug for Sequence {
251 #[inline]
252 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
253 write!(f, "Sequence({:#010x})", self.0)
255 }
256}
257
258#[cfg(feature = "alloc")]
259parse_int::impl_parse_str_from_int_infallible!(Sequence, u32, from_consensus);
260
261#[cfg(feature = "encoding")]
262encoding::encoder_newtype_exact! {
263 pub struct SequenceEncoder<'e>(encoding::ArrayEncoder<4>);
265}
266
267#[cfg(feature = "encoding")]
268impl encoding::Encodable for Sequence {
269 type Encoder<'e> = SequenceEncoder<'e>;
270 fn encoder(&self) -> Self::Encoder<'_> {
271 SequenceEncoder::new(encoding::ArrayEncoder::without_length_prefix(
272 self.to_consensus_u32().to_le_bytes(),
273 ))
274 }
275}
276
277#[cfg(feature = "encoding")]
279pub struct SequenceDecoder(encoding::ArrayDecoder<4>);
280
281#[cfg(feature = "encoding")]
282impl Default for SequenceDecoder {
283 fn default() -> Self { Self::new() }
284}
285
286#[cfg(feature = "encoding")]
287impl SequenceDecoder {
288 pub const fn new() -> Self { Self(encoding::ArrayDecoder::new()) }
290}
291
292#[cfg(feature = "encoding")]
293impl encoding::Decoder for SequenceDecoder {
294 type Output = Sequence;
295 type Error = SequenceDecoderError;
296
297 #[inline]
298 fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error> {
299 self.0.push_bytes(bytes).map_err(SequenceDecoderError)
300 }
301
302 #[inline]
303 fn end(self) -> Result<Self::Output, Self::Error> {
304 let n = u32::from_le_bytes(self.0.end().map_err(SequenceDecoderError)?);
305 Ok(Sequence::from_consensus(n))
306 }
307
308 #[inline]
309 fn read_limit(&self) -> usize { self.0.read_limit() }
310}
311
312#[cfg(feature = "encoding")]
313impl encoding::Decodable for Sequence {
314 type Decoder = SequenceDecoder;
315 fn decoder() -> Self::Decoder { SequenceDecoder(encoding::ArrayDecoder::<4>::new()) }
316}
317
318#[cfg(feature = "encoding")]
320#[derive(Debug, Clone, PartialEq, Eq)]
321pub struct SequenceDecoderError(encoding::UnexpectedEofError);
322
323#[cfg(feature = "encoding")]
324impl From<Infallible> for SequenceDecoderError {
325 fn from(never: Infallible) -> Self { match never {} }
326}
327
328#[cfg(feature = "encoding")]
329impl fmt::Display for SequenceDecoderError {
330 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
331 write_err!(f, "sequence decoder error"; self.0)
332 }
333}
334
335#[cfg(all(feature = "std", feature = "encoding"))]
336impl std::error::Error for SequenceDecoderError {
337 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
338}
339
340#[cfg(feature = "arbitrary")]
341#[cfg(feature = "alloc")]
342impl<'a> Arbitrary<'a> for Sequence {
343 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
344 let choice = u.int_in_range(0..=8)?;
346 match choice {
347 0 => Ok(Self::MAX),
348 1 => Ok(Self::ZERO),
349 2 => Ok(Self::MIN_NO_RBF),
350 3 => Ok(Self::ENABLE_LOCKTIME_AND_RBF),
351 4 => Ok(Self::from_consensus(u32::from(relative::NumberOfBlocks::MIN.to_height()))),
352 5 => Ok(Self::from_consensus(u32::from(relative::NumberOfBlocks::MAX.to_height()))),
353 6 => Ok(Self::from_consensus(
354 Self::LOCK_TYPE_MASK
355 | u32::from(relative::NumberOf512Seconds::MIN.to_512_second_intervals()),
356 )),
357 7 => Ok(Self::from_consensus(
358 Self::LOCK_TYPE_MASK
359 | u32::from(relative::NumberOf512Seconds::MAX.to_512_second_intervals()),
360 )),
361 _ => Ok(Self(u.arbitrary()?)),
362 }
363 }
364}
365
366#[cfg(feature = "arbitrary")]
367#[cfg(not(feature = "alloc"))]
368impl<'a> Arbitrary<'a> for Sequence {
369 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
370 let choice = u.int_in_range(0..=4)?;
372 match choice {
373 0 => Ok(Sequence::MAX),
374 1 => Ok(Sequence::ZERO),
375 2 => Ok(Sequence::MIN_NO_RBF),
376 3 => Ok(Sequence::ENABLE_LOCKTIME_AND_RBF),
377 _ => Ok(Sequence(u.arbitrary()?)),
378 }
379 }
380}
381
382#[cfg(test)]
383mod tests {
384 #[cfg(feature = "alloc")]
385 use alloc::format;
386
387 #[cfg(feature = "encoding")]
388 use encoding::Decoder as _;
389 #[cfg(all(feature = "encoding", feature = "alloc"))]
390 use encoding::UnexpectedEofError;
391
392 use super::*;
393
394 const MAXIMUM_ENCODABLE_SECONDS: u32 = u16::MAX as u32 * 512;
395
396 #[test]
397 fn from_seconds_floor_success() {
398 let expected = Sequence::from_hex("0x0040ffff").unwrap();
399 let actual = Sequence::from_seconds_floor(MAXIMUM_ENCODABLE_SECONDS + 511).unwrap();
400 assert_eq!(actual, expected);
401 }
402
403 #[test]
404 fn from_seconds_floor_causes_overflow_error() {
405 assert!(Sequence::from_seconds_floor(MAXIMUM_ENCODABLE_SECONDS + 512).is_err());
406 }
407
408 #[test]
409 fn from_seconds_ceil_success() {
410 let expected = Sequence::from_hex("0x0040ffff").unwrap();
411 let actual = Sequence::from_seconds_ceil(MAXIMUM_ENCODABLE_SECONDS - 511).unwrap();
412 assert_eq!(actual, expected);
413 }
414
415 #[test]
416 fn from_seconds_ceil_causes_overflow_error() {
417 assert!(Sequence::from_seconds_ceil(MAXIMUM_ENCODABLE_SECONDS + 1).is_err());
418 }
419
420 #[test]
421 fn sequence_properties() {
422 let seq_max = Sequence(0xFFFF_FFFF);
423 let seq_no_rbf = Sequence(0xFFFF_FFFE);
424 let seq_rbf = Sequence(0xFFFF_FFFD);
425
426 assert!(seq_max.is_final());
427 assert!(!seq_no_rbf.is_final());
428
429 assert!(seq_no_rbf.enables_absolute_lock_time());
430 assert!(!seq_max.enables_absolute_lock_time());
431
432 assert!(seq_rbf.is_rbf());
433 assert!(!seq_no_rbf.is_rbf());
434
435 let seq_relative = Sequence(0x7FFF_FFFF);
436 assert!(seq_relative.is_relative_lock_time());
437 assert!(!seq_max.is_relative_lock_time());
438
439 let seq_height_locked = Sequence(0x0039_9999);
440 let seq_time_locked = Sequence(0x0040_0000);
441 assert!(seq_height_locked.is_height_locked());
442 assert!(seq_time_locked.is_time_locked());
443 assert!(!seq_time_locked.is_height_locked());
444 assert!(!seq_height_locked.is_time_locked());
445 }
446
447 #[test]
448 #[cfg(feature = "alloc")]
449 fn sequence_formatting() {
450 let sequence = Sequence(0x7FFF_FFFF);
451 assert_eq!(format!("{:x}", sequence), "7fffffff");
452 assert_eq!(format!("{:X}", sequence), "7FFFFFFF");
453
454 let sequence_u32: u32 = sequence.into();
456 assert_eq!(sequence_u32, 0x7FFF_FFFF);
457 }
458
459 #[test]
460 #[cfg(feature = "alloc")]
461 fn sequence_display() {
462 use alloc::string::ToString;
463
464 let sequence = Sequence(0x7FFF_FFFF);
465 let want: u32 = 0x7FFF_FFFF;
466 assert_eq!(format!("{}", sequence), want.to_string());
467 }
468
469 #[test]
470 #[cfg(feature = "alloc")]
471 fn sequence_unprefixed_hex_roundtrip() {
472 let sequence = Sequence(0x7FFF_FFFF);
473
474 let hex_str = format!("{:x}", sequence);
475 assert_eq!(hex_str, "7fffffff");
476
477 let roundtrip = Sequence::from_unprefixed_hex(&hex_str).unwrap();
478 assert_eq!(sequence, roundtrip);
479 }
480
481 #[test]
482 fn sequence_from_height() {
483 assert_eq!(Sequence::from_height(0), Sequence(0));
485 assert_eq!(Sequence::from_height(1), Sequence(1));
486 assert_eq!(Sequence::from_height(0x7FFF), Sequence(0x7FFF));
487 assert_eq!(Sequence::from_height(0xFFFF), Sequence(0xFFFF));
488
489 let step = 512;
491 for v in (0..=u16::MAX).step_by(step) {
492 assert_eq!(Sequence::from_height(v), Sequence(v.into()));
493 }
494 }
495
496 #[test]
497 #[cfg(all(feature = "encoding", feature = "alloc"))]
498 fn sequence_decoding_error() {
499 let bytes = [0xff, 0xff, 0xff]; let mut decoder = SequenceDecoder::default();
502 assert!(decoder.push_bytes(&mut bytes.as_slice()).unwrap());
503
504 let error = decoder.end().unwrap_err();
505 assert!(matches!(error, SequenceDecoderError(UnexpectedEofError { .. })));
506 }
507}