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