p2p: Implement `encoding` traits for `GetCFHeaders`
What changed, and why it matters
This commit adds standard encoding and decoding support for a Bitcoin peer-to-peer message called GetCFHeaders. It is a routine feature addition with no visible security bug, missing check, or unsafe code. The change simply lets the library serialize and deserialize this message type in the same way it already handles related messages.
No security action required. Review as normal code-quality change.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch implements the Encodable and Decodable traits for GetCFHeaders in p2p/src/message_filter.rs, introducing GetCFHeadersEncoder, GetCFHeadersDecoder, and GetCFHeadersDecoderError. It uses existing composed encoders (Encoder3/Decoder3 over ArrayEncoder<1>, BlockHeightEncoder/Decoder, and BlockHashEncoder/Decoder) and keeps the previous impl_consensus_encoding! macro invocation. There is no evidence of length underflow, unbounded allocation, incorrect bounds, or parsing ambiguity. The filter_type byte is read via a fixed 1-byte array decoder and converted with u8::from_le_bytes.
Changed components
p2p/src/message_filter.rsGetCFHeaders message encoding/decodingInspect captured patch +81 / −0
diff --git a/p2p/src/message_filter.rs b/p2p/src/message_filter.rs
index e25ffaea..9374b0f8 100644
--- a/p2p/src/message_filter.rs
+++ b/p2p/src/message_filter.rs
@@ -186,6 +186,87 @@ pub struct GetCFHeaders {
/// The hash of the last block in the requested range
pub stop_hash: BlockHash,
}
+
+encoding::encoder_newtype! {
+ /// Encoder type for the [`GetCFHeaders`] message.
+ pub struct GetCFHeadersEncoder(Encoder3<ArrayEncoder<1>, BlockHeightEncoder, BlockHashEncoder>);
+}
+
+impl encoding::Encodable for GetCFHeaders {
+ type Encoder<'e> = GetCFHeadersEncoder;
+
+ fn encoder(&self) -> Self::Encoder<'_> {
+ GetCFHeadersEncoder(
+ Encoder3::new(
+ ArrayEncoder::without_length_prefix(self.filter_type.to_le_bytes()),
+ self.start_height.encoder(),
+ self.stop_hash.encoder()
+ )
+ )
+ }
+}
+
+type GetCFHeadersInnerDecoder = Decoder3<ArrayDecoder<1>, BlockHeightDecoder, BlockHashDecoder>;
+
+/// Decoder type for the [`GetCFHeaders`] message.
+pub struct GetCFHeadersDecoder(GetCFHeadersInnerDecoder);
+
+impl encoding::Decoder for GetCFHeadersDecoder {
+ type Output = GetCFHeaders;
+ type Error = GetCFHeadersDecoderError;
+
+ #[inline]
+ fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error> {
+ self.0.push_bytes(bytes).map_err(GetCFHeadersDecoderError)
+ }
+
+ #[inline]
+ fn end(self) -> Result<Self::Output, Self::Error> {
+ let (ty, start_height, stop_hash) = self.0.end().map_err(GetCFHeadersDecoderError)?;
+ Ok(GetCFHeaders {
+ filter_type: u8::from_le_bytes(ty),
+ start_height,
+ stop_hash
+ })
+ }
+
+ #[inline]
+ fn read_limit(&self) -> usize { self.0.read_limit() }
+}
+
+impl encoding::Decodable for GetCFHeaders {
+ type Decoder = GetCFHeadersDecoder;
+
+ fn decoder() -> Self::Decoder {
+ GetCFHeadersDecoder(
+ Decoder3::new(
+ ArrayDecoder::new(),
+ BlockHeightDecoder::new(),
+ BlockHashDecoder::new()
+ )
+ )
+ }
+}
+
+/// Errors occuring when decoding a [`GetCFHeaders`] message.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct GetCFHeadersDecoderError(<GetCFHeadersInnerDecoder as encoding::Decoder>::Error);
+
+impl From<Infallible> for GetCFHeadersDecoderError {
+ fn from(never: Infallible) -> Self { match never {} }
+}
+
+impl fmt::Display for GetCFHeadersDecoderError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write_err!(f, "getcfheaders error"; self.0)
+ }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for GetCFHeadersDecoderError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
+}
+
impl_consensus_encoding!(GetCFHeaders, filter_type, start_height, stop_hash);
/// cfheaders message
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.