1717//! It is defined in DIP6 [dip-0006.md](https://github.com/dashpay/dips/blob/master/dip-0006.md).
1818//!
1919
20+ use std:: io:: { Read , Write } ;
2021use crate :: bls_sig_utils:: { BLSPublicKey , BLSSignature } ;
2122use crate :: consensus:: { Decodable , Encodable , encode} ;
2223use crate :: hash_types:: { QuorumHash , QuorumVVecHash } ;
@@ -33,6 +34,7 @@ pub struct QuorumFinalizationCommitment {
3334 pub version : u16 ,
3435 pub llmq_type : u8 ,
3536 pub quorum_hash : QuorumHash ,
37+ pub quorum_index : Option < i16 > ,
3638 pub signers : Vec < u8 > ,
3739 pub valid_members : Vec < u8 > ,
3840 pub quorum_public_key : BLSPublicKey ,
@@ -47,6 +49,9 @@ impl QuorumFinalizationCommitment {
4749 let mut size = 2 + 1 + 32 + 48 + 32 + 96 + 96 ;
4850 size += VarInt ( self . signers . len ( ) as u64 ) . len ( ) + self . signers . len ( ) ;
4951 size += VarInt ( self . valid_members . len ( ) as u64 ) . len ( ) + self . valid_members . len ( ) ;
52+ if self . version == 2 || self . version == 4 {
53+ size += 2 ;
54+ }
5055 size
5156 }
5257}
@@ -57,6 +62,11 @@ impl Encodable for QuorumFinalizationCommitment {
5762 len += self . version . consensus_encode ( w) ?;
5863 len += self . llmq_type . consensus_encode ( w) ?;
5964 len += self . quorum_hash . consensus_encode ( w) ?;
65+ if let Some ( q_index) = self . quorum_index {
66+ if self . version == 2 || self . version == 4 {
67+ len += q_index. consensus_encode ( w) ?;
68+ }
69+ }
6070 len += self . signers . consensus_encode ( w) ?;
6171 len += self . valid_members . consensus_encode ( w) ?;
6272 len += self . quorum_public_key . consensus_encode ( w) ?;
@@ -72,8 +82,11 @@ impl Decodable for QuorumFinalizationCommitment {
7282 let version = u16:: consensus_decode ( r) ?;
7383 let llmq_type = u8:: consensus_decode ( r) ?;
7484 let quorum_hash = QuorumHash :: consensus_decode ( r) ?;
75- let signers = Vec :: < u8 > :: consensus_decode ( r) ?;
76- let valid_members = Vec :: < u8 > :: consensus_decode ( r) ?;
85+ let quorum_index = if version == 2 || version == 4 { Some ( i16:: consensus_decode ( r) ?) } else { None } ;
86+ let signers_count = read_compact_size ( r) ?;
87+ let signers = read_fixed_bitset ( r, signers_count as usize ) ?;
88+ let valid_members_count = read_compact_size ( r) ?;
89+ let valid_members = read_fixed_bitset ( r, valid_members_count as usize ) ?;
7790 let quorum_public_key = BLSPublicKey :: consensus_decode ( r) ?;
7891 let quorum_vvec_hash = QuorumVVecHash :: consensus_decode ( r) ?;
7992 let quorum_sig = BLSSignature :: consensus_decode ( r) ?;
@@ -82,8 +95,9 @@ impl Decodable for QuorumFinalizationCommitment {
8295 version,
8396 llmq_type,
8497 quorum_hash,
85- signers,
86- valid_members,
98+ quorum_index,
99+ signers : signers. iter ( ) . map ( |& b| b as u8 ) . collect ( ) ,
100+ valid_members : valid_members. iter ( ) . map ( |& b| b as u8 ) . collect ( ) ,
87101 quorum_public_key,
88102 quorum_vvec_hash,
89103 quorum_sig,
@@ -130,6 +144,54 @@ impl Decodable for QuorumCommitmentPayload {
130144 }
131145}
132146
147+ fn read_compact_size < R : Read + ?Sized > ( r : & mut R ) -> io:: Result < u64 > {
148+ let mut marker = [ 0u8 ; 1 ] ;
149+ r. read_exact ( & mut marker) ?;
150+ match marker[ 0 ] {
151+ 0xFD => {
152+ // Read the next 2 bytes as a little-endian u16
153+ let mut buf = [ 0u8 ; 2 ] ;
154+ r. read_exact ( & mut buf) ?;
155+ Ok ( u16:: from_le_bytes ( buf) as u64 )
156+ }
157+ 0xFE => {
158+ // Read the next 4 bytes as a little-endian u32
159+ let mut buf = [ 0u8 ; 4 ] ;
160+ r. read_exact ( & mut buf) ?;
161+ Ok ( u32:: from_le_bytes ( buf) as u64 )
162+ }
163+ 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 )
172+ }
173+ }
174+ }
175+
176+ fn read_fixed_bitset < R : Read + ?Sized > ( r : & mut R , size : usize ) -> std:: io:: Result < Vec < bool > > {
177+ // Calculate the number of bytes needed
178+ let num_bytes = ( size + 7 ) / 8 ;
179+ let mut bytes = vec ! [ 0u8 ; num_bytes] ;
180+
181+ // Read bytes from the reader
182+ r. read_exact ( & mut bytes) ?;
183+
184+ // Unpack bits into a vector of bools
185+ let mut bits = Vec :: with_capacity ( size) ;
186+ for p in 0 ..size {
187+ let byte = bytes[ p / 8 ] ;
188+ let bit = ( byte >> ( p % 8 ) ) & 1 ;
189+ bits. push ( bit != 0 ) ;
190+ }
191+
192+ Ok ( bits)
193+ }
194+
133195#[ cfg( test) ]
134196mod tests {
135197 use hashes:: Hash ;
@@ -151,6 +213,7 @@ mod tests {
151213 version : 0 ,
152214 llmq_type : 0 ,
153215 quorum_hash : QuorumHash :: all_zeros ( ) ,
216+ quorum_index : None ,
154217 signers : vec ! [ 1 , 2 , 3 , 4 , 5 ] ,
155218 valid_members : vec ! [ 6 , 7 , 8 , 9 , 0 ] ,
156219 quorum_public_key : BLSPublicKey :: from ( [ 0 ; 48 ] ) ,
0 commit comments