bitcoin_units/
sequence.rs1use core::fmt;
18
19#[cfg(feature = "arbitrary")]
20use arbitrary::{Arbitrary, Unstructured};
21#[cfg(feature = "serde")]
22use serde::{Deserialize, Serialize};
23
24use crate::locktime::relative::error::TimeOverflowError;
25use crate::locktime::relative::{self, NumberOf512Seconds};
26use crate::parse_int::{self, PrefixedHexError, UnprefixedHexError};
27
28#[rustfmt::skip] #[cfg(feature = "encoding")]
30#[doc(no_inline)]
31pub use self::error::SequenceDecoderError;
32
33#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
35#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
36pub struct Sequence(pub u32);
37
38impl Sequence {
39 pub const MAX: Self = Self(0xFFFF_FFFF);
43
44 pub const ZERO: Self = Self(0);
48
49 pub const FINAL: Self = Self::MAX;
51
52 pub const ENABLE_LOCKTIME_NO_RBF: Self = Self::MIN_NO_RBF;
55
56 pub const ENABLE_LOCKTIME_AND_RBF: Self = Self(0xFFFF_FFFD);
61
62 pub const SIZE: usize = 4; const MIN_NO_RBF: Self = Self(0xFFFF_FFFE);
73
74 const LOCK_TIME_DISABLE_FLAG_MASK: u32 = 0x8000_0000;
76
77 pub(super) const LOCK_TYPE_MASK: u32 = 0x0040_0000;
79
80 #[inline]
82 pub fn enables_absolute_lock_time(self) -> bool { self != Self::MAX }
83
84 #[inline]
104 pub fn is_final(self) -> bool { !self.enables_absolute_lock_time() }
105
106 #[inline]
111 pub fn is_rbf(self) -> bool { self < Self::MIN_NO_RBF }
112
113 #[inline]
115 pub fn is_relative_lock_time(self) -> bool { self.0 & Self::LOCK_TIME_DISABLE_FLAG_MASK == 0 }
116
117 #[inline]
119 pub fn is_height_locked(self) -> bool {
120 self.is_relative_lock_time() && (self.0 & Self::LOCK_TYPE_MASK == 0)
121 }
122
123 #[inline]
125 pub fn is_time_locked(self) -> bool {
126 self.is_relative_lock_time() && (self.0 & Self::LOCK_TYPE_MASK > 0)
127 }
128
129 #[inline]
136 pub fn from_hex(s: &str) -> Result<Self, PrefixedHexError> {
137 let lock_time = parse_int::hex_u32_prefixed(s)?;
138 Ok(Self::from_consensus(lock_time))
139 }
140
141 #[inline]
148 pub fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError> {
149 let lock_time = parse_int::hex_u32_unprefixed(s)?;
150 Ok(Self::from_consensus(lock_time))
151 }
152
153 #[inline]
155 pub fn from_height(height: u16) -> Self { Self(u32::from(height)) }
156
157 #[inline]
162 pub fn from_512_second_intervals(intervals: u16) -> Self {
163 Self(u32::from(intervals) | Self::LOCK_TYPE_MASK)
164 }
165
166 #[inline]
176 pub fn from_seconds_floor(seconds: u32) -> Result<Self, TimeOverflowError> {
177 let intervals = NumberOf512Seconds::from_seconds_floor(seconds)?;
178 Ok(Self::from_512_second_intervals(intervals.to_512_second_intervals()))
179 }
180
181 #[inline]
191 pub fn from_seconds_ceil(seconds: u32) -> Result<Self, TimeOverflowError> {
192 let intervals = NumberOf512Seconds::from_seconds_ceil(seconds)?;
193 Ok(Self::from_512_second_intervals(intervals.to_512_second_intervals()))
194 }
195
196 #[inline]
198 pub fn from_consensus(n: u32) -> Self { Self(n) }
199
200 #[inline]
202 pub const fn to_consensus_u32(self) -> u32 { self.0 }
203
204 #[inline]
206 pub fn to_relative_lock_time(self) -> Option<relative::LockTime> {
207 use crate::locktime::relative::{LockTime, NumberOfBlocks};
208
209 if !self.is_relative_lock_time() {
210 return None;
211 }
212
213 let lock_value = self.low_u16();
214
215 if self.is_time_locked() {
216 Some(LockTime::from(NumberOf512Seconds::from_512_second_intervals(lock_value)))
217 } else {
218 Some(LockTime::from(NumberOfBlocks::from(lock_value)))
219 }
220 }
221
222 #[inline]
226 const fn low_u16(self) -> u16 { self.0 as u16 }
227}
228
229crate::internal_macros::impl_fmt_traits_for_u32_wrapper!(Sequence);
230
231impl Default for Sequence {
232 #[inline]
234 fn default() -> Self { Self::MAX }
235}
236
237impl From<Sequence> for u32 {
238 #[inline]
239 fn from(sequence: Sequence) -> Self { sequence.0 }
240}
241
242impl fmt::Display for Sequence {
243 #[inline]
244 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
245}
246
247impl fmt::Debug for Sequence {
248 #[inline]
249 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
250 write!(f, "Sequence({:#010x})", self.0)
252 }
253}
254
255parse_int::impl_parse_str_from_int_infallible!(Sequence, u32, from_consensus);
256
257#[cfg(feature = "encoding")]
258impl encoding::Encode for Sequence {
259 type Encoder<'e> = SequenceEncoder<'e>;
260 #[inline]
261 fn encoder(&self) -> Self::Encoder<'_> {
262 SequenceEncoder::new(encoding::ArrayEncoder::without_length_prefix(
263 self.to_consensus_u32().to_le_bytes(),
264 ))
265 }
266}
267
268#[cfg(feature = "encoding")]
269impl encoding::Decode for Sequence {
270 type Decoder = SequenceDecoder;
271}
272
273#[cfg(feature = "encoding")]
274encoding::encoder_newtype_exact! {
275 #[derive(Debug, Clone)]
277 pub struct SequenceEncoder<'e>(encoding::ArrayEncoder<4>);
278}
279
280#[cfg(feature = "encoding")]
281crate::decoder_newtype! {
282 #[derive(Debug, Clone)]
284 pub struct SequenceDecoder(encoding::ArrayDecoder<4>);
285
286 pub const fn new() -> Self { Self(encoding::ArrayDecoder::new()) }
288
289 fn end(result: Result<[u8; 4], encoding::UnexpectedEofError>) -> Result<Sequence, SequenceDecoderError> {
290 let value = result.map_err(SequenceDecoderError)?;
291 let n = u32::from_le_bytes(value);
292 Ok(Sequence::from_consensus(n))
293 }
294}
295
296pub mod error {
298 #[cfg(feature = "encoding")]
299 use core::convert::Infallible;
300 #[cfg(feature = "encoding")]
301 use core::fmt;
302
303 #[cfg(feature = "encoding")]
304 use internals::write_err;
305
306 #[cfg(feature = "encoding")]
308 #[derive(Debug, Clone, PartialEq, Eq)]
309 pub struct SequenceDecoderError(pub(super) encoding::UnexpectedEofError);
310
311 #[cfg(feature = "encoding")]
312 impl From<Infallible> for SequenceDecoderError {
313 fn from(never: Infallible) -> Self { match never {} }
314 }
315
316 #[cfg(feature = "encoding")]
317 impl fmt::Display for SequenceDecoderError {
318 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
319 write_err!(f, "sequence decoder error"; self.0)
320 }
321 }
322
323 #[cfg(feature = "encoding")]
324 #[cfg(feature = "std")]
325 impl std::error::Error for SequenceDecoderError {
326 #[inline]
327 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
328 }
329}
330
331#[cfg(feature = "arbitrary")]
332#[cfg(feature = "alloc")]
333impl<'a> Arbitrary<'a> for Sequence {
334 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
335 let choice = u.int_in_range(0..=8)?;
337 match choice {
338 0 => Ok(Self::MAX),
339 1 => Ok(Self::ZERO),
340 2 => Ok(Self::MIN_NO_RBF),
341 3 => Ok(Self::ENABLE_LOCKTIME_AND_RBF),
342 4 => Ok(Self::from_consensus(u32::from(relative::NumberOfBlocks::MIN.to_height()))),
343 5 => Ok(Self::from_consensus(u32::from(relative::NumberOfBlocks::MAX.to_height()))),
344 6 => Ok(Self::from_consensus(
345 Self::LOCK_TYPE_MASK
346 | u32::from(relative::NumberOf512Seconds::MIN.to_512_second_intervals()),
347 )),
348 7 => Ok(Self::from_consensus(
349 Self::LOCK_TYPE_MASK
350 | u32::from(relative::NumberOf512Seconds::MAX.to_512_second_intervals()),
351 )),
352 _ => Ok(Self(u.arbitrary()?)),
353 }
354 }
355}
356
357#[cfg(feature = "arbitrary")]
358#[cfg(not(feature = "alloc"))]
359impl<'a> Arbitrary<'a> for Sequence {
360 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
361 let choice = u.int_in_range(0..=4)?;
363 match choice {
364 0 => Ok(Sequence::MAX),
365 1 => Ok(Sequence::ZERO),
366 2 => Ok(Sequence::MIN_NO_RBF),
367 3 => Ok(Sequence::ENABLE_LOCKTIME_AND_RBF),
368 _ => Ok(Sequence(u.arbitrary()?)),
369 }
370 }
371}
372
373#[cfg(test)]
374mod tests {
375 #[cfg(feature = "alloc")]
376 use alloc::format;
377 #[cfg(feature = "alloc")]
378 #[cfg(feature = "encoding")]
379 use alloc::string::ToString;
380 #[cfg(feature = "encoding")]
381 #[cfg(feature = "std")]
382 use std::error::Error;
383
384 #[cfg(feature = "alloc")]
385 #[cfg(feature = "encoding")]
386 use encoding::UnexpectedEofError;
387 #[cfg(feature = "encoding")]
388 use encoding::{Decode as _, Decoder as _};
389
390 use super::*;
391
392 const MAXIMUM_ENCODABLE_SECONDS: u32 = u16::MAX as u32 * 512;
393
394 #[test]
395 fn from_seconds_floor_success() {
396 let expected = Sequence::from_hex("0x0040ffff").unwrap();
397 let actual = Sequence::from_seconds_floor(MAXIMUM_ENCODABLE_SECONDS + 511).unwrap();
398 assert_eq!(actual, expected);
399 }
400
401 #[test]
402 fn from_seconds_floor_causes_overflow_error() {
403 assert!(Sequence::from_seconds_floor(MAXIMUM_ENCODABLE_SECONDS + 512).is_err());
404 }
405
406 #[test]
407 fn from_seconds_ceil_success() {
408 let expected = Sequence::from_hex("0x0040ffff").unwrap();
409 let actual = Sequence::from_seconds_ceil(MAXIMUM_ENCODABLE_SECONDS - 511).unwrap();
410 assert_eq!(actual, expected);
411 }
412
413 #[test]
414 fn from_seconds_ceil_causes_overflow_error() {
415 assert!(Sequence::from_seconds_ceil(MAXIMUM_ENCODABLE_SECONDS + 1).is_err());
416 }
417
418 #[test]
419 fn sequence_number() {
420 let seq_final = Sequence::from_consensus(0xFFFF_FFFF);
421 let seq_non_rbf = Sequence::from_consensus(0xFFFF_FFFE);
422 let block_time_lock = Sequence::from_consensus(0xFFFF);
423 let unit_time_lock = Sequence::from_consensus(0x40_FFFF);
424 let lock_time_disabled = Sequence::from_consensus(0x8000_0000);
425
426 assert!(seq_final.is_final());
427 assert!(!seq_final.is_rbf());
428 assert!(!seq_final.is_relative_lock_time());
429 assert!(!seq_non_rbf.is_rbf());
430 assert!(block_time_lock.is_relative_lock_time());
431 assert!(block_time_lock.is_height_locked());
432 assert!(block_time_lock.is_rbf());
433 assert!(unit_time_lock.is_relative_lock_time());
434 assert!(unit_time_lock.is_time_locked());
435 assert!(unit_time_lock.is_rbf());
436 assert!(!lock_time_disabled.is_relative_lock_time());
437 }
438
439 #[test]
440 fn sequence_from_hex_lower() {
441 let sequence = Sequence::from_hex("0xffffffff").unwrap();
442 assert_eq!(sequence, Sequence::MAX);
443 }
444
445 #[test]
446 fn sequence_from_hex_upper() {
447 let sequence = Sequence::from_hex("0XFFFFFFFF").unwrap();
448 assert_eq!(sequence, Sequence::MAX);
449 }
450
451 #[test]
452 fn sequence_from_unprefixed_hex_lower() {
453 let sequence = Sequence::from_unprefixed_hex("ffffffff").unwrap();
454 assert_eq!(sequence, Sequence::MAX);
455 }
456
457 #[test]
458 fn sequence_from_unprefixed_hex_upper() {
459 let sequence = Sequence::from_unprefixed_hex("FFFFFFFF").unwrap();
460 assert_eq!(sequence, Sequence::MAX);
461 }
462
463 #[test]
464 fn sequence_from_str_hex_invalid_hex_should_err() {
465 let hex = "0xzb93";
466 let result = Sequence::from_hex(hex);
467 assert!(result.is_err());
468 }
469
470 #[test]
471 fn sequence_properties() {
472 let seq_max = Sequence(0xFFFF_FFFF);
473 let seq_no_rbf = Sequence(0xFFFF_FFFE);
474 let seq_rbf = Sequence(0xFFFF_FFFD);
475
476 assert!(seq_max.is_final());
477 assert!(!seq_no_rbf.is_final());
478
479 assert!(seq_no_rbf.enables_absolute_lock_time());
480 assert!(!seq_max.enables_absolute_lock_time());
481
482 assert!(seq_rbf.is_rbf());
483 assert!(!seq_no_rbf.is_rbf());
484
485 let seq_relative = Sequence(0x7FFF_FFFF);
486 assert!(seq_relative.is_relative_lock_time());
487 assert!(!seq_max.is_relative_lock_time());
488
489 let seq_height_locked = Sequence(0x0039_9999);
490 let seq_time_locked = Sequence(0x0040_0000);
491 assert!(seq_height_locked.is_height_locked());
492 assert!(seq_time_locked.is_time_locked());
493 assert!(!seq_time_locked.is_height_locked());
494 assert!(!seq_height_locked.is_time_locked());
495 }
496
497 #[test]
498 #[cfg(feature = "alloc")]
499 fn sequence_formatting() {
500 let sequence = Sequence(0x7FFF_FFFF);
501 assert_eq!(format!("{:x}", sequence), "7fffffff");
502 assert_eq!(format!("{:X}", sequence), "7FFFFFFF");
503
504 let sequence_u32: u32 = sequence.into();
506 assert_eq!(sequence_u32, 0x7FFF_FFFF);
507 }
508
509 #[test]
510 #[cfg(feature = "alloc")]
511 fn sequence_display() {
512 use alloc::string::ToString;
513
514 let sequence = Sequence(0x7FFF_FFFF);
515 let want: u32 = 0x7FFF_FFFF;
516 assert_eq!(format!("{}", sequence), want.to_string());
517 }
518
519 #[test]
520 #[cfg(feature = "alloc")]
521 fn sequence_unprefixed_hex_roundtrip() {
522 let sequence = Sequence(0x7FFF_FFFF);
523
524 let hex_str = format!("{:x}", sequence);
525 assert_eq!(hex_str, "7fffffff");
526
527 let roundtrip = Sequence::from_unprefixed_hex(&hex_str).unwrap();
528 assert_eq!(sequence, roundtrip);
529 }
530
531 #[test]
532 fn sequence_from_height() {
533 assert_eq!(Sequence::from_height(0), Sequence(0));
535 assert_eq!(Sequence::from_height(1), Sequence(1));
536 assert_eq!(Sequence::from_height(0x7FFF), Sequence(0x7FFF));
537 assert_eq!(Sequence::from_height(0xFFFF), Sequence(0xFFFF));
538
539 let step = 512;
541 for v in (0..=u16::MAX).step_by(step) {
542 assert_eq!(Sequence::from_height(v), Sequence(v.into()));
543 }
544 }
545
546 #[test]
547 #[cfg(feature = "alloc")]
548 #[cfg(feature = "encoding")]
549 fn sequence_decoding_error() {
550 let bytes = [0xff, 0xff, 0xff]; let mut decoder = SequenceDecoder::default();
553 assert!(decoder.push_bytes(&mut bytes.as_slice()).unwrap().needs_more());
554
555 let error = decoder.end().unwrap_err();
556 assert!(matches!(error, SequenceDecoderError(UnexpectedEofError { .. })));
557 }
558
559 #[test]
560 #[cfg(feature = "alloc")]
561 fn decoder_error_display_is_non_empty() {
562 #[cfg(feature = "encoding")]
563 {
564 let mut decoder = Sequence::decoder();
566 let _ = decoder.push_bytes(&mut [0u8; 3].as_slice());
567 let e = decoder.end().unwrap_err();
568 assert!(!e.to_string().is_empty());
569 #[cfg(feature = "std")]
570 assert!(e.source().is_some());
571 }
572 }
573}