-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: further block deserialization fixes #46
Changes from 3 commits
c3624de
ef77bee
d4e5bea
ca7ad39
0db8960
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -17,6 +17,7 @@ | |||||||||||||
//! It is defined in DIP6 [dip-0006.md](https://github.com/dashpay/dips/blob/master/dip-0006.md). | ||||||||||||||
//! | ||||||||||||||
|
||||||||||||||
use std::io::{Read, Write}; | ||||||||||||||
use crate::bls_sig_utils::{BLSPublicKey, BLSSignature}; | ||||||||||||||
use crate::consensus::{Decodable, Encodable, encode}; | ||||||||||||||
use crate::hash_types::{QuorumHash, QuorumVVecHash}; | ||||||||||||||
|
@@ -33,6 +34,7 @@ pub struct QuorumFinalizationCommitment { | |||||||||||||
pub version: u16, | ||||||||||||||
pub llmq_type: u8, | ||||||||||||||
pub quorum_hash: QuorumHash, | ||||||||||||||
pub quorum_index: Option<i16>, | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle potential In the Consider modifying the if self.version == 2 || self.version == 4 {
- len += self.quorum_index.unwrap().consensus_encode(w)?;
+ if let Some(index) = self.quorum_index {
+ len += index.consensus_encode(w)?;
+ } else {
+ return Err(io::Error::new(io::ErrorKind::InvalidData, "quorum_index is None for version 2 or 4"));
+ }
}
|
||||||||||||||
pub signers: Vec<u8>, | ||||||||||||||
pub valid_members: Vec<u8>, | ||||||||||||||
pub quorum_public_key: BLSPublicKey, | ||||||||||||||
|
@@ -47,6 +49,9 @@ impl QuorumFinalizationCommitment { | |||||||||||||
let mut size = 2 + 1 + 32 + 48 + 32 + 96 + 96; | ||||||||||||||
size += VarInt(self.signers.len() as u64).len() + self.signers.len(); | ||||||||||||||
size += VarInt(self.valid_members.len() as u64).len() + self.valid_members.len(); | ||||||||||||||
if self.version == 2 || self.version == 4 { | ||||||||||||||
size += 16; | ||||||||||||||
} | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct the size calculation for In the Modify the size addition to reflect the actual size of if self.version == 2 || self.version == 4 {
- size += 16;
+ size += 2; // i16 is 2 bytes
} 📝 Committable suggestion
Suggested change
|
||||||||||||||
size | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
@@ -57,6 +62,9 @@ impl Encodable for QuorumFinalizationCommitment { | |||||||||||||
len += self.version.consensus_encode(w)?; | ||||||||||||||
len += self.llmq_type.consensus_encode(w)?; | ||||||||||||||
len += self.quorum_hash.consensus_encode(w)?; | ||||||||||||||
if self.version == 2 || self.version == 4 { | ||||||||||||||
len += self.quorum_index.unwrap().consensus_encode(w)?; | ||||||||||||||
} | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prevent potential panic when unwrapping Similar to the earlier comment, unwrapping Apply the same modification as suggested for lines 37-37 to handle |
||||||||||||||
len += self.signers.consensus_encode(w)?; | ||||||||||||||
len += self.valid_members.consensus_encode(w)?; | ||||||||||||||
len += self.quorum_public_key.consensus_encode(w)?; | ||||||||||||||
|
@@ -72,8 +80,11 @@ impl Decodable for QuorumFinalizationCommitment { | |||||||||||||
let version = u16::consensus_decode(r)?; | ||||||||||||||
let llmq_type = u8::consensus_decode(r)?; | ||||||||||||||
let quorum_hash = QuorumHash::consensus_decode(r)?; | ||||||||||||||
let signers = Vec::<u8>::consensus_decode(r)?; | ||||||||||||||
let valid_members = Vec::<u8>::consensus_decode(r)?; | ||||||||||||||
let quorum_index = if version == 2 || version == 4 { Some(i16::consensus_decode(r)?) } else { None }; | ||||||||||||||
let signers_count = read_compact_size(r)?; | ||||||||||||||
let signers = read_fixed_bitset(r, signers_count as usize)?; | ||||||||||||||
let valid_members_count = read_compact_size(r)?; | ||||||||||||||
let valid_members = read_fixed_bitset(r, valid_members_count as usize)?; | ||||||||||||||
let quorum_public_key = BLSPublicKey::consensus_decode(r)?; | ||||||||||||||
let quorum_vvec_hash = QuorumVVecHash::consensus_decode(r)?; | ||||||||||||||
let quorum_sig = BLSSignature::consensus_decode(r)?; | ||||||||||||||
|
@@ -82,8 +93,9 @@ impl Decodable for QuorumFinalizationCommitment { | |||||||||||||
version, | ||||||||||||||
llmq_type, | ||||||||||||||
quorum_hash, | ||||||||||||||
signers, | ||||||||||||||
valid_members, | ||||||||||||||
quorum_index, | ||||||||||||||
signers: signers.iter().map(|&b| b as u8).collect(), | ||||||||||||||
valid_members: valid_members.iter().map(|&b| b as u8).collect(), | ||||||||||||||
Comment on lines
+98
to
+100
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Simplify conversion from In the If |
||||||||||||||
quorum_public_key, | ||||||||||||||
quorum_vvec_hash, | ||||||||||||||
quorum_sig, | ||||||||||||||
|
@@ -130,6 +142,54 @@ impl Decodable for QuorumCommitmentPayload { | |||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
fn read_compact_size<R: Read + ?Sized>(r: &mut R) -> io::Result<u64> { | ||||||||||||||
let mut marker = [0u8; 1]; | ||||||||||||||
r.read_exact(&mut marker)?; | ||||||||||||||
match marker[0] { | ||||||||||||||
0xFD => { | ||||||||||||||
// Read the next 2 bytes as a little-endian u16 | ||||||||||||||
let mut buf = [0u8; 2]; | ||||||||||||||
r.read_exact(&mut buf)?; | ||||||||||||||
Ok(u16::from_le_bytes(buf) as u64) | ||||||||||||||
} | ||||||||||||||
0xFE => { | ||||||||||||||
// Read the next 4 bytes as a little-endian u32 | ||||||||||||||
let mut buf = [0u8; 4]; | ||||||||||||||
r.read_exact(&mut buf)?; | ||||||||||||||
Ok(u32::from_le_bytes(buf) as u64) | ||||||||||||||
} | ||||||||||||||
0xFF => { | ||||||||||||||
// Read the next 8 bytes as a little-endian u64 | ||||||||||||||
let mut buf = [0u8; 8]; | ||||||||||||||
r.read_exact(&mut buf)?; | ||||||||||||||
Ok(u64::from_le_bytes(buf)) | ||||||||||||||
} | ||||||||||||||
value => { | ||||||||||||||
// For values less than 253, the value is stored directly in the marker byte | ||||||||||||||
Ok(value as u64) | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
Comment on lines
+147
to
+174
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider reusing existing The Replace -let signers_count = read_compact_size(r)?;
+let signers_count = VarInt::consensus_decode(r)?.0; Make similar changes for If
|
||||||||||||||
|
||||||||||||||
fn read_fixed_bitset<R: Read + ?Sized>(r: &mut R, size: usize) -> std::io::Result<Vec<bool>> { | ||||||||||||||
// Calculate the number of bytes needed | ||||||||||||||
let num_bytes = (size + 7) / 8; | ||||||||||||||
let mut bytes = vec![0u8; num_bytes]; | ||||||||||||||
|
||||||||||||||
// Read bytes from the reader | ||||||||||||||
r.read_exact(&mut bytes)?; | ||||||||||||||
|
||||||||||||||
// Unpack bits into a vector of bools | ||||||||||||||
let mut bits = Vec::with_capacity(size); | ||||||||||||||
for p in 0..size { | ||||||||||||||
let byte = bytes[p / 8]; | ||||||||||||||
let bit = (byte >> (p % 8)) & 1; | ||||||||||||||
bits.push(bit != 0); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
Ok(bits) | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
#[cfg(test)] | ||||||||||||||
mod tests { | ||||||||||||||
use hashes::Hash; | ||||||||||||||
|
@@ -151,6 +211,7 @@ mod tests { | |||||||||||||
version: 0, | ||||||||||||||
llmq_type: 0, | ||||||||||||||
quorum_hash: QuorumHash::all_zeros(), | ||||||||||||||
quorum_index: None, | ||||||||||||||
signers: vec![1, 2, 3, 4, 5], | ||||||||||||||
valid_members: vec![6, 7, 8, 9, 0], | ||||||||||||||
quorum_public_key: BLSPublicKey::from([0; 48]), | ||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Based on the search results, I can now generate the final response. The code shows that the
consensus_encode
implementation inTransaction
properly handles witness serialization and has special cases for transaction types. Thehave_witness
flag is determined by input witnesses and is explicitly set to false for certain transaction types, includingAssetUnlock
. However, I don't see theQuorumCommitment
case being handled in the serialization code, which is inconsistent with the deserialization behavior.Serialization handling for QuorumCommitment transactions needs to be updated
The deserialization code sets
segwit = false
for QuorumCommitment transactions, but the corresponding serialization code inconsensus_encode
doesn't handle this case. This could lead to serialization/deserialization inconsistency. Add the following case inconsensus_encode
:🔗 Analysis chain
Verify serialization consistency for QuorumCommitment transactions.
While the deserialization change looks correct, we should ensure that the serialization logic in
consensus_encode
handles QuorumCommitment transactions consistently. Please verify that:have_witness
flag inconsensus_encode
matches this deserialization behaviorLet's verify the serialization handling:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
Length of output: 153
Script:
Length of output: 68
Script:
Length of output: 52
Script:
Length of output: 22043
Script:
Length of output: 95
Script:
Length of output: 60
Script:
Length of output: 69
Script:
Length of output: 60
Script:
Length of output: 1822