p2p: Implement `encoding` traits for `FilterLoad`
What changed, and why it matters
This commit adds a new way to encode and decode the Bitcoin 'filterload' P2P network message using a new internal encoding framework. It is a routine refactor that mirrors how other message types were already handled. There is no indication of a security bug being fixed or introduced.
No security action needed. Review as normal code-quality/refactor change.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change implements the project’s new Encodable/Decodable traits for FilterLoad in p2p/src/message_bloom.rs, using composed Encoder2/Encoder3/Decoder4 helpers. It also adds a dedicated FilterLoadDecoderError type. The existing impl_consensus_encoding! macro remains in place, so this is additive rather than a behavioral change to consensus serialization.
Changed components
p2p/src/message_bloom.rsInspect captured patch +96 / −1
diff --git a/p2p/src/message_bloom.rs b/p2p/src/message_bloom.rs
index ff953bd8..e548d41c 100644
--- a/p2p/src/message_bloom.rs
+++ b/p2p/src/message_bloom.rs
@@ -11,7 +11,7 @@ use core::fmt;
#[cfg(feature = "arbitrary")]
use arbitrary::{Arbitrary, Unstructured};
use bitcoin::consensus::{encode, Decodable, Encodable, ReadExt};
-use encoding::{ArrayDecoder, ArrayEncoder, ByteVecDecoder, BytesEncoder, CompactSizeEncoder, Encoder2};
+use encoding::{ArrayDecoder, ArrayEncoder, ByteVecDecoder, BytesEncoder, CompactSizeEncoder, Decoder4, Encoder2, Encoder3};
use internals::write_err;
use io::{BufRead, Write};
@@ -30,6 +30,101 @@ pub struct FilterLoad {
pub flags: BloomFlags,
}
+encoding::encoder_newtype! {
+ /// The encoder for the [`FilterLoad`] message.
+ pub struct FilterLoadEncoder<'e>(
+ Encoder2<
+ Encoder2<CompactSizeEncoder, BytesEncoder<'e>>,
+ Encoder3<
+ ArrayEncoder<4>,
+ ArrayEncoder<4>,
+ BloomFlagsEncoder
+ >
+ >
+ );
+}
+
+impl encoding::Encodable for FilterLoad {
+ type Encoder<'e> = FilterLoadEncoder<'e>;
+
+ fn encoder(&self) -> Self::Encoder<'_> {
+ FilterLoadEncoder(Encoder2::new(
+ Encoder2::new(
+ CompactSizeEncoder::new(self.filter.len()),
+ BytesEncoder::without_length_prefix(&self.filter)
+ ),
+ Encoder3::new(
+ ArrayEncoder::without_length_prefix(self.hash_funcs.to_le_bytes()),
+ ArrayEncoder::without_length_prefix(self.tweak.to_le_bytes()),
+ self.flags.encoder(),
+ ),
+ ))
+ }
+}
+
+type FilterLoadInnerDecoder = Decoder4<ByteVecDecoder, ArrayDecoder<4>, ArrayDecoder<4>, BloomFlagsDecoder>;
+
+/// The decoder for the [`FilterLoad`] message.
+pub struct FilterLoadDecoder(FilterLoadInnerDecoder);
+
+impl encoding::Decoder for FilterLoadDecoder {
+ type Output = FilterLoad;
+ type Error = FilterLoadDecoderError;
+
+ #[inline]
+ fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error> {
+ self.0.push_bytes(bytes).map_err(FilterLoadDecoderError)
+ }
+
+ #[inline]
+ fn end(self) -> Result<Self::Output, Self::Error> {
+ let (filter, hash_funcs, tweak, flags) = self.0.end().map_err(FilterLoadDecoderError)?;
+ Ok(FilterLoad {
+ filter,
+ hash_funcs: u32::from_le_bytes(hash_funcs),
+ tweak: u32::from_le_bytes(tweak),
+ flags
+ })
+ }
+
+ #[inline]
+ fn read_limit(&self) -> usize { self.0.read_limit() }
+}
+
+impl encoding::Decodable for FilterLoad {
+ type Decoder = FilterLoadDecoder;
+
+ fn decoder() -> Self::Decoder {
+ FilterLoadDecoder(
+ Decoder4::new(
+ ByteVecDecoder::new(),
+ ArrayDecoder::new(),
+ ArrayDecoder::new(),
+ BloomFlags::decoder(),
+ )
+ )
+ }
+}
+
+/// An error occuring when decoding a [`FilterLoad`] message.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct FilterLoadDecoderError(<FilterLoadInnerDecoder as encoding::Decoder>::Error);
+
+impl From<Infallible> for FilterLoadDecoderError {
+ fn from(never: Infallible) -> Self { match never {} }
+}
+
+impl fmt::Display for FilterLoadDecoderError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write_err!(f, "filterload error"; self.0)
+ }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for FilterLoadDecoderError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
+}
+
impl_consensus_encoding!(FilterLoad, filter, hash_funcs, tweak, flags);
/// Bloom filter update flags
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.