Skip to content

Commit 4609769

Browse files
committed
Move internals::compact_size encoding into CompactSizeEncoder
Currently, the CompactSizeEncoder calls into the internals::compact_size module to perform the actual encoding process. This creates a strange API where there are two ways to do the same thing, one of which differs from how other encoders work. Move encode and encoded_size from internals::compact_size to the CompactSizeEncoder in consensus_encoding. Replace usage of compact_size::encode with pub(crate) function in primitives and direct usage of CompactSizeEncoder in bitcoin.
1 parent 1719fda commit 4609769

File tree

15 files changed

+173
-179
lines changed

15 files changed

+173
-179
lines changed

api/consensus_encoding/all-features.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ pub const fn bitcoin_consensus_encoding::ByteVecDecoder::new() -> Self
293293
pub const fn bitcoin_consensus_encoding::BytesEncoder<'sl>::without_length_prefix(sl: &'sl [u8]) -> Self
294294
pub const fn bitcoin_consensus_encoding::CompactSizeDecoder::new() -> Self
295295
pub const fn bitcoin_consensus_encoding::CompactSizeDecoder::new_with_limit(limit: usize) -> Self
296+
pub const fn bitcoin_consensus_encoding::CompactSizeEncoder::encoded_size(value: usize) -> usize
296297
pub const fn bitcoin_consensus_encoding::Decoder2<A, B>::new(first: A, second: B) -> Self
297298
pub const fn bitcoin_consensus_encoding::Decoder3<A, B, C>::new(dec_1: A, dec_2: B, dec_3: C) -> Self
298299
pub const fn bitcoin_consensus_encoding::Decoder4<A, B, C, D>::new(dec_1: A, dec_2: B, dec_3: C, dec_4: D) -> Self

api/consensus_encoding/alloc-only.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ pub const fn bitcoin_consensus_encoding::ByteVecDecoder::new() -> Self
272272
pub const fn bitcoin_consensus_encoding::BytesEncoder<'sl>::without_length_prefix(sl: &'sl [u8]) -> Self
273273
pub const fn bitcoin_consensus_encoding::CompactSizeDecoder::new() -> Self
274274
pub const fn bitcoin_consensus_encoding::CompactSizeDecoder::new_with_limit(limit: usize) -> Self
275+
pub const fn bitcoin_consensus_encoding::CompactSizeEncoder::encoded_size(value: usize) -> usize
275276
pub const fn bitcoin_consensus_encoding::Decoder2<A, B>::new(first: A, second: B) -> Self
276277
pub const fn bitcoin_consensus_encoding::Decoder3<A, B, C>::new(dec_1: A, dec_2: B, dec_3: C) -> Self
277278
pub const fn bitcoin_consensus_encoding::Decoder4<A, B, C, D>::new(dec_1: A, dec_2: B, dec_3: C, dec_4: D) -> Self

api/consensus_encoding/no-features.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ pub const fn bitcoin_consensus_encoding::ArrayEncoder<N>::without_length_prefix(
215215
pub const fn bitcoin_consensus_encoding::BytesEncoder<'sl>::without_length_prefix(sl: &'sl [u8]) -> Self
216216
pub const fn bitcoin_consensus_encoding::CompactSizeDecoder::new() -> Self
217217
pub const fn bitcoin_consensus_encoding::CompactSizeDecoder::new_with_limit(limit: usize) -> Self
218+
pub const fn bitcoin_consensus_encoding::CompactSizeEncoder::encoded_size(value: usize) -> usize
218219
pub const fn bitcoin_consensus_encoding::Decoder2<A, B>::new(first: A, second: B) -> Self
219220
pub const fn bitcoin_consensus_encoding::Decoder3<A, B, C>::new(dec_1: A, dec_2: B, dec_3: C) -> Self
220221
pub const fn bitcoin_consensus_encoding::Decoder4<A, B, C, D>::new(dec_1: A, dec_2: B, dec_3: C, dec_4: D) -> Self

api/internals/all-features.txt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,9 @@ impl<const N: usize, T> bitcoin_internals::array::ArrayExt for [T; N]
9494
pub bitcoin_internals::script::PushDataLenLen::Four = 4
9595
pub bitcoin_internals::script::PushDataLenLen::One = 1
9696
pub bitcoin_internals::script::PushDataLenLen::Two = 2
97-
pub const bitcoin_internals::compact_size::MAX_ENCODABLE_VALUE: u64
98-
pub const bitcoin_internals::compact_size::MAX_ENCODING_SIZE: usize
9997
pub const fn bitcoin_internals::array_vec::ArrayVec<T, CAP>::as_slice(&self) -> &[T]
10098
pub const fn bitcoin_internals::array_vec::ArrayVec<T, CAP>::from_slice(slice: &[T]) -> Self
10199
pub const fn bitcoin_internals::array_vec::ArrayVec<T, CAP>::new() -> Self
102-
pub const fn bitcoin_internals::compact_size::encoded_size_const(value: u64) -> usize
103100
pub const fn bitcoin_internals::const_casts::i16_to_i64(value: i16) -> i64
104101
pub const fn bitcoin_internals::const_casts::u16_to_u32(value: u16) -> u32
105102
pub const fn bitcoin_internals::const_casts::u16_to_u64(value: u16) -> u64
@@ -139,8 +136,6 @@ pub fn bitcoin_internals::array_vec::ArrayVec<T, CAP>::hash<H: core::hash::Hashe
139136
pub fn bitcoin_internals::array_vec::ArrayVec<T, CAP>::pop(&mut self) -> core::option::Option<T>
140137
pub fn bitcoin_internals::array_vec::ArrayVec<T, CAP>::push(&mut self, element: T)
141138
pub fn bitcoin_internals::compact_size::decode_unchecked(slice: &mut &[u8]) -> u64
142-
pub fn bitcoin_internals::compact_size::encode(value: impl bitcoin_internals::ToU64) -> bitcoin_internals::array_vec::ArrayVec<u8, MAX_ENCODING_SIZE>
143-
pub fn bitcoin_internals::compact_size::encoded_size(value: impl bitcoin_internals::ToU64) -> usize
144139
pub fn bitcoin_internals::error::input_string::CannotParse<'_, T>::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
145140
pub fn bitcoin_internals::error::input_string::InputString::clone(&self) -> bitcoin_internals::error::input_string::InputString
146141
pub fn bitcoin_internals::error::input_string::InputString::cmp(&self, other: &bitcoin_internals::error::input_string::InputString) -> core::cmp::Ordering

api/internals/alloc-only.txt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,9 @@ impl<const N: usize, T> bitcoin_internals::array::ArrayExt for [T; N]
8585
pub bitcoin_internals::script::PushDataLenLen::Four = 4
8686
pub bitcoin_internals::script::PushDataLenLen::One = 1
8787
pub bitcoin_internals::script::PushDataLenLen::Two = 2
88-
pub const bitcoin_internals::compact_size::MAX_ENCODABLE_VALUE: u64
89-
pub const bitcoin_internals::compact_size::MAX_ENCODING_SIZE: usize
9088
pub const fn bitcoin_internals::array_vec::ArrayVec<T, CAP>::as_slice(&self) -> &[T]
9189
pub const fn bitcoin_internals::array_vec::ArrayVec<T, CAP>::from_slice(slice: &[T]) -> Self
9290
pub const fn bitcoin_internals::array_vec::ArrayVec<T, CAP>::new() -> Self
93-
pub const fn bitcoin_internals::compact_size::encoded_size_const(value: u64) -> usize
9491
pub const fn bitcoin_internals::const_casts::i16_to_i64(value: i16) -> i64
9592
pub const fn bitcoin_internals::const_casts::u16_to_u32(value: u16) -> u32
9693
pub const fn bitcoin_internals::const_casts::u16_to_u64(value: u16) -> u64
@@ -128,8 +125,6 @@ pub fn bitcoin_internals::array_vec::ArrayVec<T, CAP>::hash<H: core::hash::Hashe
128125
pub fn bitcoin_internals::array_vec::ArrayVec<T, CAP>::pop(&mut self) -> core::option::Option<T>
129126
pub fn bitcoin_internals::array_vec::ArrayVec<T, CAP>::push(&mut self, element: T)
130127
pub fn bitcoin_internals::compact_size::decode_unchecked(slice: &mut &[u8]) -> u64
131-
pub fn bitcoin_internals::compact_size::encode(value: impl bitcoin_internals::ToU64) -> bitcoin_internals::array_vec::ArrayVec<u8, MAX_ENCODING_SIZE>
132-
pub fn bitcoin_internals::compact_size::encoded_size(value: impl bitcoin_internals::ToU64) -> usize
133128
pub fn bitcoin_internals::error::input_string::CannotParse<'_, T>::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
134129
pub fn bitcoin_internals::error::input_string::InputString::clone(&self) -> bitcoin_internals::error::input_string::InputString
135130
pub fn bitcoin_internals::error::input_string::InputString::cmp(&self, other: &bitcoin_internals::error::input_string::InputString) -> core::cmp::Ordering

api/internals/no-features.txt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,9 @@ impl<const N: usize, T> bitcoin_internals::array::ArrayExt for [T; N]
8282
pub bitcoin_internals::script::PushDataLenLen::Four = 4
8383
pub bitcoin_internals::script::PushDataLenLen::One = 1
8484
pub bitcoin_internals::script::PushDataLenLen::Two = 2
85-
pub const bitcoin_internals::compact_size::MAX_ENCODABLE_VALUE: u64
86-
pub const bitcoin_internals::compact_size::MAX_ENCODING_SIZE: usize
8785
pub const fn bitcoin_internals::array_vec::ArrayVec<T, CAP>::as_slice(&self) -> &[T]
8886
pub const fn bitcoin_internals::array_vec::ArrayVec<T, CAP>::from_slice(slice: &[T]) -> Self
8987
pub const fn bitcoin_internals::array_vec::ArrayVec<T, CAP>::new() -> Self
90-
pub const fn bitcoin_internals::compact_size::encoded_size_const(value: u64) -> usize
9188
pub const fn bitcoin_internals::const_casts::i16_to_i64(value: i16) -> i64
9289
pub const fn bitcoin_internals::const_casts::u16_to_u32(value: u16) -> u32
9390
pub const fn bitcoin_internals::const_casts::u16_to_u64(value: u16) -> u64
@@ -125,8 +122,6 @@ pub fn bitcoin_internals::array_vec::ArrayVec<T, CAP>::hash<H: core::hash::Hashe
125122
pub fn bitcoin_internals::array_vec::ArrayVec<T, CAP>::pop(&mut self) -> core::option::Option<T>
126123
pub fn bitcoin_internals::array_vec::ArrayVec<T, CAP>::push(&mut self, element: T)
127124
pub fn bitcoin_internals::compact_size::decode_unchecked(slice: &mut &[u8]) -> u64
128-
pub fn bitcoin_internals::compact_size::encode(value: impl bitcoin_internals::ToU64) -> bitcoin_internals::array_vec::ArrayVec<u8, MAX_ENCODING_SIZE>
129-
pub fn bitcoin_internals::compact_size::encoded_size(value: impl bitcoin_internals::ToU64) -> usize
130125
pub fn bitcoin_internals::error::input_string::CannotParse<'_, T>::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
131126
pub fn bitcoin_internals::error::input_string::InputString::clone(&self) -> bitcoin_internals::error::input_string::InputString
132127
pub fn bitcoin_internals::error::input_string::InputString::cmp(&self, other: &bitcoin_internals::error::input_string::InputString) -> core::cmp::Ordering

bitcoin/src/blockdata/block.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
use core::convert::Infallible;
1111
use core::fmt;
1212

13-
use internals::{compact_size, ToU64};
13+
use encoding::CompactSizeEncoder;
14+
use internals::ToU64;
1415
use io::{BufRead, Write};
1516

1617
use crate::consensus::encode::{self, Decodable, Encodable, WriteExt as _};
@@ -180,7 +181,7 @@ impl BlockCheckedExt for Block<Checked> {
180181
fn total_size(&self) -> usize {
181182
let mut size = Header::SIZE;
182183

183-
size += compact_size::encoded_size(self.transactions().len());
184+
size += CompactSizeEncoder::encoded_size(self.transactions().len());
184185
size += self.transactions().iter().map(|tx| tx.total_size()).sum::<usize>();
185186

186187
size
@@ -226,7 +227,7 @@ impl BlockCheckedExt for Block<Checked> {
226227
fn block_base_size(transactions: &[Transaction]) -> usize {
227228
let mut size = Header::SIZE;
228229

229-
size += compact_size::encoded_size(transactions.len());
230+
size += CompactSizeEncoder::encoded_size(transactions.len());
230231
size += transactions.iter().map(|tx| tx.base_size()).sum::<usize>();
231232

232233
size

bitcoin/src/blockdata/transaction.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ use core::fmt;
1414

1515
#[cfg(feature = "arbitrary")]
1616
use arbitrary::{Arbitrary, Unstructured};
17-
use internals::{compact_size, const_casts, write_err, ToU64};
17+
use encoding::CompactSizeEncoder;
18+
use internals::{const_casts, write_err, ToU64};
1819
use io::{BufRead, Write};
1920

2021
use super::Weight;
@@ -172,7 +173,7 @@ internal_macros::define_extension_trait! {
172173
fn base_size(&self) -> usize {
173174
let mut size = OutPoint::SIZE;
174175

175-
size += compact_size::encoded_size(self.script_sig.len());
176+
size += CompactSizeEncoder::encoded_size(self.script_sig.len());
176177
size += self.script_sig.len();
177178

178179
size + Sequence::SIZE
@@ -249,7 +250,7 @@ internal_macros::define_extension_trait! {
249250
/// Returns the total number of bytes that this script pubkey would contribute to a transaction.
250251
fn size_from_script_pubkey(script_pubkey: &ScriptPubKey) -> usize {
251252
let len = script_pubkey.len();
252-
Amount::SIZE + compact_size::encoded_size(len) + len
253+
Amount::SIZE + CompactSizeEncoder::encoded_size(len) + len
253254
}
254255

255256
/// Extension functionality for the [`Transaction`] type.
@@ -390,10 +391,10 @@ impl TransactionExt for Transaction {
390391
fn base_size(&self) -> usize {
391392
let mut size: usize = 4; // Serialized length of a u32 for the version number.
392393

393-
size += compact_size::encoded_size(self.inputs.len());
394+
size += CompactSizeEncoder::encoded_size(self.inputs.len());
394395
size += self.inputs.iter().map(|input| input.base_size()).sum::<usize>();
395396

396-
size += compact_size::encoded_size(self.outputs.len());
397+
size += CompactSizeEncoder::encoded_size(self.outputs.len());
397398
size += self.outputs.iter().map(|output| output.size()).sum::<usize>();
398399

399400
size + absolute::LockTime::SIZE
@@ -408,14 +409,14 @@ impl TransactionExt for Transaction {
408409
size += 2; // 1 byte for the marker and 1 for the flag.
409410
}
410411

411-
size += compact_size::encoded_size(self.inputs.len());
412+
size += CompactSizeEncoder::encoded_size(self.inputs.len());
412413
size += self
413414
.inputs
414415
.iter()
415416
.map(|input| if uses_segwit { input.total_size() } else { input.base_size() })
416417
.sum::<usize>();
417418

418-
size += compact_size::encoded_size(self.outputs.len());
419+
size += CompactSizeEncoder::encoded_size(self.outputs.len());
419420
size += self.outputs.iter().map(|output| output.size()).sum::<usize>();
420421

421422
size + absolute::LockTime::SIZE
@@ -877,7 +878,7 @@ where
877878

878879
let (output_count, output_scripts_size) =
879880
output_script_lens.into_iter().fold((0, 0), |(count, scripts_size), script_len| {
880-
(count + 1, scripts_size + script_len + compact_size::encoded_size(script_len))
881+
(count + 1, scripts_size + script_len + CompactSizeEncoder::encoded_size(script_len))
881882
});
882883

883884
predict_weight_internal(
@@ -899,8 +900,8 @@ const fn predict_weight_internal(
899900
// The value field of a TxOut is 8 bytes.
900901
let output_size = 8 * output_count + output_scripts_size;
901902
let non_input_size = 4 // version
902-
+ compact_size::encoded_size_const(input_count as u64) // Can't use ToU64 in const context.
903-
+ compact_size::encoded_size_const(output_count as u64)
903+
+ CompactSizeEncoder::encoded_size(input_count) // Can't use ToU64 in const context.
904+
+ CompactSizeEncoder::encoded_size(output_count)
904905
+ output_size
905906
+ 4; // locktime
906907
let weight = if inputs_with_witnesses == 0 {
@@ -939,7 +940,7 @@ pub const fn predict_weight_from_slices(
939940
i = 0;
940941
while i < output_script_lens.len() {
941942
let script_len = output_script_lens[i];
942-
output_scripts_size += script_len + compact_size::encoded_size_const(script_len as u64);
943+
output_scripts_size += script_len + CompactSizeEncoder::encoded_size(script_len);
943944
i += 1;
944945
}
945946

bitcoin/src/consensus/encode.rs

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@
1717
use core::any::TypeId;
1818
use core::{cmp, mem, slice};
1919

20+
use encoding::{CompactSizeEncoder, Encoder};
2021
use hashes::{sha256, sha256d, Hash};
2122
use hex::DisplayHex as _;
22-
use internals::{compact_size, ToU64};
23+
use internals::ToU64;
2324
use io::{BufRead, Cursor, Read, Write};
2425

2526
use super::IterReader;
@@ -184,8 +185,9 @@ impl<W: Write + ?Sized> WriteExt for W {
184185
}
185186
#[inline]
186187
fn emit_compact_size(&mut self, v: impl ToU64) -> Result<usize, io::Error> {
187-
let encoded = compact_size::encode(v.to_u64());
188-
self.emit_slice(&encoded)?;
188+
let encoder = CompactSizeEncoder::new(v.to_u64().try_into().unwrap_or(usize::MAX));
189+
let encoded = encoder.current_chunk();
190+
self.emit_slice(encoded)?;
189191
Ok(encoded.len())
190192
}
191193
}
@@ -349,19 +351,28 @@ impl_int_encodable!(i32, read_i32, emit_i32);
349351
impl_int_encodable!(i64, read_i64, emit_i64);
350352

351353
/// Returns 1 for 0..=0xFC, 3 for 0xFD..=(2^16-1), 5 for 0x10000..=(2^32-1), and 9 otherwise.
354+
#[deprecated(since = "0.33.0", note = "use `consensus_encoding::CompactSizeEncoder::encoded_size` instead")]
352355
#[inline]
353356
pub const fn varint_size_u64(v: u64) -> usize {
357+
const LIMIT: u64 = if core::mem::size_of::<usize>() <= 8 {
358+
usize::MAX as u64 // Cast is ok, because usize is <= the size of u64
359+
} else {
360+
u64::MAX
361+
};
362+
363+
#[allow(unreachable_patterns)] // Disable lint because this match is reachable on < 64 bit platforms
354364
match v {
355-
0..=0xFC => 1,
356-
0xFD..=0xFFFF => 3,
357-
0x10000..=0xFFFFFFFF => 5,
358-
_ => 9,
365+
0..=LIMIT => encoding::CompactSizeEncoder::encoded_size(v as usize), // cast is ok because we just checked bounds
366+
_ => encoding::CompactSizeEncoder::encoded_size(usize::MAX),
359367
}
360368
}
361369

362370
/// Returns 1 for 0..=0xFC, 3 for 0xFD..=(2^16-1), 5 for 0x10000..=(2^32-1), and 9 otherwise.
371+
#[deprecated(since = "0.33.0", note = "use `consensus_encoding::CompactSizeEncoder::encoded_size` instead")]
363372
#[inline]
364-
pub fn varint_size(v: impl ToU64) -> usize { varint_size_u64(v.to_u64()) }
373+
pub fn varint_size(v: impl ToU64) -> usize {
374+
encoding::CompactSizeEncoder::encoded_size(v.to_u64().try_into().unwrap_or(usize::MAX))
375+
}
365376

366377
impl Encodable for bool {
367378
#[inline]
@@ -807,25 +818,29 @@ mod tests {
807818
assert_eq!(encode(0xFD), [0xFDu8, 0xFD, 0]);
808819
assert_eq!(encode(0xFFF), [0xFDu8, 0xFF, 0xF]);
809820
assert_eq!(encode(0xF0F0F0F), [0xFEu8, 0xF, 0xF, 0xF, 0xF]);
821+
#[cfg(target_pointer_width = "64")]
810822
assert_eq!(encode(0xF0F0F0F0F0E0), vec![0xFFu8, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0, 0],);
811823
assert_eq!(test_varint_encode(0xFF, &0x100000000_u64.to_le_bytes()).unwrap(), 0x100000000,);
812824
assert_eq!(test_varint_encode(0xFE, &0x10000_u64.to_le_bytes()).unwrap(), 0x10000);
813825
assert_eq!(test_varint_encode(0xFD, &0xFD_u64.to_le_bytes()).unwrap(), 0xFD);
814826

815827
// Test that length calc is working correctly
816-
fn test_varint_len(varint: u64, expected: usize) {
828+
fn test_varint_len(varint: usize, expected: usize) {
817829
let mut encoder = vec![];
818830
assert_eq!(encoder.emit_compact_size(varint).unwrap(), expected);
819-
assert_eq!(varint_size(varint), expected);
831+
assert_eq!(encoding::CompactSizeEncoder::encoded_size(varint), expected);
820832
}
821833
test_varint_len(0, 1);
822834
test_varint_len(0xFC, 1);
823835
test_varint_len(0xFD, 3);
824836
test_varint_len(0xFFFF, 3);
825837
test_varint_len(0x10000, 5);
826838
test_varint_len(0xFFFFFFFF, 5);
827-
test_varint_len(0xFFFFFFFF + 1, 9);
828-
test_varint_len(u64::MAX, 9);
839+
#[cfg(target_pointer_width = "64")]
840+
{
841+
test_varint_len(0xFFFFFFFF + 1, 9);
842+
test_varint_len(u64::MAX as usize, 9);
843+
}
829844
}
830845

831846
#[test]

bitcoin/src/psbt/serialize.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
//! Traits to serialize PSBT values to and from raw bytes
66
//! according to the BIP-0174 specification.
77
8+
use encoding::CompactSizeEncoder;
89
use hashes::{hash160, ripemd160, sha256, sha256d};
9-
use internals::compact_size;
1010
#[allow(unused)] // MSRV polyfill
1111
use internals::slice::SliceExt;
1212

@@ -389,7 +389,7 @@ impl Serialize for TapTree {
389389
let capacity = self
390390
.script_leaves()
391391
.map(|l| {
392-
l.script().len() + compact_size::encoded_size(l.script().len()) // script version
392+
l.script().len() + CompactSizeEncoder::encoded_size(l.script().len()) // script version
393393
+ 1 // merkle branch
394394
+ 1 // leaf version
395395
})

0 commit comments

Comments
 (0)