p2p: Add CommandStringEncoder newtype
What changed, and why it matters
This commit is a simple internal code cleanup in the Bitcoin peer-to-peer networking code. It renames a generic array-based encoder to a more specific 'CommandStringEncoder' for the 12-byte command strings used in Bitcoin network messages. There is no change to behavior, data formats, or security properties.
No security action required. This is a non-functional refactor. Normal code review and merge procedures apply.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch introduces a newtype wrapper CommandStringEncoder around ArrayEncoder<12> and replaces direct uses of ArrayEncoder<12> for CommandString encoding. The newtype implements the Encoder and ExactSizeEncoder traits by delegating to the inner ArrayEncoder. The commit message explicitly states the motivation is semantic clarity and matching standard implementations, and notes the manual implementation is required due to lifetime conflicts with the encoder_newtype! macro in V1NetworkMessage. No functional logic changes.
Changed components
p2p/src/message.rsCommandString encodingV1NetworkMessage encoderInspect captured patch +28 / −3
diff --git a/p2p/src/message.rs b/p2p/src/message.rs
index 1bcd5a9b..2b2387c8 100644
--- a/p2p/src/message.rs
+++ b/p2p/src/message.rs
@@ -139,14 +139,14 @@ impl Decodable for CommandString {
}
impl encoding::Encodable for CommandString {
- type Encoder<'e> = encoding::ArrayEncoder<12>;
+ type Encoder<'e> = CommandStringEncoder;
fn encoder(&self) -> Self::Encoder<'_> {
let mut rawbytes = [0u8; 12];
let strbytes = self.0.as_bytes();
debug_assert!(strbytes.len() <= 12);
rawbytes[..strbytes.len()].copy_from_slice(strbytes);
- encoding::ArrayEncoder::without_length_prefix(rawbytes)
+ CommandStringEncoder::without_length_prefix(rawbytes)
}
}
@@ -156,6 +156,31 @@ impl encoding::Decodable for CommandString {
fn decoder() -> Self::Decoder { CommandStringDecoder { inner: encoding::ArrayDecoder::new() } }
}
+/// Encoder for the [`CommandString`] type
+// We can't use the [`encoder_newtype!`] macro due to the lifetime conflicting
+// when constructing the encoder in `V1NetworkMessage`.
+pub struct CommandStringEncoder(encoding::ArrayEncoder<12>);
+
+impl CommandStringEncoder {
+ /// Constructs an encoder which encodes the command string with no length prefix.
+ pub const fn without_length_prefix(arr: [u8; 12]) -> Self {
+ Self(encoding::ArrayEncoder::without_length_prefix(arr))
+ }
+}
+
+impl encoding::Encoder for CommandStringEncoder {
+ #[inline]
+ fn current_chunk(&self) -> &[u8] { self.0.current_chunk() }
+
+ #[inline]
+ fn advance(&mut self) -> bool { self.0.advance() }
+}
+
+impl encoding::ExactSizeEncoder for CommandStringEncoder {
+ #[inline]
+ fn len(&self) -> usize { 12 }
+}
+
/// Decoder for [`CommandString`].
pub struct CommandStringDecoder {
inner: encoding::ArrayDecoder<12>,
@@ -841,7 +866,7 @@ encoding::encoder_newtype! {
encoding::Encoder2<
encoding::Encoder4<
encoding::ArrayEncoder<4>,
- encoding::ArrayEncoder<12>,
+ CommandStringEncoder,
encoding::ArrayEncoder<4>,
encoding::ArrayEncoder<4>,
>,
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.