p2p: Implement `encoding` traits for `BlockTransactionsRequest`
What changed, and why it matters
This commit adds new encoding and decoding machinery for a Bitcoin peer-to-peer message type (BlockTransactionsRequest). It is a routine feature addition that mirrors an existing implementation and does not appear to fix or introduce a security problem on its own.
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 project’s newer encoding::Encodable/Decodable traits for BlockTransactionsRequest in p2p/src/bip152.rs. It introduces a newtype encoder/decoder pair, an Offset slice/vector decoder, and a dedicated error type, while keeping the legacy Encodable implementation intact. The change is additive and follows the established patterns in the crate.
Changed components
p2p/src/bip152.rsInspect captured patch +80 / −1
diff --git a/p2p/src/bip152.rs b/p2p/src/bip152.rs
index be99e825..0cf462a1 100644
--- a/p2p/src/bip152.rs
+++ b/p2p/src/bip152.rs
@@ -14,10 +14,12 @@ use std::error;
use arbitrary::{Arbitrary, Unstructured};
use bitcoin::consensus::encode::{self, Decodable, Encodable, ReadExt, WriteExt};
use bitcoin::{block, Block, BlockChecked, BlockHash, Transaction};
-use encoding::{CompactSizeDecoder, CompactSizeEncoder};
+use encoding::{CompactSizeDecoder, CompactSizeEncoder, Decoder2, Encoder2, SliceEncoder, VecDecoder};
use hashes::{sha256, siphash24};
use internals::array::ArrayExt as _;
+use internals::write_err;
use io::{BufRead, Write};
+use primitives::block::{BlockHashDecoder, BlockHashEncoder};
/// A BIP-0152 error
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -415,6 +417,83 @@ impl BlockTransactionsRequest {
}
}
+encoding::encoder_newtype! {
+ /// The encoder for [`BlockTransactionsRequest`].
+ pub struct BlockTransactionsRequestEncoder<'e>(
+ Encoder2<
+ BlockHashEncoder,
+ Encoder2<CompactSizeEncoder, SliceEncoder<'e, Offset>>
+ >
+ );
+}
+
+impl encoding::Encodable for BlockTransactionsRequest {
+ type Encoder<'e> = BlockTransactionsRequestEncoder<'e>;
+
+ fn encoder(&self) -> Self::Encoder<'_> {
+ BlockTransactionsRequestEncoder(
+ Encoder2::new(
+ self.block_hash.encoder(),
+ Encoder2::new(
+ CompactSizeEncoder::new(self.offsets.len()),
+ SliceEncoder::without_length_prefix(&self.offsets)
+ )
+ )
+ )
+ }
+}
+
+type BlockTransactionsRequestInnerDecoder = Decoder2<BlockHashDecoder, VecDecoder<Offset>>;
+
+/// The encoder type for a [`BlockTransactionsRequest`].
+pub struct BlockTransactionsRequestDecoder(BlockTransactionsRequestInnerDecoder);
+
+impl encoding::Decoder for BlockTransactionsRequestDecoder {
+ type Output = BlockTransactionsRequest;
+ type Error = BlockTransactionsRequestDecoderError;
+
+ #[inline]
+ fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error> {
+ self.0.push_bytes(bytes).map_err(BlockTransactionsRequestDecoderError)
+ }
+
+ #[inline]
+ fn end(self) -> Result<Self::Output, Self::Error> {
+ let (block_hash, offsets) = self.0.end().map_err(BlockTransactionsRequestDecoderError)?;
+ Ok(BlockTransactionsRequest { block_hash, offsets })
+ }
+
+ #[inline]
+ fn read_limit(&self) -> usize { self.0.read_limit() }
+}
+
+impl encoding::Decodable for BlockTransactionsRequest {
+ type Decoder = BlockTransactionsRequestDecoder;
+
+ fn decoder() -> Self::Decoder {
+ BlockTransactionsRequestDecoder(Decoder2::new(BlockHashDecoder::new(), VecDecoder::new()))
+ }
+}
+
+/// An error decoding a [`BlockTransactionsRequest`] message.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct BlockTransactionsRequestDecoderError(<BlockTransactionsRequestInnerDecoder as encoding::Decoder>::Error);
+
+impl From<Infallible> for BlockTransactionsRequestDecoderError {
+ fn from(never: Infallible) -> Self { match never {} }
+}
+
+impl fmt::Display for BlockTransactionsRequestDecoderError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write_err!(f, "blocktxnrequest error"; self.0)
+ }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for BlockTransactionsRequestDecoderError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
+}
+
impl Encodable for BlockTransactionsRequest {
fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
let mut len = self.block_hash.consensus_encode(w)?;
Why this scored 12/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.