@@ -144,35 +144,50 @@ impl Decodable for QuorumCommitmentPayload {
144144 }
145145}
146146
147- fn read_compact_size < R : Read + ?Sized > ( r : & mut R ) -> io:: Result < u64 > {
147+ fn read_compact_size < R : Read + ?Sized > ( r : & mut R ) -> io:: Result < u32 > {
148148 let mut marker = [ 0u8 ; 1 ] ;
149149 r. read_exact ( & mut marker) ?;
150150 match marker[ 0 ] {
151151 0xFD => {
152- // Read the next 2 bytes as a little-endian u16
153152 let mut buf = [ 0u8 ; 2 ] ;
154153 r. read_exact ( & mut buf) ?;
155- Ok ( u16:: from_le_bytes ( buf) as u64 )
154+ Ok ( u16:: from_le_bytes ( buf) as u32 )
156155 }
157156 0xFE => {
158- // Read the next 4 bytes as a little-endian u32
159157 let mut buf = [ 0u8 ; 4 ] ;
160158 r. read_exact ( & mut buf) ?;
161- Ok ( u32:: from_le_bytes ( buf) as u64 )
159+ Ok ( u32:: from_le_bytes ( buf) )
162160 }
163161 0xFF => {
164- // Read the next 8 bytes as a little-endian u64
165- let mut buf = [ 0u8 ; 8 ] ;
166- r. read_exact ( & mut buf) ?;
167- Ok ( u64:: from_le_bytes ( buf) )
168- }
169- value => {
170- // For values less than 253, the value is stored directly in the marker byte
171- Ok ( value as u64 )
162+ // Value is too large to fit in u32
163+ Err ( io:: Error :: new (
164+ io:: ErrorKind :: InvalidData ,
165+ "CompactSize value exceeds u32::MAX" ,
166+ ) )
172167 }
168+ value => Ok ( value as u32 ) ,
173169 }
174170}
175171
172+ fn write_compact_size < W : Write > ( w : & mut W , value : u32 ) -> io:: Result < usize > {
173+ let bytes_written = if value < 253 {
174+ // For values less than 253, write the value as a single byte.
175+ w. write_all ( & [ value as u8 ] ) ?;
176+ 1 // 1 byte written
177+ } else if value <= 0xFFFF {
178+ // For values from 253 to 65535, write 0xFD followed by the value as a little-endian u16.
179+ w. write_all ( & [ 0xFDu8 ] ) ?;
180+ w. write_all ( & ( value as u16 ) . to_le_bytes ( ) ) ?;
181+ 3 // 1 byte marker + 2 bytes for u16
182+ } else {
183+ // For values from 65536 to 0xFFFFFFFF, write 0xFE followed by the value as a little-endian u32.
184+ w. write_all ( & [ 0xFEu8 ] ) ?;
185+ w. write_all ( & value. to_le_bytes ( ) ) ?;
186+ 5 // 1 byte marker + 4 bytes for u32
187+ } ;
188+ Ok ( bytes_written)
189+ }
190+
176191fn read_fixed_bitset < R : Read + ?Sized > ( r : & mut R , size : usize ) -> std:: io:: Result < Vec < bool > > {
177192 // Calculate the number of bytes needed
178193 let num_bytes = ( size + 7 ) / 8 ;
@@ -194,14 +209,13 @@ fn read_fixed_bitset<R: Read + ?Sized>(r: &mut R, size: usize) -> std::io::Resul
194209
195210#[ cfg( test) ]
196211mod tests {
212+ use std:: io:: Cursor ;
197213 use hashes:: Hash ;
198214
199215 use crate :: bls_sig_utils:: { BLSPublicKey , BLSSignature } ;
200216 use crate :: consensus:: Encodable ;
201217 use crate :: hash_types:: { QuorumHash , QuorumVVecHash } ;
202- use crate :: transaction:: special_transaction:: quorum_commitment:: {
203- QuorumCommitmentPayload , QuorumFinalizationCommitment ,
204- } ;
218+ use crate :: transaction:: special_transaction:: quorum_commitment:: { read_compact_size, write_compact_size, QuorumCommitmentPayload , QuorumFinalizationCommitment } ;
205219
206220 #[ test]
207221 fn size ( ) {
@@ -226,4 +240,48 @@ mod tests {
226240 assert_eq ! ( payload. size( ) , want) ;
227241 assert_eq ! ( actual, want) ;
228242 }
243+
244+ #[ test]
245+ fn test_compact_size_round_trip ( ) {
246+ let test_values = vec ! [
247+ 0u32 ,
248+ 1 ,
249+ 252 ,
250+ 253 ,
251+ 254 ,
252+ 255 ,
253+ 300 ,
254+ 5000 ,
255+ 65535 ,
256+ 65536 ,
257+ 70000 ,
258+ 1_000_000 ,
259+ u32 :: MAX ,
260+ ] ;
261+
262+ for & value in & test_values {
263+ let mut buffer = Vec :: new ( ) ;
264+ // Write the value to the buffer
265+ let bytes_written = write_compact_size ( & mut buffer, value) . expect ( "Failed to write" ) ;
266+ // Read the value back from the buffer
267+ let mut cursor = Cursor :: new ( & buffer) ;
268+ let read_value = read_compact_size ( & mut cursor) . expect ( "Failed to read" ) ;
269+
270+ // Assert that the original value matches the deserialized value
271+ assert_eq ! (
272+ value, read_value,
273+ "Deserialized value does not match original for value {}" ,
274+ value
275+ ) ;
276+
277+ // Ensure that we've consumed all bytes (no extra bytes left)
278+ let position = cursor. position ( ) ;
279+ assert_eq ! (
280+ position as usize ,
281+ buffer. len( ) ,
282+ "Not all bytes were consumed for value {}" ,
283+ value
284+ ) ;
285+ }
286+ }
229287}
0 commit comments