consensus_encoding: Add `CompactSizeEncoder` implementation
What changed, and why it matters
This commit adds a new helper for writing Bitcoin-style compact-size numbers. It is a straightforward feature addition with no visible security bug. There is no indication it fixes a vulnerability or introduces a dangerous behavior.
No security action required. Review as normal code-quality/feature addition.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch introduces CompactSizeEncoder in consensus_encoding/src/encode/encoders.rs. It wraps internals::compact_size::encode and implements the Encoder trait so callers can stream compact-size bytes. The implementation is stateless except for an Option
Changed components
consensus_encoding/src/encode/encoders.rsInspect captured patch +60 / −1
diff --git a/consensus_encoding/src/encode/encoders.rs b/consensus_encoding/src/encode/encoders.rs
index dcb011f2..d4d69c7c 100644
--- a/consensus_encoding/src/encode/encoders.rs
+++ b/consensus_encoding/src/encode/encoders.rs
@@ -12,7 +12,7 @@
//!
use internals::array_vec::ArrayVec;
-use internals::compact_size;
+use internals::{compact_size, ToU64};
use super::{Encodable, Encoder};
@@ -250,6 +250,27 @@ impl<A: Encoder, B: Encoder, C: Encoder, D: Encoder, E: Encoder, F: Encoder> Enc
fn advance(&mut self) -> bool { self.inner.advance() }
}
+/// Encoder for a compact size encoded integer.
+pub struct CompactSizeEncoder {
+ buf: Option<ArrayVec<u8, SIZE>>,
+}
+
+impl CompactSizeEncoder {
+ /// Constructs a new `CompactSizeEncoder`.
+ pub fn new(value: impl ToU64) -> Self { Self { buf: Some(compact_size::encode(value)) } }
+}
+
+impl Encoder for CompactSizeEncoder {
+ #[inline]
+ fn current_chunk(&self) -> Option<&[u8]> { self.buf.as_ref().map(|b| &b[..]) }
+
+ #[inline]
+ fn advance(&mut self) -> bool {
+ self.buf = None;
+ false
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -651,4 +672,42 @@ mod tests {
assert!(!encoder.advance());
assert_eq!(encoder.current_chunk(), None);
}
+ #[test]
+ fn encode_compact_size() {
+ // 1-byte
+ let mut e = CompactSizeEncoder::new(0x10u64);
+ assert_eq!(e.current_chunk(), Some(&[0x10][..]));
+ assert!(!e.advance());
+ assert_eq!(e.current_chunk(), None);
+
+ let mut e = CompactSizeEncoder::new(0xFCu64);
+ assert_eq!(e.current_chunk(), Some(&[0xFC][..]));
+ assert!(!e.advance());
+
+ // 0xFD + u16
+ let mut e = CompactSizeEncoder::new(0x00FDu64);
+ assert_eq!(e.current_chunk(), Some(&[0xFD, 0xFD, 0x00][..]));
+ assert!(!e.advance());
+
+ let mut e = CompactSizeEncoder::new(0x0FFFu64);
+ assert_eq!(e.current_chunk(), Some(&[0xFD, 0xFF, 0x0F][..]));
+ assert!(!e.advance());
+
+ // 0xFE + u32
+ let mut e = CompactSizeEncoder::new(0x0001_0000u64);
+ assert_eq!(e.current_chunk(), Some(&[0xFE, 0x00, 0x00, 0x01, 0x00][..]));
+ assert!(!e.advance());
+
+ let mut e = CompactSizeEncoder::new(0x0F0F_0F0Fu64);
+ assert_eq!(e.current_chunk(), Some(&[0xFE, 0x0F, 0x0F, 0x0F, 0x0F][..]));
+ assert!(!e.advance());
+
+ // 0xFF + u64
+ let mut e = CompactSizeEncoder::new(0x0000_F0F0_F0F0_F0E0u64);
+ assert_eq!(
+ e.current_chunk(),
+ Some(&[0xFF, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00][..])
+ );
+ assert!(!e.advance());
+ }
}
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.