17
17
//! It is defined in DIP6 [dip-0006.md](https://github.com/dashpay/dips/blob/master/dip-0006.md).
18
18
//!
19
19
20
+ use std:: io:: { Read , Write } ;
20
21
use crate :: bls_sig_utils:: { BLSPublicKey , BLSSignature } ;
21
22
use crate :: consensus:: { Decodable , Encodable , encode} ;
22
23
use crate :: hash_types:: { QuorumHash , QuorumVVecHash } ;
@@ -33,6 +34,7 @@ pub struct QuorumFinalizationCommitment {
33
34
pub version : u16 ,
34
35
pub llmq_type : u8 ,
35
36
pub quorum_hash : QuorumHash ,
37
+ pub quorum_index : Option < i16 > ,
36
38
pub signers : Vec < u8 > ,
37
39
pub valid_members : Vec < u8 > ,
38
40
pub quorum_public_key : BLSPublicKey ,
@@ -47,6 +49,9 @@ impl QuorumFinalizationCommitment {
47
49
let mut size = 2 + 1 + 32 + 48 + 32 + 96 + 96 ;
48
50
size += VarInt ( self . signers . len ( ) as u64 ) . len ( ) + self . signers . len ( ) ;
49
51
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
+ }
50
55
size
51
56
}
52
57
}
@@ -57,6 +62,11 @@ impl Encodable for QuorumFinalizationCommitment {
57
62
len += self . version . consensus_encode ( w) ?;
58
63
len += self . llmq_type . consensus_encode ( w) ?;
59
64
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
+ }
60
70
len += self . signers . consensus_encode ( w) ?;
61
71
len += self . valid_members . consensus_encode ( w) ?;
62
72
len += self . quorum_public_key . consensus_encode ( w) ?;
@@ -72,8 +82,11 @@ impl Decodable for QuorumFinalizationCommitment {
72
82
let version = u16:: consensus_decode ( r) ?;
73
83
let llmq_type = u8:: consensus_decode ( r) ?;
74
84
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 ) ?;
77
90
let quorum_public_key = BLSPublicKey :: consensus_decode ( r) ?;
78
91
let quorum_vvec_hash = QuorumVVecHash :: consensus_decode ( r) ?;
79
92
let quorum_sig = BLSSignature :: consensus_decode ( r) ?;
@@ -82,8 +95,9 @@ impl Decodable for QuorumFinalizationCommitment {
82
95
version,
83
96
llmq_type,
84
97
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 ( ) ,
87
101
quorum_public_key,
88
102
quorum_vvec_hash,
89
103
quorum_sig,
@@ -130,6 +144,54 @@ impl Decodable for QuorumCommitmentPayload {
130
144
}
131
145
}
132
146
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
+
133
195
#[ cfg( test) ]
134
196
mod tests {
135
197
use hashes:: Hash ;
@@ -151,6 +213,7 @@ mod tests {
151
213
version : 0 ,
152
214
llmq_type : 0 ,
153
215
quorum_hash : QuorumHash :: all_zeros ( ) ,
216
+ quorum_index : None ,
154
217
signers : vec ! [ 1 , 2 , 3 , 4 , 5 ] ,
155
218
valid_members : vec ! [ 6 , 7 , 8 , 9 , 0 ] ,
156
219
quorum_public_key : BLSPublicKey :: from ( [ 0 ; 48 ] ) ,
0 commit comments