p2p: Implement `encoding` traits for `AddrV1Message`
What changed, and why it matters
This commit adds new serialization/deserialization code for an existing Bitcoin peer-to-peer message type (AddrV1Message). It is a straightforward refactoring that implements the project's newer 'encoding' traits for a struct that already had older consensus encoding support. There is no indication of a security bug being fixed or introduced.
No security action required. Review as normal code-quality/refactoring change.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change in p2p/src/address.rs introduces AddrV1MessageEncoder, AddrV1MessageDecoder, and AddrV1MessageDecoderError, plus Encodable/Decodable implementations using the project’s newer encoding framework. The existing crate::consensus::impl_consensus_encoding! macro invocation remains in place. The decoder reads a 4-byte little-endian timestamp and an Address. No bounds, validation, or logic changes are visible; this is preparatory work for a later AddrPayload refactor.
Changed components
p2p/src/address.rsAddrV1MessageInspect captured patch +72 / −1
diff --git a/p2p/src/address.rs b/p2p/src/address.rs
index a7502e82..d62cb24d 100644
--- a/p2p/src/address.rs
+++ b/p2p/src/address.rs
@@ -15,7 +15,7 @@ use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV
use arbitrary::{Arbitrary, Unstructured};
use bitcoin::consensus::encode::{self, Decodable, Encodable, ReadExt, WriteExt};
use encoding::{
- ArrayDecoder, ArrayEncoder, ByteVecDecoder, BytesEncoder, CompactSizeEncoder, Decoder2,
+ ArrayDecoder, ArrayEncoder, ByteVecDecoder, BytesEncoder, CompactSizeEncoder, Decoder2, Encoder2,
};
use internals::array::ArrayExt;
use internals::write_err;
@@ -255,6 +255,77 @@ pub struct AddrV1Message {
pub address: Address,
}
+encoding::encoder_newtype! {
+ /// The encoder for an [`AddrV1Message`].
+ pub struct AddrV1MessageEncoder<'e>(Encoder2<ArrayEncoder<4>, AddressEncoder<'e>>);
+}
+
+impl encoding::Encodable for AddrV1Message {
+ type Encoder<'e> = AddrV1MessageEncoder<'e>;
+
+ fn encoder(&self) -> Self::Encoder<'_> {
+ AddrV1MessageEncoder::new(Encoder2::new(
+ ArrayEncoder::without_length_prefix(self.time.to_le_bytes()),
+ self.address.encoder()
+ ))
+ }
+}
+
+type AddrV1MessageInnerDecoder = Decoder2<ArrayDecoder<4>, AddressDecoder>;
+
+/// The decoder for an [`AddrV2Message`].
+pub struct AddrV1MessageDecoder(AddrV1MessageInnerDecoder);
+
+impl encoding::Decoder for AddrV1MessageDecoder {
+ type Output = AddrV1Message;
+ type Error = AddrV1MessageDecoderError;
+
+ #[inline]
+ fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error> {
+ self.0.push_bytes(bytes).map_err(AddrV1MessageDecoderError)
+ }
+
+ #[inline]
+ fn end(self) -> Result<Self::Output, Self::Error> {
+ let (time, address) = self.0.end().map_err(AddrV1MessageDecoderError)?;
+ let time = u32::from_le_bytes(time);
+ Ok(AddrV1Message { time, address })
+ }
+
+ #[inline]
+ fn read_limit(&self) -> usize { self.0.read_limit() }
+}
+
+impl encoding::Decodable for AddrV1Message {
+ type Decoder = AddrV1MessageDecoder;
+
+ fn decoder() -> Self::Decoder {
+ AddrV1MessageDecoder(AddrV1MessageInnerDecoder::new(
+ ArrayDecoder::new(),
+ Address::decoder())
+ )
+ }
+}
+
+/// An error occuring when decoding a [`AddrV1Message`].
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct AddrV1MessageDecoderError(<AddrV1MessageInnerDecoder as encoding::Decoder>::Error);
+
+impl From<Infallible> for AddrV1MessageDecoderError {
+ fn from(never: Infallible) -> Self { match never {} }
+}
+
+impl fmt::Display for AddrV1MessageDecoderError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write_err!(f, "addrv1 message error"; self.0)
+ }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for AddrV1MessageDecoderError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
+}
+
crate::consensus::impl_consensus_encoding!(AddrV1Message, time, address);
/// Supported networks for use in BIP-0155 addrv2 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.