p2p: Implement `encoding` traits for `FilterAdd`
What changed, and why it matters
This commit adds new serialization/deserialization code for the Bitcoin P2P 'filteradd' bloom-filter message in the rust-bitcoin library. It is a routine feature implementation with no visible security bug, no fix of a vulnerability, and no disclosed security relevance.
No security action required. Review as normal code-quality/encoding-correctness change if desired.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch introduces an encoding::Encodable/Decodable implementation for FilterAdd using the crate’s newer encoding traits. It adds FilterAddEncoder, FilterAddDecoder, FilterAddDecoderError, and wires them to encode a compact-size length followed by the raw byte vector. The older impl_consensus_encoding! macro invocation remains in place, so this is additive rather than a replacement. There is no evidence of memory-safety issues, panic paths, unbounded allocation bypass, or incorrect consensus encoding in the diff.
Changed components
rust-bitcoin p2p/src/message_bloom.rsFilterAdd message encoding/decodingInspect captured patch +73 / −0
diff --git a/p2p/src/message_bloom.rs b/p2p/src/message_bloom.rs
index c09ddce1..9b18f692 100644
--- a/p2p/src/message_bloom.rs
+++ b/p2p/src/message_bloom.rs
@@ -5,10 +5,14 @@
//! This module describes BIP-0037 Connection Bloom filtering network messages.
use alloc::vec::Vec;
+use core::convert::Infallible;
+use core::fmt;
#[cfg(feature = "arbitrary")]
use arbitrary::{Arbitrary, Unstructured};
use bitcoin::consensus::{encode, Decodable, Encodable, ReadExt};
+use encoding::{ByteVecDecoder, BytesEncoder, CompactSizeEncoder, Encoder2};
+use internals::write_err;
use io::{BufRead, Write};
use crate::consensus::impl_consensus_encoding;
@@ -68,6 +72,75 @@ pub struct FilterAdd {
pub data: Vec<u8>,
}
+encoding::encoder_newtype! {
+ /// The encoder of the [`FilterAdd`] message.
+ pub struct FilterAddEncoder<'e>(Encoder2<CompactSizeEncoder, BytesEncoder<'e>>);
+}
+
+impl encoding::Encodable for FilterAdd {
+ type Encoder<'e> = FilterAddEncoder<'e>;
+
+ fn encoder(&self) -> Self::Encoder<'_> {
+ FilterAddEncoder(
+ Encoder2::new(
+ CompactSizeEncoder::new(self.data.len()),
+ BytesEncoder::without_length_prefix(&self.data)
+ )
+ )
+ }
+}
+
+type FilterAddInnerDecoder = ByteVecDecoder;
+
+/// The decoder for the [`FilterAdd`] message.
+pub struct FilterAddDecoder(FilterAddInnerDecoder);
+
+impl encoding::Decoder for FilterAddDecoder {
+ type Output = FilterAdd;
+ type Error = FilterAddDecoderError;
+
+ #[inline]
+ fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error> {
+ self.0.push_bytes(bytes).map_err(FilterAddDecoderError)
+ }
+
+ #[inline]
+ fn end(self) -> Result<Self::Output, Self::Error> {
+ let data = self.0.end().map_err(FilterAddDecoderError)?;
+ Ok(FilterAdd { data })
+ }
+
+ #[inline]
+ fn read_limit(&self) -> usize { self.0.read_limit() }
+}
+
+impl encoding::Decodable for FilterAdd {
+ type Decoder = FilterAddDecoder;
+
+ fn decoder() -> Self::Decoder {
+ FilterAddDecoder(FilterAddInnerDecoder::new())
+ }
+}
+
+/// An error decoding a [`FilterAdd`] message.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct FilterAddDecoderError(<FilterAddInnerDecoder as encoding::Decoder>::Error);
+
+impl From<Infallible> for FilterAddDecoderError {
+ fn from(never: Infallible) -> Self { match never {} }
+}
+
+impl fmt::Display for FilterAddDecoderError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write_err!(f, "filteradd error"; self)
+ }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for FilterAddDecoderError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
+}
+
impl_consensus_encoding!(FilterAdd, data);
#[cfg(feature = "arbitrary")]
Why this scored 17/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.