What changed, and why it matters
This commit removes the automatic default value for the Bitcoin transaction `Sequence` type in the rust-bitcoin library. Previously, code that asked for a default sequence number would silently get the maximum value (0xffffffff), which disables transaction replacement. The change forces callers to explicitly choose a sequence value, reducing the risk of accidental misconfiguration. It is an API-cleanup change rather than a fix for an active security bug.
Review downstream code that previously called `Sequence::default()` or derived `Default` on structs containing `Sequence`. Replace those with an explicit sequence value such as `Sequence::MAX` or another semantically appropriate constant. Monitor the project for any follow-up commit that adds a `Sequence::new()` constructor.
Security signals we found
Removal of Default impl for a consensus-relevant type (Sequence)
Default previously returned Sequence::MAX, which disables BIP-68/BIP-112 relative timelocks
No advisory, CVE, or vendor security disclosure linked to the change
Change is defensive API hardening, not a patch for a known vulnerability
Evidence from the diff
The patch deletes impl Default for Sequence from units/src/sequence.rs, where Default::default() returned Sequence::MAX (0xffffffff). It updates fuzz targets, API conformance tests, and public API snapshot files to reflect the removed trait implementation. The fuzz wrapper now uses Sequence::MAX explicitly. No new new() constructor is added. The change is purely defensive: it prevents downstream code from unknowingly relying on a non-obvious default for a consensus-relevant field.
Changed components
bitcoin_units::sequence::Sequenceunits/src/sequence.rsfuzz/fuzz_targets/units/standard_checks.rsprimitives/tests/api.rsunits/tests/api.rsunits/api/*.txt public API snapshotsInspect captured patch +1 / −23
diff --git a/fuzz/fuzz_targets/units/standard_checks.rs b/fuzz/fuzz_targets/units/standard_checks.rs
index 87652076..6b3397bb 100644
--- a/fuzz/fuzz_targets/units/standard_checks.rs
+++ b/fuzz/fuzz_targets/units/standard_checks.rs
@@ -58,11 +58,11 @@ mod fuzz {
wrap_for_checks!(BlockMtpInterval);
wrap_for_checks!(NumberOf512Seconds);
wrap_for_checks!(NumberOfBlocks);
- wrap_for_checks!(Sequence);
wrap_for_checks!(SignedAmount);
// Structs that need defaults
wrap_for_checks!(BlockHeight, super::BlockHeight::MIN);
+ wrap_for_checks!(Sequence, super::Sequence::MAX);
wrap_for_checks!(BlockMtp, super::BlockMtp::from_u32(1_742_979_600)); // 26 Mar 2025 9:00 UTC
wrap_for_checks!(BlockTime, super::BlockTime::from(1_742_979_600)); // 26 Mar 2025 9:00 UTC
wrap_for_checks!(FeeRate, super::FeeRate::BROADCAST_MIN);
diff --git a/primitives/tests/api.rs b/primitives/tests/api.rs
index 510838ea..78e3b6a4 100644
--- a/primitives/tests/api.rs
+++ b/primitives/tests/api.rs
@@ -207,7 +207,6 @@ struct Default {
c3: ScriptSigBuf,
c4: TapScriptBuf,
c5: WitnessScriptBuf,
- d: Sequence,
e: Witness,
}
@@ -431,7 +430,6 @@ fn regression_default() {
c3: ScriptSigBuf::from_bytes(Vec::new()),
c4: TapScriptBuf::from_bytes(Vec::new()),
c5: WitnessScriptBuf::from_bytes(Vec::new()),
- d: Sequence::MAX,
e: Witness::new(),
};
assert_eq!(got, want);
diff --git a/units/api/all-features.txt b/units/api/all-features.txt
index 7a9a61b2..1293689a 100644
--- a/units/api/all-features.txt
+++ b/units/api/all-features.txt
@@ -8808,8 +8808,6 @@ impl core::convert::TryFrom<alloc::string::String> for bitcoin_units::sequence::
impl core::convert::TryFrom<bitcoin_units::sequence::Sequence> for bitcoin_units::locktime::relative::LockTime
pub type bitcoin_units::locktime::relative::LockTime::Error = bitcoin_units::locktime::relative::error::DisabledLockTimeError [impl: impl core::convert::TryFrom<bitcoin_units::sequence::Sequence> for bitcoin_units::locktime::relative::LockTime]
pub fn bitcoin_units::locktime::relative::LockTime::try_from(seq: bitcoin_units::sequence::Sequence) -> core::result::Result<Self, bitcoin_units::locktime::relative::error::DisabledLockTimeError> [impl: impl core::convert::TryFrom<bitcoin_units::sequence::Sequence> for bitcoin_units::locktime::relative::LockTime]
-impl core::default::Default for bitcoin_units::sequence::Sequence
- pub fn bitcoin_units::sequence::Sequence::default() -> Self [impl: impl core::default::Default for bitcoin_units::sequence::Sequence]
impl core::fmt::Binary for bitcoin_units::sequence::Sequence
pub fn bitcoin_units::sequence::Sequence::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result [impl: impl core::fmt::Binary for bitcoin_units::sequence::Sequence]
impl core::fmt::Debug for bitcoin_units::sequence::Sequence
@@ -11312,8 +11310,6 @@ impl core::convert::TryFrom<alloc::string::String> for bitcoin_units::sequence::
impl core::convert::TryFrom<bitcoin_units::sequence::Sequence> for bitcoin_units::locktime::relative::LockTime
pub type bitcoin_units::locktime::relative::LockTime::Error = bitcoin_units::locktime::relative::error::DisabledLockTimeError [impl: impl core::convert::TryFrom<bitcoin_units::sequence::Sequence> for bitcoin_units::locktime::relative::LockTime]
pub fn bitcoin_units::locktime::relative::LockTime::try_from(seq: bitcoin_units::sequence::Sequence) -> core::result::Result<Self, bitcoin_units::locktime::relative::error::DisabledLockTimeError> [impl: impl core::convert::TryFrom<bitcoin_units::sequence::Sequence> for bitcoin_units::locktime::relative::LockTime]
-impl core::default::Default for bitcoin_units::sequence::Sequence
- pub fn bitcoin_units::sequence::Sequence::default() -> Self [impl: impl core::default::Default for bitcoin_units::sequence::Sequence]
impl core::fmt::Binary for bitcoin_units::sequence::Sequence
pub fn bitcoin_units::sequence::Sequence::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result [impl: impl core::fmt::Binary for bitcoin_units::sequence::Sequence]
impl core::fmt::Debug for bitcoin_units::sequence::Sequence
diff --git a/units/api/alloc-only.txt b/units/api/alloc-only.txt
index fb5e0b76..baf367c6 100644
--- a/units/api/alloc-only.txt
+++ b/units/api/alloc-only.txt
@@ -7416,8 +7416,6 @@ impl core::convert::TryFrom<alloc::string::String> for bitcoin_units::sequence::
impl core::convert::TryFrom<bitcoin_units::sequence::Sequence> for bitcoin_units::locktime::relative::LockTime
pub type bitcoin_units::locktime::relative::LockTime::Error = bitcoin_units::locktime::relative::error::DisabledLockTimeError [impl: impl core::convert::TryFrom<bitcoin_units::sequence::Sequence> for bitcoin_units::locktime::relative::LockTime]
pub fn bitcoin_units::locktime::relative::LockTime::try_from(seq: bitcoin_units::sequence::Sequence) -> core::result::Result<Self, bitcoin_units::locktime::relative::error::DisabledLockTimeError> [impl: impl core::convert::TryFrom<bitcoin_units::sequence::Sequence> for bitcoin_units::locktime::relative::LockTime]
-impl core::default::Default for bitcoin_units::sequence::Sequence
- pub fn bitcoin_units::sequence::Sequence::default() -> Self [impl: impl core::default::Default for bitcoin_units::sequence::Sequence]
impl core::fmt::Binary for bitcoin_units::sequence::Sequence
pub fn bitcoin_units::sequence::Sequence::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result [impl: impl core::fmt::Binary for bitcoin_units::sequence::Sequence]
impl core::fmt::Debug for bitcoin_units::sequence::Sequence
@@ -9517,8 +9515,6 @@ impl core::convert::TryFrom<alloc::string::String> for bitcoin_units::sequence::
impl core::convert::TryFrom<bitcoin_units::sequence::Sequence> for bitcoin_units::locktime::relative::LockTime
pub type bitcoin_units::locktime::relative::LockTime::Error = bitcoin_units::locktime::relative::error::DisabledLockTimeError [impl: impl core::convert::TryFrom<bitcoin_units::sequence::Sequence> for bitcoin_units::locktime::relative::LockTime]
pub fn bitcoin_units::locktime::relative::LockTime::try_from(seq: bitcoin_units::sequence::Sequence) -> core::result::Result<Self, bitcoin_units::locktime::relative::error::DisabledLockTimeError> [impl: impl core::convert::TryFrom<bitcoin_units::sequence::Sequence> for bitcoin_units::locktime::relative::LockTime]
-impl core::default::Default for bitcoin_units::sequence::Sequence
- pub fn bitcoin_units::sequence::Sequence::default() -> Self [impl: impl core::default::Default for bitcoin_units::sequence::Sequence]
impl core::fmt::Binary for bitcoin_units::sequence::Sequence
pub fn bitcoin_units::sequence::Sequence::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result [impl: impl core::fmt::Binary for bitcoin_units::sequence::Sequence]
impl core::fmt::Debug for bitcoin_units::sequence::Sequence
diff --git a/units/api/no-features.txt b/units/api/no-features.txt
index 55623f05..180e86fa 100644
--- a/units/api/no-features.txt
+++ b/units/api/no-features.txt
@@ -6590,8 +6590,6 @@ impl core::convert::TryFrom<&str> for bitcoin_units::sequence::Sequence
impl core::convert::TryFrom<bitcoin_units::sequence::Sequence> for bitcoin_units::locktime::relative::LockTime
pub type bitcoin_units::locktime::relative::LockTime::Error = bitcoin_units::locktime::relative::error::DisabledLockTimeError [impl: impl core::convert::TryFrom<bitcoin_units::sequence::Sequence> for bitcoin_units::locktime::relative::LockTime]
pub fn bitcoin_units::locktime::relative::LockTime::try_from(seq: bitcoin_units::sequence::Sequence) -> core::result::Result<Self, bitcoin_units::locktime::relative::error::DisabledLockTimeError> [impl: impl core::convert::TryFrom<bitcoin_units::sequence::Sequence> for bitcoin_units::locktime::relative::LockTime]
-impl core::default::Default for bitcoin_units::sequence::Sequence
- pub fn bitcoin_units::sequence::Sequence::default() -> Self [impl: impl core::default::Default for bitcoin_units::sequence::Sequence]
impl core::fmt::Binary for bitcoin_units::sequence::Sequence
pub fn bitcoin_units::sequence::Sequence::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result [impl: impl core::fmt::Binary for bitcoin_units::sequence::Sequence]
impl core::fmt::Debug for bitcoin_units::sequence::Sequence
@@ -8563,8 +8561,6 @@ impl core::convert::TryFrom<&str> for bitcoin_units::sequence::Sequence
impl core::convert::TryFrom<bitcoin_units::sequence::Sequence> for bitcoin_units::locktime::relative::LockTime
pub type bitcoin_units::locktime::relative::LockTime::Error = bitcoin_units::locktime::relative::error::DisabledLockTimeError [impl: impl core::convert::TryFrom<bitcoin_units::sequence::Sequence> for bitcoin_units::locktime::relative::LockTime]
pub fn bitcoin_units::locktime::relative::LockTime::try_from(seq: bitcoin_units::sequence::Sequence) -> core::result::Result<Self, bitcoin_units::locktime::relative::error::DisabledLockTimeError> [impl: impl core::convert::TryFrom<bitcoin_units::sequence::Sequence> for bitcoin_units::locktime::relative::LockTime]
-impl core::default::Default for bitcoin_units::sequence::Sequence
- pub fn bitcoin_units::sequence::Sequence::default() -> Self [impl: impl core::default::Default for bitcoin_units::sequence::Sequence]
impl core::fmt::Binary for bitcoin_units::sequence::Sequence
pub fn bitcoin_units::sequence::Sequence::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result [impl: impl core::fmt::Binary for bitcoin_units::sequence::Sequence]
impl core::fmt::Debug for bitcoin_units::sequence::Sequence
diff --git a/units/src/sequence.rs b/units/src/sequence.rs
index 66223acf..fe0856cb 100644
--- a/units/src/sequence.rs
+++ b/units/src/sequence.rs
@@ -228,12 +228,6 @@ impl Sequence {
crate::internal_macros::impl_fmt_traits_for_u32_wrapper!(Sequence);
-impl Default for Sequence {
- /// The default value of sequence is 0xffffffff.
- #[inline]
- fn default() -> Self { Self::MAX }
-}
-
impl From<Sequence> for u32 {
#[inline]
fn from(sequence: Sequence) -> Self { sequence.0 }
diff --git a/units/tests/api.rs b/units/tests/api.rs
index 429146b0..25c85275 100644
--- a/units/tests/api.rs
+++ b/units/tests/api.rs
@@ -129,7 +129,6 @@ struct Default {
d: BlockMtpInterval,
e: relative::NumberOf512Seconds,
f: relative::NumberOfBlocks,
- g: Sequence,
}
/// A struct that includes all public error types (excl. decode errors).
@@ -436,7 +435,6 @@ fn regression_default() {
d: BlockMtpInterval::ZERO,
e: relative::NumberOf512Seconds::ZERO,
f: relative::NumberOfBlocks::ZERO,
- g: Sequence::MAX,
};
assert_eq!(got, want);
}
Why this scored 19/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.