bitcoin_primitives/
sequence.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Bitcoin transaction input sequence number.
4//!
5//! The sequence field is used for:
6//! - Indicating whether absolute lock-time (specified in `lock_time` field of [`Transaction`]) is enabled.
7//! - Indicating and encoding [BIP-68] relative lock-times.
8//! - Indicating whether a transaction opts-in to [BIP-125] replace-by-fee.
9//!
10//! Note that transactions spending an output with `OP_CHECKLOCKTIMEVERIFY`MUST NOT use
11//! `Sequence::MAX` for the corresponding input. [BIP-65]
12//!
13//! [BIP-65]: <https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki>
14//! [BIP-68]: <https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki>
15//! [BIP-125]: <https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki>
16
17use core::fmt;
18
19#[cfg(feature = "arbitrary")]
20use arbitrary::{Arbitrary, Unstructured};
21#[cfg(feature = "serde")]
22use serde::{Deserialize, Serialize};
23#[cfg(feature = "alloc")]
24use units::locktime::relative::TimeOverflowError;
25#[cfg(feature = "alloc")]
26use units::parse::{self, PrefixedHexError, UnprefixedHexError};
27
28#[cfg(feature = "alloc")]
29use crate::locktime::relative;
30#[cfg(all(doc, feature = "alloc"))]
31use crate::transaction::Transaction;
32
33/// Bitcoin transaction input sequence number.
34#[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    /// The maximum allowable sequence number.
40    ///
41    /// The sequence number that disables replace-by-fee, absolute lock time and relative lock time.
42    pub const MAX: Self = Sequence(0xFFFFFFFF);
43    /// Zero value sequence.
44    ///
45    /// This sequence number enables replace-by-fee and absolute lock time.
46    pub const ZERO: Self = Sequence(0);
47    /// The sequence number that disables replace-by-fee, absolute lock time and relative lock time.
48    pub const FINAL: Self = Sequence::MAX;
49    /// The sequence number that enables absolute lock time but disables replace-by-fee
50    /// and relative lock time.
51    pub const ENABLE_LOCKTIME_NO_RBF: Self = Sequence::MIN_NO_RBF;
52    /// The sequence number that enables replace-by-fee and absolute lock time but
53    /// disables relative lock time.
54    #[deprecated(since = "TBD", note = "use `ENABLE_LOCKTIME_AND_RBF` instead")]
55    pub const ENABLE_RBF_NO_LOCKTIME: Self = Sequence(0xFFFFFFFD);
56    /// The maximum sequence number that enables replace-by-fee and absolute lock time but
57    /// disables relative lock time.
58    ///
59    /// This sequence number has no meaning other than to enable RBF and the absolute locktime.
60    pub const ENABLE_LOCKTIME_AND_RBF: Self = Sequence(0xFFFFFFFD);
61
62    /// The number of bytes that a sequence number contributes to the size of a transaction.
63    pub const SIZE: usize = 4; // Serialized length of a u32.
64
65    /// The lowest sequence number that does not opt-in for replace-by-fee.
66    ///
67    /// A transaction is considered to have opted in to replacement of itself
68    /// if any of it's inputs have a `Sequence` number less than this value
69    /// (Explicit Signalling [BIP-125]).
70    ///
71    /// [BIP-125]: <https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki]>
72    const MIN_NO_RBF: Self = Sequence(0xFFFFFFFE);
73    /// BIP-68 relative lock time disable flag mask.
74    const LOCK_TIME_DISABLE_FLAG_MASK: u32 = 0x80000000;
75    /// BIP-68 relative lock time type flag mask.
76    const LOCK_TYPE_MASK: u32 = 0x00400000;
77
78    /// Returns `true` if the sequence number enables absolute lock-time ([`Transaction::lock_time`]).
79    #[inline]
80    pub fn enables_absolute_lock_time(&self) -> bool { *self != Sequence::MAX }
81
82    /// Returns `true` if the sequence number indicates that the transaction is finalized.
83    ///
84    /// Instead of this method please consider using `!enables_absolute_lock_time` because it
85    /// is equivalent and improves readability for those not steeped in Bitcoin folklore.
86    ///
87    /// ## Historical note
88    ///
89    /// The term 'final' is an archaic Bitcoin term, it may have come about because the sequence
90    /// number in the original Bitcoin code was intended to be incremented in order to replace a
91    /// transaction, so once the sequence number got to `u64::MAX` it could no longer be increased,
92    /// hence it was 'final'.
93    ///
94    ///
95    /// Some other references to the term:
96    /// - `CTxIn::SEQUENCE_FINAL` in the Bitcoin Core code.
97    /// - [BIP-112]: "BIP 68 prevents a non-final transaction from being selected for inclusion in a
98    ///   block until the corresponding input has reached the specified age"
99    ///
100    /// [BIP-112]: <https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki>
101    #[inline]
102    pub fn is_final(&self) -> bool { !self.enables_absolute_lock_time() }
103
104    /// Returns true if the transaction opted-in to BIP125 replace-by-fee.
105    ///
106    /// Replace by fee is signaled by the sequence being less than 0xfffffffe which is checked by
107    /// this method. Note, this is the highest "non-final" value (see [`Sequence::is_final`]).
108    #[inline]
109    pub fn is_rbf(&self) -> bool { *self < Sequence::MIN_NO_RBF }
110
111    /// Returns `true` if the sequence has a relative lock-time.
112    #[inline]
113    pub fn is_relative_lock_time(&self) -> bool {
114        self.0 & Sequence::LOCK_TIME_DISABLE_FLAG_MASK == 0
115    }
116
117    /// Returns `true` if the sequence number encodes a block based relative lock-time.
118    #[inline]
119    pub fn is_height_locked(&self) -> bool {
120        self.is_relative_lock_time() & (self.0 & Sequence::LOCK_TYPE_MASK == 0)
121    }
122
123    /// Returns `true` if the sequence number encodes a time interval based relative lock-time.
124    #[inline]
125    pub fn is_time_locked(&self) -> bool {
126        self.is_relative_lock_time() & (self.0 & Sequence::LOCK_TYPE_MASK > 0)
127    }
128
129    /// Constructs a new `Sequence` from a prefixed hex string.
130    #[cfg(feature = "alloc")]
131    pub fn from_hex(s: &str) -> Result<Self, PrefixedHexError> {
132        let lock_time = parse::hex_u32_prefixed(s)?;
133        Ok(Self::from_consensus(lock_time))
134    }
135
136    /// Constructs a new `Sequence` from an unprefixed hex string.
137    #[cfg(feature = "alloc")]
138    pub fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError> {
139        let lock_time = parse::hex_u32_unprefixed(s)?;
140        Ok(Self::from_consensus(lock_time))
141    }
142
143    /// Constructs a new relative lock-time using block height.
144    #[inline]
145    pub fn from_height(height: u16) -> Self { Sequence(u32::from(height)) }
146
147    /// Constructs a new relative lock-time using time intervals where each interval is equivalent
148    /// to 512 seconds.
149    ///
150    /// Encoding finer granularity of time for relative lock-times is not supported in Bitcoin
151    #[inline]
152    pub fn from_512_second_intervals(intervals: u16) -> Self {
153        Sequence(u32::from(intervals) | Sequence::LOCK_TYPE_MASK)
154    }
155
156    /// Constructs a new relative lock-time from seconds, converting the seconds into 512 second
157    /// interval with floor division.
158    ///
159    /// Will return an error if the input cannot be encoded in 16 bits.
160    #[inline]
161    #[cfg(feature = "alloc")]
162    pub fn from_seconds_floor(seconds: u32) -> Result<Self, TimeOverflowError> {
163        if let Ok(interval) = u16::try_from(seconds / 512) {
164            Ok(Sequence::from_512_second_intervals(interval))
165        } else {
166            Err(TimeOverflowError::new(seconds))
167        }
168    }
169
170    /// Constructs a new relative lock-time from seconds, converting the seconds into 512 second
171    /// interval with ceiling division.
172    ///
173    /// Will return an error if the input cannot be encoded in 16 bits.
174    #[inline]
175    #[cfg(feature = "alloc")]
176    pub fn from_seconds_ceil(seconds: u32) -> Result<Self, TimeOverflowError> {
177        if let Ok(interval) = u16::try_from((seconds + 511) / 512) {
178            Ok(Sequence::from_512_second_intervals(interval))
179        } else {
180            Err(TimeOverflowError::new(seconds))
181        }
182    }
183
184    /// Constructs a new sequence from a u32 value.
185    #[inline]
186    pub fn from_consensus(n: u32) -> Self { Sequence(n) }
187
188    /// Returns the inner 32bit integer value of Sequence.
189    #[inline]
190    pub fn to_consensus_u32(self) -> u32 { self.0 }
191
192    /// Constructs a new [`relative::LockTime`] from this [`Sequence`] number.
193    #[inline]
194    #[cfg(feature = "alloc")]
195    pub fn to_relative_lock_time(&self) -> Option<relative::LockTime> {
196        use crate::locktime::relative::{Height, LockTime, Time};
197
198        if !self.is_relative_lock_time() {
199            return None;
200        }
201
202        let lock_value = self.low_u16();
203
204        if self.is_time_locked() {
205            Some(LockTime::from(Time::from_512_second_intervals(lock_value)))
206        } else {
207            Some(LockTime::from(Height::from(lock_value)))
208        }
209    }
210
211    /// Returns the low 16 bits from sequence number.
212    ///
213    /// BIP-68 only uses the low 16 bits for relative lock value.
214    #[cfg(feature = "alloc")]
215    fn low_u16(&self) -> u16 { self.0 as u16 }
216}
217
218impl Default for Sequence {
219    /// The default value of sequence is 0xffffffff.
220    fn default() -> Self { Sequence::MAX }
221}
222
223impl From<Sequence> for u32 {
224    fn from(sequence: Sequence) -> u32 { sequence.0 }
225}
226
227impl fmt::Display for Sequence {
228    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
229}
230
231impl fmt::LowerHex for Sequence {
232    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
233}
234#[cfg(feature = "alloc")]
235internals::impl_to_hex_from_lower_hex!(Sequence, |sequence: &Sequence| {
236    8 - sequence.0.leading_zeros() as usize / 4
237});
238
239impl fmt::UpperHex for Sequence {
240    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) }
241}
242
243impl fmt::Debug for Sequence {
244    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
245        // 10 because its 8 digits + 2 for the '0x'
246        write!(f, "Sequence({:#010x})", self.0)
247    }
248}
249
250#[cfg(feature = "alloc")]
251units::impl_parse_str_from_int_infallible!(Sequence, u32, from_consensus);
252
253#[cfg(feature = "arbitrary")]
254#[cfg(feature = "alloc")]
255impl<'a> Arbitrary<'a> for Sequence {
256    fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
257        // Equally weight the cases of meaningful sequence numbers
258        let choice = u.int_in_range(0..=8)?;
259        match choice {
260            0 => Ok(Sequence::MAX),
261            1 => Ok(Sequence::ZERO),
262            2 => Ok(Sequence::MIN_NO_RBF),
263            3 => Ok(Sequence::ENABLE_LOCKTIME_AND_RBF),
264            4 => Ok(Sequence::from_consensus(relative::Height::MIN.to_consensus_u32())),
265            5 => Ok(Sequence::from_consensus(relative::Height::MAX.to_consensus_u32())),
266            6 => Ok(Sequence::from_consensus(relative::Time::MIN.to_consensus_u32())),
267            7 => Ok(Sequence::from_consensus(relative::Time::MAX.to_consensus_u32())),
268            _ => Ok(Sequence(u.arbitrary()?)),
269        }
270    }
271}
272
273#[cfg(feature = "arbitrary")]
274#[cfg(not(feature = "alloc"))]
275impl<'a> Arbitrary<'a> for Sequence {
276    fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
277        // Equally weight the cases of meaningful sequence numbers
278        let choice = u.int_in_range(0..=4)?;
279        match choice {
280            0 => Ok(Sequence::MAX),
281            1 => Ok(Sequence::ZERO),
282            2 => Ok(Sequence::MIN_NO_RBF),
283            3 => Ok(Sequence::ENABLE_LOCKTIME_AND_RBF),
284            _ => Ok(Sequence(u.arbitrary()?)),
285        }
286    }
287}
288
289#[cfg(test)]
290#[cfg(feature = "alloc")]
291mod tests {
292    use super::*;
293
294    const MAXIMUM_ENCODABLE_SECONDS: u32 = u16::MAX as u32 * 512;
295
296    #[test]
297    fn from_seconds_floor_success() {
298        let expected = Sequence::from_hex("0x0040ffff").unwrap();
299        let actual = Sequence::from_seconds_floor(MAXIMUM_ENCODABLE_SECONDS + 511).unwrap();
300        assert_eq!(actual, expected);
301    }
302
303    #[test]
304    fn from_seconds_floor_causes_overflow_error() {
305        assert!(Sequence::from_seconds_floor(MAXIMUM_ENCODABLE_SECONDS + 512).is_err());
306    }
307
308    #[test]
309    fn from_seconds_ceil_success() {
310        let expected = Sequence::from_hex("0x0040ffff").unwrap();
311        let actual = Sequence::from_seconds_ceil(MAXIMUM_ENCODABLE_SECONDS - 511).unwrap();
312        assert_eq!(actual, expected);
313    }
314
315    #[test]
316    fn from_seconds_ceil_causes_overflow_error() {
317        assert!(Sequence::from_seconds_ceil(MAXIMUM_ENCODABLE_SECONDS + 1).is_err());
318    }
319}