p2p: Implement `encoding` traits for `CFCheckpt`
What changed, and why it matters
This commit adds missing data-encoding (serialization/deserialization) support for a Bitcoin peer-to-peer message type called CFCheckpt. It is a routine feature implementation, not a security fix. There is no indication in the commit or supplied references that this addresses a vulnerability, a bug, or a security-relevant issue.
No security action required. Review as normal code-quality/feature work if desired.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change implements the project’s Encodable and Decodable traits for CFCheckpt in p2p/src/message_filter.rs, adding a dedicated encoder/decoder pair (CFCheckptEncoder/CFCheckptDecoder) and an associated error type. It also updates the import list to include SliceEncoder and VecDecoder. The existing impl_consensus_encoding! macro invocation remains. No bug fixes, bounds checks, validation changes, or security mitigations are present in the diff.
Changed components
p2p/src/message_filter.rsCFCheckpt message encoding/decodingInspect captured patch +89 / −1
diff --git a/p2p/src/message_filter.rs b/p2p/src/message_filter.rs
index 1e38c33a..b0cea5c4 100644
--- a/p2p/src/message_filter.rs
+++ b/p2p/src/message_filter.rs
@@ -10,7 +10,7 @@ use core::fmt;
#[cfg(feature = "arbitrary")]
use arbitrary::{Arbitrary, Unstructured};
-use encoding::{ArrayDecoder, ArrayEncoder, ByteVecDecoder, BytesEncoder, CompactSizeEncoder, Decoder2, Decoder3, Encoder2, Encoder3};
+use encoding::{ArrayDecoder, ArrayEncoder, ByteVecDecoder, BytesEncoder, CompactSizeEncoder, Decoder2, Decoder3, Encoder2, Encoder3, SliceEncoder, VecDecoder};
use hashes::{sha256d, HashEngine};
use internals::write_err;
use primitives::{block::{BlockHashDecoder, BlockHashEncoder}, BlockHash};
@@ -592,6 +592,94 @@ pub struct CFCheckpt {
/// The filter headers at intervals of 1,000
pub filter_headers: Vec<FilterHeader>,
}
+
+encoding::encoder_newtype! {
+ /// Encoder type for a [`CFCheckpt`] message.
+ pub struct CFCheckptEncoder<'e>(
+ Encoder3<
+ ArrayEncoder<1>,
+ BlockHashEncoder,
+ Encoder2<CompactSizeEncoder, SliceEncoder<'e, FilterHeader>>
+ >
+ );
+}
+
+impl encoding::Encodable for CFCheckpt {
+ type Encoder<'e> = CFCheckptEncoder<'e>
+ where
+ Self: 'e;
+
+ fn encoder(&self) -> Self::Encoder<'_> {
+ CFCheckptEncoder(
+ Encoder3::new(
+ ArrayEncoder::without_length_prefix(self.filter_type.to_le_bytes()),
+ self.stop_hash.encoder(),
+ Encoder2::new(
+ CompactSizeEncoder::new(self.filter_headers.len()),
+ SliceEncoder::without_length_prefix(&self.filter_headers)
+ )
+ )
+ )
+ }
+}
+
+type CFCheckptInnerDecoder = Decoder3<ArrayDecoder<1>, BlockHashDecoder, VecDecoder<FilterHeader>>;
+
+/// Decoder type for a [`CFCheckpt`] message.
+pub struct CFCheckptDecoder(CFCheckptInnerDecoder);
+
+impl encoding::Decoder for CFCheckptDecoder {
+ type Output = CFCheckpt;
+ type Error = CFCheckptDecoderError;
+
+ #[inline]
+ fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error> {
+ self.0.push_bytes(bytes).map_err(CFCheckptDecoderError)
+ }
+
+ #[inline]
+ fn end(self) -> Result<Self::Output, Self::Error> {
+ let (ty, stop_hash, filter_headers) = self.0.end().map_err(CFCheckptDecoderError)?;
+ Ok(CFCheckpt {
+ filter_type: u8::from_le_bytes(ty),
+ stop_hash,
+ filter_headers,
+ })
+ }
+
+ #[inline]
+ fn read_limit(&self) -> usize { self.0.read_limit() }
+}
+
+impl encoding::Decodable for CFCheckpt {
+ type Decoder = CFCheckptDecoder;
+
+ fn decoder() -> Self::Decoder {
+ CFCheckptDecoder(
+ Decoder3::new(ArrayDecoder::new(), BlockHashDecoder::new(), VecDecoder::new())
+ )
+ }
+}
+
+/// Errors occuring when decoding a [`CFCheckpt`] message.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct CFCheckptDecoderError(<CFCheckptInnerDecoder as encoding::Decoder>::Error);
+
+impl From<Infallible> for CFCheckptDecoderError {
+ fn from(never: Infallible) -> Self { match never {} }
+}
+
+impl fmt::Display for CFCheckptDecoderError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write_err!(f, "cfcheckpt error"; self.0)
+ }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for CFCheckptDecoderError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
+}
+
impl_consensus_encoding!(CFCheckpt, filter_type, stop_hash, filter_headers);
#[cfg(feature = "arbitrary")]
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.