consensus_encoding: add decoder traits
What changed, and why it matters
This commit adds new Rust traits (interface definitions) for a streaming, push-based Bitcoin consensus decoder. It only introduces abstract code patterns—no actual decoding logic for real Bitcoin data types, no changes to existing behavior, and no bug fixes. There is nothing here that directly affects security.
No security action required. Review future implementations of these traits for correct handling of partial/malformed input, resource exhaustion, and panic safety, since push-based decoders can be exposed to untrusted network data.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch creates consensus_encoding/src/decode/mod.rs defining Decodable and Decoder traits, and re-exports them from lib.rs. Decoder is a push-style stateful decoder with push_bytes(&mut self, bytes: &mut &[u8]) -> Result
Changed components
consensus_encoding/src/decode/mod.rsconsensus_encoding/src/lib.rsInspect captured patch +61 / −0
diff --git a/consensus_encoding/src/decode/mod.rs b/consensus_encoding/src/decode/mod.rs
new file mode 100644
index 00000000..1e8c658d
--- /dev/null
+++ b/consensus_encoding/src/decode/mod.rs
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: CC0-1.0
+
+//! Consensus Decoding Traits
+
+/// A Bitcoin object which can be consensus-decoded using a push decoder.
+///
+/// To decode something, create a [`Self::Decoder`] and push byte slices
+/// into it with [`Decoder::push_bytes`], then call [`Decoder::end`] to get the result.
+pub trait Decodable {
+ /// Associated decoder for the type.
+ type Decoder: Decoder<Output = Self>;
+ /// Constructs a "default decoder" for the type.
+ fn decoder() -> Self::Decoder;
+}
+
+/// A push decoder for a consensus-decodable object.
+pub trait Decoder: Sized {
+ /// The type that this decoder produces when decoding is complete.
+ type Output;
+ /// The error type that this decoder can produce.
+ type Error;
+
+ /// Push bytes into the decoder, consuming as much as possible.
+ ///
+ /// The slice reference will be advanced to point to the unconsumed portion.
+ /// Returns `Ok(true)` if more bytes are needed to complete decoding,
+ /// `Ok(false)` if the decoder is ready to finalize with [`Self::end`],
+ /// or `Err(error)` if parsing failed.
+ ///
+ /// # Errors
+ ///
+ /// Returns an error if the provided bytes are invalid or malformed according
+ /// to the decoder's validation rules. Insufficient data (needing more
+ /// bytes) is *not* an error for this method, the decoder will simply consume
+ /// what it can and return `true` to indicate more data is needed.
+ ///
+ /// # Panics
+ ///
+ /// May panic if called after a previous call to [`Self::push_bytes`] errored.
+ #[must_use = "must check result to avoid panics on subsequent calls"]
+ fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error>;
+
+ /// Complete the decoding process and return the final result.
+ ///
+ /// This consumes the decoder and should be called when no more input
+ /// data is available.
+ ///
+ /// # Errors
+ ///
+ /// Returns an error if the decoder has not received sufficient data to
+ /// complete decoding, or if the accumulated data is invalid when considered
+ /// as a complete object.
+ ///
+ /// # Panics
+ ///
+ /// May panic if called after a previous call to [`Self::push_bytes`] errored.
+ #[must_use = "must check result to avoid panics on subsequent calls"]
+ fn end(self) -> Result<Self::Output, Self::Error>;
+}
diff --git a/consensus_encoding/src/lib.rs b/consensus_encoding/src/lib.rs
index 0e2fa737..2050acb7 100644
--- a/consensus_encoding/src/lib.rs
+++ b/consensus_encoding/src/lib.rs
@@ -19,8 +19,10 @@ extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
+mod decode;
mod encode;
+pub use self::decode::{Decodable, Decoder};
#[cfg(feature = "alloc")]
pub use self::encode::encode_to_vec;
#[cfg(feature = "std")]
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.