Skip to content

Commit b486c83

Browse files
committed
Use usize for CompactSizeEncoder::new
The current CompactSizeEncoder::new() constructor uses an impl ToU64 for its first parameter. The ToU64 trait is part of internals, and thus isn't permitted to be part of the public API of consensus_encoding. Change the ToU64 parameter type to usize, encoding values outside of the u64 range (such as on 128 bit system) as u64::MAX.
1 parent 9bc2919 commit b486c83

File tree

6 files changed

+42
-21
lines changed

6 files changed

+42
-21
lines changed

api/consensus_encoding/all-features.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ pub fn bitcoin_consensus_encoding::CompactSizeDecoderError::eq(&self, other: &bi
326326
pub fn bitcoin_consensus_encoding::CompactSizeDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
327327
pub fn bitcoin_consensus_encoding::CompactSizeEncoder::advance(&mut self) -> bool
328328
pub fn bitcoin_consensus_encoding::CompactSizeEncoder::current_chunk(&self) -> &[u8]
329-
pub fn bitcoin_consensus_encoding::CompactSizeEncoder::new(value: impl bitcoin_internals::ToU64) -> Self
329+
pub fn bitcoin_consensus_encoding::CompactSizeEncoder::new(value: usize) -> Self
330330
pub fn bitcoin_consensus_encoding::Decodable::decoder() -> Self::Decoder
331331
pub fn bitcoin_consensus_encoding::Decoder2<A, B>::end(self) -> core::result::Result<Self::Output, Self::Error>
332332
pub fn bitcoin_consensus_encoding::Decoder2<A, B>::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result<bool, Self::Error>

api/consensus_encoding/alloc-only.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ pub fn bitcoin_consensus_encoding::CompactSizeDecoderError::eq(&self, other: &bi
303303
pub fn bitcoin_consensus_encoding::CompactSizeDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
304304
pub fn bitcoin_consensus_encoding::CompactSizeEncoder::advance(&mut self) -> bool
305305
pub fn bitcoin_consensus_encoding::CompactSizeEncoder::current_chunk(&self) -> &[u8]
306-
pub fn bitcoin_consensus_encoding::CompactSizeEncoder::new(value: impl bitcoin_internals::ToU64) -> Self
306+
pub fn bitcoin_consensus_encoding::CompactSizeEncoder::new(value: usize) -> Self
307307
pub fn bitcoin_consensus_encoding::Decodable::decoder() -> Self::Decoder
308308
pub fn bitcoin_consensus_encoding::Decoder2<A, B>::end(self) -> core::result::Result<Self::Output, Self::Error>
309309
pub fn bitcoin_consensus_encoding::Decoder2<A, B>::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result<bool, Self::Error>

api/consensus_encoding/no-features.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ pub fn bitcoin_consensus_encoding::CompactSizeDecoderError::eq(&self, other: &bi
237237
pub fn bitcoin_consensus_encoding::CompactSizeDecoderError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
238238
pub fn bitcoin_consensus_encoding::CompactSizeEncoder::advance(&mut self) -> bool
239239
pub fn bitcoin_consensus_encoding::CompactSizeEncoder::current_chunk(&self) -> &[u8]
240-
pub fn bitcoin_consensus_encoding::CompactSizeEncoder::new(value: impl bitcoin_internals::ToU64) -> Self
240+
pub fn bitcoin_consensus_encoding::CompactSizeEncoder::new(value: usize) -> Self
241241
pub fn bitcoin_consensus_encoding::Decodable::decoder() -> Self::Decoder
242242
pub fn bitcoin_consensus_encoding::Decoder2<A, B>::end(self) -> core::result::Result<Self::Output, Self::Error>
243243
pub fn bitcoin_consensus_encoding::Decoder2<A, B>::push_bytes(&mut self, bytes: &mut &[u8]) -> core::result::Result<bool, Self::Error>

consensus_encoding/src/encode/encoders.rs

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
//!
1313
1414
use internals::array_vec::ArrayVec;
15-
use internals::{compact_size, ToU64};
15+
use internals::compact_size;
1616

1717
use super::{Encodable, Encoder};
1818

@@ -226,7 +226,16 @@ pub struct CompactSizeEncoder {
226226

227227
impl CompactSizeEncoder {
228228
/// Constructs a new `CompactSizeEncoder`.
229-
pub fn new(value: impl ToU64) -> Self { Self { buf: Some(compact_size::encode(value)) } }
229+
///
230+
/// Encodings are defined only for the range of u64. On systems where usize is
231+
/// larger than u64, it will be possible to call this method with out-of-range
232+
/// values. In such cases we will ignore the passed value and encode [`u64::MAX`].
233+
/// But even on such exotic systems, we expect users to pass the length of an
234+
/// in-memory object, meaning that such large values are impossible to obtain.
235+
pub fn new(value: usize) -> Self {
236+
let enc_value = value.try_into().unwrap_or(u64::MAX);
237+
Self { buf: Some(compact_size::encode(enc_value)) }
238+
}
230239
}
231240

232241
impl Encoder for CompactSizeEncoder {
@@ -554,42 +563,54 @@ mod tests {
554563
#[test]
555564
fn encode_compact_size() {
556565
// 1-byte
557-
let mut e = CompactSizeEncoder::new(0x10u64);
566+
let mut e = CompactSizeEncoder::new(0x10usize);
558567
assert_eq!(e.current_chunk(), &[0x10][..]);
559568
assert!(!e.advance());
560569
assert!(e.current_chunk().is_empty());
561570

562-
let mut e = CompactSizeEncoder::new(0xFCu64);
571+
let mut e = CompactSizeEncoder::new(0xFCusize);
563572
assert_eq!(e.current_chunk(), &[0xFC][..]);
564573
assert!(!e.advance());
565574
assert!(e.current_chunk().is_empty());
566575

567576
// 0xFD + u16
568-
let mut e = CompactSizeEncoder::new(0x00FDu64);
577+
let mut e = CompactSizeEncoder::new(0x00FDusize);
569578
assert_eq!(e.current_chunk(), &[0xFD, 0xFD, 0x00][..]);
570579
assert!(!e.advance());
571580
assert!(e.current_chunk().is_empty());
572581

573-
let mut e = CompactSizeEncoder::new(0x0FFFu64);
582+
let mut e = CompactSizeEncoder::new(0x0FFFusize);
574583
assert_eq!(e.current_chunk(), &[0xFD, 0xFF, 0x0F][..]);
575584
assert!(!e.advance());
576585
assert!(e.current_chunk().is_empty());
577586

578587
// 0xFE + u32
579-
let mut e = CompactSizeEncoder::new(0x0001_0000u64);
588+
let mut e = CompactSizeEncoder::new(0x0001_0000usize);
580589
assert_eq!(e.current_chunk(), &[0xFE, 0x00, 0x00, 0x01, 0x00][..]);
581590
assert!(!e.advance());
582591
assert!(e.current_chunk().is_empty());
583592

584-
let mut e = CompactSizeEncoder::new(0x0F0F_0F0Fu64);
593+
let mut e = CompactSizeEncoder::new(0x0F0F_0F0Fusize);
585594
assert_eq!(e.current_chunk(), &[0xFE, 0x0F, 0x0F, 0x0F, 0x0F][..]);
586595
assert!(!e.advance());
587596
assert!(e.current_chunk().is_empty());
588597

589598
// 0xFF + u64
590-
let mut e = CompactSizeEncoder::new(0x0000_F0F0_F0F0_F0E0u64);
591-
assert_eq!(e.current_chunk(), &[0xFF, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00][..]);
592-
assert!(!e.advance());
593-
assert!(e.current_chunk().is_empty());
599+
// This test only runs on systems with >= 64 bit usize.
600+
if core::mem::size_of::<usize>() >= 8 {
601+
let mut e = CompactSizeEncoder::new(0x0000_F0F0_F0F0_F0E0u64 as usize);
602+
assert_eq!(e.current_chunk(), &[0xFF, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00][..]);
603+
assert!(!e.advance());
604+
assert!(e.current_chunk().is_empty());
605+
}
606+
607+
// > u64::MAX encodes as u64::MAX.
608+
// This test only runs on systems with > 64 bit usize.
609+
if core::mem::size_of::<usize>() > 8 {
610+
let mut e = CompactSizeEncoder::new((u128::from(u64::MAX) + 5) as usize);
611+
assert_eq!(e.current_chunk(), &[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF][..]);
612+
assert!(!e.advance());
613+
assert!(e.current_chunk().is_empty());
614+
}
594615
}
595616
}

consensus_encoding/tests/encode.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,19 +153,19 @@ fn encode_slice_encoder_mixed_empty_and_data() {
153153
#[test]
154154
fn encode_compact_size_boundary_values() {
155155
// Test CompactSizeEncoder with boundary values.
156-
let mut encoder = CompactSizeEncoder::new(252u32);
156+
let mut encoder = CompactSizeEncoder::new(252usize);
157157
assert_eq!(encoder.current_chunk(), &[252]);
158158
assert!(!encoder.advance());
159159

160-
let mut encoder = CompactSizeEncoder::new(253u32);
160+
let mut encoder = CompactSizeEncoder::new(253usize);
161161
assert_eq!(encoder.current_chunk(), &[0xFD, 253, 0]);
162162
assert!(!encoder.advance());
163163

164-
let mut encoder = CompactSizeEncoder::new(0x10000u32);
164+
let mut encoder = CompactSizeEncoder::new(0x10000usize);
165165
assert_eq!(encoder.current_chunk(), &[0xFE, 0, 0, 1, 0]);
166166
assert!(!encoder.advance());
167167

168-
let mut encoder = CompactSizeEncoder::new(0u32);
168+
let mut encoder = CompactSizeEncoder::new(0usize);
169169
assert_eq!(encoder.current_chunk(), &[0]);
170170
assert!(!encoder.advance());
171171
}

primitives/src/transaction.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,11 +330,11 @@ impl Encodable for Transaction {
330330
fn encoder(&self) -> Self::Encoder<'_> {
331331
let version = self.version.encoder();
332332
let inputs = Encoder2::new(
333-
CompactSizeEncoder::new(self.inputs.len() as u64),
333+
CompactSizeEncoder::new(self.inputs.len()),
334334
SliceEncoder::without_length_prefix(self.inputs.as_ref()),
335335
);
336336
let outputs = Encoder2::new(
337-
CompactSizeEncoder::new(self.outputs.len() as u64),
337+
CompactSizeEncoder::new(self.outputs.len()),
338338
SliceEncoder::without_length_prefix(self.outputs.as_ref()),
339339
);
340340
let lock_time = self.lock_time.encoder();

0 commit comments

Comments
 (0)