@@ -23,6 +23,7 @@ use crate::consensus::{Decodable, Encodable, encode};
2323use crate :: hash_types:: { QuorumHash , QuorumVVecHash } ;
2424use crate :: prelude:: * ;
2525use crate :: { VarInt , io} ;
26+ use crate :: consensus:: encode:: { compact_size_len, fixed_bitset_len, read_compact_size, read_fixed_bitset, write_compact_size, write_fixed_bitset} ;
2627
2728/// A Quorum Finalization Commitment. It is described in the finalization section of DIP6:
2829/// [dip-0006.md#6-finalization-phase](https://github.com/dashpay/dips/blob/master/dip-0006.md#6-finalization-phase)
@@ -35,8 +36,8 @@ pub struct QuorumFinalizationCommitment {
3536 pub llmq_type : u8 ,
3637 pub quorum_hash : QuorumHash ,
3738 pub quorum_index : Option < i16 > ,
38- pub signers : Vec < u8 > ,
39- pub valid_members : Vec < u8 > ,
39+ pub signers : Vec < bool > ,
40+ pub valid_members : Vec < bool > ,
4041 pub quorum_public_key : BLSPublicKey ,
4142 pub quorum_vvec_hash : QuorumVVecHash ,
4243 pub quorum_sig : BLSSignature ,
@@ -47,8 +48,10 @@ impl QuorumFinalizationCommitment {
4748 /// The size of the payload in bytes.
4849 pub fn size ( & self ) -> usize {
4950 let mut size = 2 + 1 + 32 + 48 + 32 + 96 + 96 ;
50- size += VarInt ( self . signers . len ( ) as u64 ) . len ( ) + self . signers . len ( ) ;
51- size += VarInt ( self . valid_members . len ( ) as u64 ) . len ( ) + self . valid_members . len ( ) ;
51+ size += compact_size_len ( self . signers . len ( ) as u32 ) ;
52+ size += fixed_bitset_len ( self . signers . as_slice ( ) , self . signers . len ( ) ) ;
53+ size += compact_size_len ( self . valid_members . len ( ) as u32 ) ;
54+ size += fixed_bitset_len ( self . valid_members . as_slice ( ) , self . signers . len ( ) ) ;
5255 if self . version == 2 || self . version == 4 {
5356 size += 2 ;
5457 }
@@ -67,8 +70,10 @@ impl Encodable for QuorumFinalizationCommitment {
6770 len += q_index. consensus_encode ( w) ?;
6871 }
6972 }
70- len += self . signers . consensus_encode ( w) ?;
71- len += self . valid_members . consensus_encode ( w) ?;
73+ len += write_compact_size ( w, self . signers . len ( ) as u32 ) ?;
74+ len += write_fixed_bitset ( w, self . signers . as_slice ( ) , self . signers . iter ( ) . len ( ) ) ?;
75+ len += write_compact_size ( w, self . valid_members . len ( ) as u32 ) ?;
76+ len += write_fixed_bitset ( w, self . valid_members . as_slice ( ) , self . valid_members . iter ( ) . len ( ) ) ?;
7277 len += self . quorum_public_key . consensus_encode ( w) ?;
7378 len += self . quorum_vvec_hash . consensus_encode ( w) ?;
7479 len += self . quorum_sig . consensus_encode ( w) ?;
@@ -96,8 +101,8 @@ impl Decodable for QuorumFinalizationCommitment {
96101 llmq_type,
97102 quorum_hash,
98103 quorum_index,
99- signers : signers . iter ( ) . map ( | & b| b as u8 ) . collect ( ) ,
100- valid_members : valid_members . iter ( ) . map ( | & b| b as u8 ) . collect ( ) ,
104+ signers,
105+ valid_members,
101106 quorum_public_key,
102107 quorum_vvec_hash,
103108 quorum_sig,
@@ -144,144 +149,60 @@ impl Decodable for QuorumCommitmentPayload {
144149 }
145150}
146151
147- fn read_compact_size < R : Read + ?Sized > ( r : & mut R ) -> io:: Result < u32 > {
148- let mut marker = [ 0u8 ; 1 ] ;
149- r. read_exact ( & mut marker) ?;
150- match marker[ 0 ] {
151- 0xFD => {
152- let mut buf = [ 0u8 ; 2 ] ;
153- r. read_exact ( & mut buf) ?;
154- Ok ( u16:: from_le_bytes ( buf) as u32 )
155- }
156- 0xFE => {
157- let mut buf = [ 0u8 ; 4 ] ;
158- r. read_exact ( & mut buf) ?;
159- Ok ( u32:: from_le_bytes ( buf) )
160- }
161- 0xFF => {
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- ) )
167- }
168- value => Ok ( value as u32 ) ,
169- }
170- }
171-
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-
191- fn read_fixed_bitset < R : Read + ?Sized > ( r : & mut R , size : usize ) -> std:: io:: Result < Vec < bool > > {
192- // Calculate the number of bytes needed
193- let num_bytes = ( size + 7 ) / 8 ;
194- let mut bytes = vec ! [ 0u8 ; num_bytes] ;
195-
196- // Read bytes from the reader
197- r. read_exact ( & mut bytes) ?;
198-
199- // Unpack bits into a vector of bools
200- let mut bits = Vec :: with_capacity ( size) ;
201- for p in 0 ..size {
202- let byte = bytes[ p / 8 ] ;
203- let bit = ( byte >> ( p % 8 ) ) & 1 ;
204- bits. push ( bit != 0 ) ;
205- }
206-
207- Ok ( bits)
208- }
209-
210152#[ cfg( test) ]
211153mod tests {
212- use std:: io:: Cursor ;
213154 use hashes:: Hash ;
214155
215156 use crate :: bls_sig_utils:: { BLSPublicKey , BLSSignature } ;
216157 use crate :: consensus:: Encodable ;
217158 use crate :: hash_types:: { QuorumHash , QuorumVVecHash } ;
218- use crate :: transaction:: special_transaction:: quorum_commitment:: { read_compact_size , write_compact_size , QuorumCommitmentPayload , QuorumFinalizationCommitment } ;
159+ use crate :: transaction:: special_transaction:: quorum_commitment:: { QuorumCommitmentPayload , QuorumFinalizationCommitment } ;
219160
220161 #[ test]
221162 fn size ( ) {
222- let want = 325 ;
223- let payload = QuorumCommitmentPayload {
224- version : 0 ,
225- height : 0 ,
226- finalization_commitment : QuorumFinalizationCommitment {
163+ {
164+ let want = 317 ;
165+ let payload = QuorumCommitmentPayload {
227166 version : 0 ,
228- llmq_type : 0 ,
229- quorum_hash : QuorumHash :: all_zeros ( ) ,
230- quorum_index : None ,
231- signers : vec ! [ 1 , 2 , 3 , 4 , 5 ] ,
232- valid_members : vec ! [ 6 , 7 , 8 , 9 , 0 ] ,
233- quorum_public_key : BLSPublicKey :: from ( [ 0 ; 48 ] ) ,
234- quorum_vvec_hash : QuorumVVecHash :: all_zeros ( ) ,
235- quorum_sig : BLSSignature :: from ( [ 0 ; 96 ] ) ,
236- sig : BLSSignature :: from ( [ 0 ; 96 ] ) ,
237- } ,
238- } ;
239- let actual = payload. consensus_encode ( & mut Vec :: new ( ) ) . unwrap ( ) ;
240- assert_eq ! ( payload. size( ) , want) ;
241- assert_eq ! ( actual, want) ;
242- }
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- ) ;
167+ height : 0 ,
168+ finalization_commitment : QuorumFinalizationCommitment {
169+ version : 1 ,
170+ llmq_type : 0 ,
171+ quorum_hash : QuorumHash :: all_zeros ( ) ,
172+ quorum_index : None ,
173+ signers : vec ! [ true , false , true , true , false ] ,
174+ valid_members : vec ! [ false , true , false , true ] ,
175+ quorum_public_key : BLSPublicKey :: from ( [ 0 ; 48 ] ) ,
176+ quorum_vvec_hash : QuorumVVecHash :: all_zeros ( ) ,
177+ quorum_sig : BLSSignature :: from ( [ 0 ; 96 ] ) ,
178+ sig : BLSSignature :: from ( [ 0 ; 96 ] ) ,
179+ } ,
180+ } ;
181+ let actual = payload. consensus_encode ( & mut Vec :: new ( ) ) . unwrap ( ) ;
182+ assert_eq ! ( payload. size( ) , want) ;
183+ assert_eq ! ( actual, want) ;
184+ }
185+ {
186+ let want = 319 ;
187+ let payload = QuorumCommitmentPayload {
188+ version : 0 ,
189+ height : 0 ,
190+ finalization_commitment : QuorumFinalizationCommitment {
191+ version : 2 ,
192+ llmq_type : 0 ,
193+ quorum_hash : QuorumHash :: all_zeros ( ) ,
194+ quorum_index : Some ( 1 ) ,
195+ signers : vec ! [ true , false , true , true , false , true , false ] ,
196+ valid_members : vec ! [ false , true , false , true , false , true ] ,
197+ quorum_public_key : BLSPublicKey :: from ( [ 0 ; 48 ] ) ,
198+ quorum_vvec_hash : QuorumVVecHash :: all_zeros ( ) ,
199+ quorum_sig : BLSSignature :: from ( [ 0 ; 96 ] ) ,
200+ sig : BLSSignature :: from ( [ 0 ; 96 ] ) ,
201+ } ,
202+ } ;
203+ let actual = payload. consensus_encode ( & mut Vec :: new ( ) ) . unwrap ( ) ;
204+ assert_eq ! ( payload. size( ) , want) ;
205+ assert_eq ! ( actual, want) ;
285206 }
286207 }
287208}
0 commit comments