Merge rust-bitcoin/rust-bitcoin#6667: Make the `WitnessesEncoder` private
What changed, and why it matters
This commit makes a small internal helper type called WitnessesEncoder private. It was previously exported as public API but is only used inside the transaction encoder. The change removes it from the public API surface and moves the code closer to where it is used. There is no security bug being fixed here.
No security action needed. This is a routine API cleanup. Users who previously relied on `WitnessesEncoder` being public will need to update their code, but this is a breaking API change rather than a security fix.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit changes WitnessesEncoder from pub struct to struct in primitives/src/transaction.rs, removes it from the public re-export list in bitcoin/src/blockdata/transaction.rs, and updates the generated API text files (all-features.txt, alloc-only.txt) to reflect the reduced public API. The implementation logic is unchanged; only visibility and code location are modified.
Changed components
primitives/src/transaction.rsbitcoin/src/blockdata/transaction.rsprimitives/api/all-features.txtprimitives/api/alloc-only.txtInspect captured patch +54 / −132
### bitcoin/src/blockdata/transaction.rs
@@ -36,7 +36,7 @@ pub use primitives::transaction::BlockHashDecoderError;
pub use primitives::transaction::{
BlockHashDecoder, Ntxid, OutPoint, OutPointDecoder, OutPointEncoder, Transaction,
TransactionDecoder, TransactionEncoder, TxIn, TxInDecoder, TxInEncoder, TxOut, TxOutDecoder,
- TxOutEncoder, Txid, Version, VersionDecoder, VersionEncoder, WitnessesEncoder, Wtxid,
+ TxOutEncoder, Txid, Version, VersionDecoder, VersionEncoder, Wtxid,
};
#[doc(no_inline)]
### primitives/api/all-features.txt
@@ -5804,45 +5804,6 @@ impl<T> core::clone::CloneToUninit for bitcoin_primitives::transaction::VersionE
pub unsafe fn bitcoin_primitives::transaction::VersionEncoder<'e>::clone_to_uninit(&self, dest: *mut u8) [impl: impl<T> core::clone::CloneToUninit for bitcoin_primitives::transaction::VersionEncoder<'e> where T: core::clone::Clone]
impl<T> core::convert::From<T> for bitcoin_primitives::transaction::VersionEncoder<'e>
pub fn bitcoin_primitives::transaction::VersionEncoder<'e>::from(t: T) -> T [impl: impl<T> core::convert::From<T> for bitcoin_primitives::transaction::VersionEncoder<'e>]
-pub struct bitcoin_primitives::transaction::WitnessesEncoder<'e>
-impl<'e> bitcoin_primitives::transaction::WitnessesEncoder<'e>
-pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::new(inputs: &'e [bitcoin_primitives::transaction::TxIn]) -> Self
-impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::WitnessesEncoder<'_>
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'_>::advance(&mut self) -> bitcoin_consensus_encoding::encode::EncoderStatus [impl: impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::WitnessesEncoder<'_>]
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'_>::current_chunk(&self) -> &[u8] [impl: impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::WitnessesEncoder<'_>]
-impl<'e> core::clone::Clone for bitcoin_primitives::transaction::WitnessesEncoder<'e>
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::clone(&self) -> bitcoin_primitives::transaction::WitnessesEncoder<'e> [impl: impl<'e> core::clone::Clone for bitcoin_primitives::transaction::WitnessesEncoder<'e>]
-impl<'e> core::fmt::Debug for bitcoin_primitives::transaction::WitnessesEncoder<'e>
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result [impl: impl<'e> core::fmt::Debug for bitcoin_primitives::transaction::WitnessesEncoder<'e>]
-impl<'e> core::marker::Freeze for bitcoin_primitives::transaction::WitnessesEncoder<'e>
-impl<'e> core::marker::Send for bitcoin_primitives::transaction::WitnessesEncoder<'e>
-impl<'e> core::marker::Sync for bitcoin_primitives::transaction::WitnessesEncoder<'e>
-impl<'e> core::marker::Unpin for bitcoin_primitives::transaction::WitnessesEncoder<'e>
-impl<'e> core::marker::UnsafeUnpin for bitcoin_primitives::transaction::WitnessesEncoder<'e>
-impl<'e> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::WitnessesEncoder<'e>
-impl<'e> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::WitnessesEncoder<'e>
-impl<T, U> core::convert::Into<U> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where U: core::convert::From<T>
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::into(self) -> U [impl: impl<T, U> core::convert::Into<U> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where U: core::convert::From<T>]
-impl<T, U> core::convert::TryFrom<U> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where U: core::convert::Into<T>
- pub type bitcoin_primitives::transaction::WitnessesEncoder<'e>::Error = core::convert::Infallible [impl: impl<T, U> core::convert::TryFrom<U> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where U: core::convert::Into<T>]
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::try_from(value: U) -> core::result::Result<T, <T as core::convert::TryFrom<U>>::Error> [impl: impl<T, U> core::convert::TryFrom<U> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where U: core::convert::Into<T>]
-impl<T, U> core::convert::TryInto<U> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where U: core::convert::TryFrom<T>
- pub type bitcoin_primitives::transaction::WitnessesEncoder<'e>::Error = <U as core::convert::TryFrom<T>>::Error [impl: impl<T, U> core::convert::TryInto<U> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where U: core::convert::TryFrom<T>]
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::try_into(self) -> core::result::Result<U, <U as core::convert::TryFrom<T>>::Error> [impl: impl<T, U> core::convert::TryInto<U> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where U: core::convert::TryFrom<T>]
-impl<T> alloc::borrow::ToOwned for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: core::clone::Clone
- pub type bitcoin_primitives::transaction::WitnessesEncoder<'e>::Owned = T [impl: impl<T> alloc::borrow::ToOwned for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: core::clone::Clone]
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::clone_into(&self, target: &mut T) [impl: impl<T> alloc::borrow::ToOwned for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: core::clone::Clone]
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::to_owned(&self) -> T [impl: impl<T> alloc::borrow::ToOwned for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: core::clone::Clone]
-impl<T> core::any::Any for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: 'static + ?core::marker::Sized
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::type_id(&self) -> core::any::TypeId [impl: impl<T> core::any::Any for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: 'static + ?core::marker::Sized]
-impl<T> core::borrow::Borrow<T> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: ?core::marker::Sized
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::borrow(&self) -> &T [impl: impl<T> core::borrow::Borrow<T> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: ?core::marker::Sized]
-impl<T> core::borrow::BorrowMut<T> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: ?core::marker::Sized
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::borrow_mut(&mut self) -> &mut T [impl: impl<T> core::borrow::BorrowMut<T> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: ?core::marker::Sized]
-impl<T> core::clone::CloneToUninit for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: core::clone::Clone
- pub unsafe fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::clone_to_uninit(&self, dest: *mut u8) [impl: impl<T> core::clone::CloneToUninit for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: core::clone::Clone]
-impl<T> core::convert::From<T> for bitcoin_primitives::transaction::WitnessesEncoder<'e>
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::from(t: T) -> T [impl: impl<T> core::convert::From<T> for bitcoin_primitives::transaction::WitnessesEncoder<'e>]
pub struct bitcoin_primitives::transaction::Wtxid(_)
impl bitcoin_primitives::Wtxid
pub const bitcoin_primitives::Wtxid::COINBASE: Self
### primitives/api/alloc-only.txt
@@ -5395,45 +5395,6 @@ impl<T> core::clone::CloneToUninit for bitcoin_primitives::transaction::VersionE
pub unsafe fn bitcoin_primitives::transaction::VersionEncoder<'e>::clone_to_uninit(&self, dest: *mut u8) [impl: impl<T> core::clone::CloneToUninit for bitcoin_primitives::transaction::VersionEncoder<'e> where T: core::clone::Clone]
impl<T> core::convert::From<T> for bitcoin_primitives::transaction::VersionEncoder<'e>
pub fn bitcoin_primitives::transaction::VersionEncoder<'e>::from(t: T) -> T [impl: impl<T> core::convert::From<T> for bitcoin_primitives::transaction::VersionEncoder<'e>]
-pub struct bitcoin_primitives::transaction::WitnessesEncoder<'e>
-impl<'e> bitcoin_primitives::transaction::WitnessesEncoder<'e>
-pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::new(inputs: &'e [bitcoin_primitives::transaction::TxIn]) -> Self
-impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::WitnessesEncoder<'_>
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'_>::advance(&mut self) -> bitcoin_consensus_encoding::encode::EncoderStatus [impl: impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::WitnessesEncoder<'_>]
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'_>::current_chunk(&self) -> &[u8] [impl: impl bitcoin_consensus_encoding::encode::Encoder for bitcoin_primitives::transaction::WitnessesEncoder<'_>]
-impl<'e> core::clone::Clone for bitcoin_primitives::transaction::WitnessesEncoder<'e>
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::clone(&self) -> bitcoin_primitives::transaction::WitnessesEncoder<'e> [impl: impl<'e> core::clone::Clone for bitcoin_primitives::transaction::WitnessesEncoder<'e>]
-impl<'e> core::fmt::Debug for bitcoin_primitives::transaction::WitnessesEncoder<'e>
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result [impl: impl<'e> core::fmt::Debug for bitcoin_primitives::transaction::WitnessesEncoder<'e>]
-impl<'e> core::marker::Freeze for bitcoin_primitives::transaction::WitnessesEncoder<'e>
-impl<'e> core::marker::Send for bitcoin_primitives::transaction::WitnessesEncoder<'e>
-impl<'e> core::marker::Sync for bitcoin_primitives::transaction::WitnessesEncoder<'e>
-impl<'e> core::marker::Unpin for bitcoin_primitives::transaction::WitnessesEncoder<'e>
-impl<'e> core::marker::UnsafeUnpin for bitcoin_primitives::transaction::WitnessesEncoder<'e>
-impl<'e> core::panic::unwind_safe::RefUnwindSafe for bitcoin_primitives::transaction::WitnessesEncoder<'e>
-impl<'e> core::panic::unwind_safe::UnwindSafe for bitcoin_primitives::transaction::WitnessesEncoder<'e>
-impl<T, U> core::convert::Into<U> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where U: core::convert::From<T>
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::into(self) -> U [impl: impl<T, U> core::convert::Into<U> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where U: core::convert::From<T>]
-impl<T, U> core::convert::TryFrom<U> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where U: core::convert::Into<T>
- pub type bitcoin_primitives::transaction::WitnessesEncoder<'e>::Error = core::convert::Infallible [impl: impl<T, U> core::convert::TryFrom<U> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where U: core::convert::Into<T>]
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::try_from(value: U) -> core::result::Result<T, <T as core::convert::TryFrom<U>>::Error> [impl: impl<T, U> core::convert::TryFrom<U> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where U: core::convert::Into<T>]
-impl<T, U> core::convert::TryInto<U> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where U: core::convert::TryFrom<T>
- pub type bitcoin_primitives::transaction::WitnessesEncoder<'e>::Error = <U as core::convert::TryFrom<T>>::Error [impl: impl<T, U> core::convert::TryInto<U> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where U: core::convert::TryFrom<T>]
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::try_into(self) -> core::result::Result<U, <U as core::convert::TryFrom<T>>::Error> [impl: impl<T, U> core::convert::TryInto<U> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where U: core::convert::TryFrom<T>]
-impl<T> alloc::borrow::ToOwned for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: core::clone::Clone
- pub type bitcoin_primitives::transaction::WitnessesEncoder<'e>::Owned = T [impl: impl<T> alloc::borrow::ToOwned for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: core::clone::Clone]
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::clone_into(&self, target: &mut T) [impl: impl<T> alloc::borrow::ToOwned for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: core::clone::Clone]
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::to_owned(&self) -> T [impl: impl<T> alloc::borrow::ToOwned for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: core::clone::Clone]
-impl<T> core::any::Any for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: 'static + ?core::marker::Sized
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::type_id(&self) -> core::any::TypeId [impl: impl<T> core::any::Any for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: 'static + ?core::marker::Sized]
-impl<T> core::borrow::Borrow<T> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: ?core::marker::Sized
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::borrow(&self) -> &T [impl: impl<T> core::borrow::Borrow<T> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: ?core::marker::Sized]
-impl<T> core::borrow::BorrowMut<T> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: ?core::marker::Sized
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::borrow_mut(&mut self) -> &mut T [impl: impl<T> core::borrow::BorrowMut<T> for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: ?core::marker::Sized]
-impl<T> core::clone::CloneToUninit for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: core::clone::Clone
- pub unsafe fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::clone_to_uninit(&self, dest: *mut u8) [impl: impl<T> core::clone::CloneToUninit for bitcoin_primitives::transaction::WitnessesEncoder<'e> where T: core::clone::Clone]
-impl<T> core::convert::From<T> for bitcoin_primitives::transaction::WitnessesEncoder<'e>
- pub fn bitcoin_primitives::transaction::WitnessesEncoder<'e>::from(t: T) -> T [impl: impl<T> core::convert::From<T> for bitcoin_primitives::transaction::WitnessesEncoder<'e>]
pub struct bitcoin_primitives::transaction::Wtxid(_)
impl bitcoin_primitives::Wtxid
pub const bitcoin_primitives::Wtxid::COINBASE: Self
### primitives/src/transaction.rs
@@ -695,6 +695,59 @@ enum IsSegwit {
No,
}
+/// Encodes the witnesses from a list of inputs.
+#[cfg(feature = "alloc")]
+#[derive(Debug, Clone)]
+struct WitnessesEncoder<'e> {
+ inputs: &'e [TxIn],
+ /// Encoder for the current witness being encoded.
+ cur_enc: Option<WitnessEncoder<'e>>,
+}
+
+#[cfg(feature = "alloc")]
+impl<'e> WitnessesEncoder<'e> {
+ /// Constructs a new encoder for all witnesses in a list of transaction inputs.
+ pub fn new(inputs: &'e [TxIn]) -> Self {
+ Self { inputs, cur_enc: inputs.first().map(|input| input.witness.encoder()) }
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl encoding::Encoder for WitnessesEncoder<'_> {
+ #[inline]
+ fn current_chunk(&self) -> &[u8] {
+ self.cur_enc.as_ref().map(WitnessEncoder::current_chunk).unwrap_or_default()
+ }
+
+ #[inline]
+ fn advance(&mut self) -> EncoderStatus {
+ let Some(cur) = self.cur_enc.as_mut() else {
+ return EncoderStatus::Finished;
+ };
+
+ loop {
+ // On subsequent calls, attempt to advance the current encoder and return
+ // success if this succeeds.
+ if cur.advance().has_more() {
+ return EncoderStatus::HasMore;
+ }
+ // self.inputs guaranteed to be non-empty if cur_enc is non-None.
+ self.inputs = &self.inputs[1..];
+
+ // If advancing the current encoder failed, attempt to move to the next encoder.
+ if let Some(input) = self.inputs.first() {
+ *cur = input.witness.encoder();
+ if !cur.current_chunk().is_empty() {
+ return EncoderStatus::HasMore;
+ }
+ } else {
+ self.cur_enc = None; // shortcut the next call to advance()
+ return EncoderStatus::Finished;
+ }
+ }
+ }
+}
+
/// How many times we have state transitioned to encoding a witness (zero-based).
#[cfg(feature = "alloc")]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -766,59 +819,6 @@ impl encoding::Encode for TxIn {
}
}
-/// Encodes the witnesses from a list of inputs.
-#[cfg(feature = "alloc")]
-#[derive(Debug, Clone)]
-pub struct WitnessesEncoder<'e> {
- inputs: &'e [TxIn],
- /// Encoder for the current witness being encoded.
- cur_enc: Option<WitnessEncoder<'e>>,
-}
-
-#[cfg(feature = "alloc")]
-impl<'e> WitnessesEncoder<'e> {
- /// Constructs a new encoder for all witnesses in a list of transaction inputs.
- pub fn new(inputs: &'e [TxIn]) -> Self {
- Self { inputs, cur_enc: inputs.first().map(|input| input.witness.encoder()) }
- }
-}
-
-#[cfg(feature = "alloc")]
-impl encoding::Encoder for WitnessesEncoder<'_> {
- #[inline]
- fn current_chunk(&self) -> &[u8] {
- self.cur_enc.as_ref().map(WitnessEncoder::current_chunk).unwrap_or_default()
- }
-
- #[inline]
- fn advance(&mut self) -> EncoderStatus {
- let Some(cur) = self.cur_enc.as_mut() else {
- return EncoderStatus::Finished;
- };
-
- loop {
- // On subsequent calls, attempt to advance the current encoder and return
- // success if this succeeds.
- if cur.advance().has_more() {
- return EncoderStatus::HasMore;
- }
- // self.inputs guaranteed to be non-empty if cur_enc is non-None.
- self.inputs = &self.inputs[1..];
-
- // If advancing the current encoder failed, attempt to move to the next encoder.
- if let Some(input) = self.inputs.first() {
- *cur = input.witness.encoder();
- if !cur.current_chunk().is_empty() {
- return EncoderStatus::HasMore;
- }
- } else {
- self.cur_enc = None; // shortcut the next call to advance()
- return EncoderStatus::Finished;
- }
- }
- }
-}
-
#[cfg(feature = "alloc")]
encoding::encoder_newtype_exact! {
/// The encoder for the [`TxIn`] type.Why this scored 15/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.