Skip to content

Commit e148098

Browse files
authored
fix: further block deserialization fixes (#46)
* fix: qcommitment seqwit always false * fix: qcommitment quorumIndex field * fix: qcommitment signers validmembers bitsets * correct size * do not unwrap
1 parent 078ae44 commit e148098

File tree

2 files changed

+70
-4
lines changed

2 files changed

+70
-4
lines changed

dash/src/blockdata/transaction/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,9 @@ impl Decodable for Transaction {
653653
if special_transaction_type == TransactionType::AssetUnlock {
654654
segwit = false;
655655
}
656+
if special_transaction_type == TransactionType::QuorumCommitment {
657+
segwit = false;
658+
}
656659
if segwit {
657660
let segwit_flag = u8::consensus_decode_from_finite_reader(r)?;
658661
match segwit_flag {

dash/src/blockdata/transaction/special_transaction/quorum_commitment.rs

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
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};
2021
use crate::bls_sig_utils::{BLSPublicKey, BLSSignature};
2122
use crate::consensus::{Decodable, Encodable, encode};
2223
use 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)]
134196
mod 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

Comments
 (0)