Skip to content
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

Merged
merged 5 commits into from
Oct 31, 2024

Conversation

ogabrielides
Copy link
Collaborator

@ogabrielides ogabrielides commented Oct 31, 2024

Further fixes for deserializing blocks correctly:

  • qcommitment seqwit is always false
  • qcommitment support of quorumIndex field (dip-24)
  • qcommitment correct deserialization of signers, validMembers fields as dynamic bitsets

Summary by CodeRabbit

  • New Features

    • Enhanced transaction handling for TransactionType::QuorumCommitment, ensuring proper deserialization as non-segwit.
    • Introduced a new field quorum_index in the QuorumFinalizationCommitment structure for improved functionality.
    • Added utility functions for better handling of variable-length data in transactions.
  • Documentation

    • Updated documentation comments for clarity on segwit and non-segwit transaction handling.

Copy link

coderabbitai bot commented Oct 31, 2024

Walkthrough

The changes involve modifications to the Transaction struct and its methods in the dash/src/blockdata/transaction/mod.rs file, specifically adding a condition for handling TransactionType::QuorumCommitment. This ensures it is treated as non-segwit during deserialization. Additionally, the QuorumFinalizationCommitment structure in quorum_commitment.rs is updated with a new field, quorum_index, and the encoding/decoding methods are refined for better handling of transaction data. New utility functions for reading variable-length data are also introduced to enhance code maintainability.

Changes

File Path Change Summary
dash/src/blockdata/transaction/mod.rs - Updated consensus_decode_from_finite_reader to handle TransactionType::QuorumCommitment as non-segwit.
- Improved documentation for clarity on segwit handling.
dash/src/blockdata/transaction/special_transaction/quorum_commitment.rs - Added field pub quorum_index: Option<i16> to QuorumFinalizationCommitment.
- Updated size, consensus_encode, and consensus_decode methods for handling quorum_index.
- Introduced utility functions read_compact_size and read_fixed_bitset for improved data reading.

Poem

🐇 In the land of code where rabbits play,
New fields and functions hop into the fray.
QuorumCommitment, now clear and bright,
With better reads, our future's in sight!
A joyful dance in the data we weave,
Celebrating changes, we cheer and believe! 🎉


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Outside diff range and nitpick comments (1)
dash/src/blockdata/transaction/mod.rs (1)

656-658: Consider adding test coverage for QuorumCommitment transactions.

While the codebase has good test coverage, it would be beneficial to add specific test cases for:

  1. Serialization/deserialization of QuorumCommitment transactions
  2. Verification that the segwit flag is correctly handled
  3. Edge cases around QuorumCommitment transaction processing

Would you like me to help generate test cases for QuorumCommitment transactions?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 078ae44 and d4e5bea.

📒 Files selected for processing (2)
  • dash/src/blockdata/transaction/mod.rs (1 hunks)
  • dash/src/blockdata/transaction/special_transaction/quorum_commitment.rs (8 hunks)
🔇 Additional comments (4)
dash/src/blockdata/transaction/mod.rs (1)

656-658: LGTM! The change correctly handles QuorumCommitment transactions.

The addition of this condition ensures QuorumCommitment transactions are treated as non-segwit transactions during deserialization, similar to how AssetUnlock transactions are handled. This aligns with the PR objective to fix block deserialization issues.

Let's verify there are no other QuorumCommitment transaction references that need similar treatment:

✅ Verification successful

Setting segwit=false for QuorumCommitment transactions is correct

The verification confirms that:

  1. QuorumCommitment transactions are a special transaction type (type=6) defined in DIP6 for storing quorum information in the blockchain
  2. The change aligns with how other special transactions like AssetUnlock are handled
  3. The implementation is consistent with the transaction's serialization/deserialization logic across the codebase
  4. No other locations require similar segwit handling modifications
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other QuorumCommitment transaction handling
rg -A 5 "QuorumCommitment" 

Length of output: 153


Script:

#!/bin/bash
# Let's try a more comprehensive search for QuorumCommitment
rg -i "quorumcommitment|quorum.*commitment" --type rust -A 5

# Also search for TransactionType enum definition to understand all variants
ast-grep --pattern 'enum TransactionType {
  $$$
}'

# Search for segwit-related handling in transactions
rg "segwit.*=.*false" --type rust -A 5

Length of output: 21429

dash/src/blockdata/transaction/special_transaction/quorum_commitment.rs (3)

83-84: Ensure consistent handling of quorum_index during decoding

In the consensus_decode method, you're setting quorum_index to Some when version is 2 or 4. This should align with how quorum_index is handled during encoding. Ensure that any optional fields are consistently managed to prevent mismatches between encoding and decoding.


174-192: Ensure correct bit unpacking in read_fixed_bitset

The read_fixed_bitset function unpacks bits from bytes into a vector of booleans. Verify that the bit order and indexing logic align with the protocol's expectations to prevent misinterpretation of the data.

Consider adding tests to confirm the correctness of read_fixed_bitset.


Line range hint 85-98: Verify correctness of read_compact_size and read_fixed_bitset usage

The decoding of signers and valid_members now uses read_compact_size and read_fixed_bitset. Ensure that these functions correctly handle the data according to the protocol specifications, and that any edge cases are properly managed.

Run the following script to inspect the usage of read_compact_size and read_fixed_bitset in the codebase:

✅ Verification successful

Let me analyze the findings from the shell script results to verify the correctness of read_compact_size and read_fixed_bitset usage.

This will help us verify the implementation details and any associated tests to ensure they handle the data correctly according to protocol specifications.


Based on the implementation details revealed, I can now provide a final response about the correctness of these functions.

read_compact_size and read_fixed_bitset implementations are correct and follow protocol specifications

The implementations show proper handling of:

  • Compact size encoding with correct marker bytes (0xFD, 0xFE, 0xFF) and corresponding byte lengths
  • Proper endianness (little-endian) for multi-byte integers
  • Efficient bitset handling with correct bit packing/unpacking
  • Safe memory allocation with proper size calculations

The code follows standard Bitcoin compact size encoding format and provides efficient bitset manipulation for the quorum commitment structure.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the implementation of `read_compact_size` and `read_fixed_bitset`

# Check if similar functions already exist in the codebase
rg 'fn.*read_compact_size' -t rust

# Check calls to `read_compact_size` and `read_fixed_bitset`
rg 'read_compact_size|read_fixed_bitset' -A 5 -B 2 -t rust

# Verify if `VarInt::consensus_decode` could be reused instead
rg 'VarInt::consensus_decode' -A 5 -B 2 -t rust

Length of output: 10922


Script:

#!/bin/bash
# Let's examine the implementation of read_compact_size and read_fixed_bitset

# Check the implementation details
rg -A 20 '^fn read_compact_size' dash/src/blockdata/transaction/special_transaction/quorum_commitment.rs

# Check the implementation details of read_fixed_bitset
rg -A 20 '^fn read_fixed_bitset' dash/src/blockdata/transaction/special_transaction/quorum_commitment.rs

# Look for any tests related to these functions
rg 'mod tests.*read_(compact_size|fixed_bitset)' -A 20 -t rust

Length of output: 1586

Comment on lines +656 to +658
if special_transaction_type == TransactionType::QuorumCommitment {
segwit = false;
}
Copy link

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 in Transaction properly handles witness serialization and has special cases for transaction types. The have_witness flag is determined by input witnesses and is explicitly set to false for certain transaction types, including AssetUnlock. However, I don't see the QuorumCommitment 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 in consensus_encode doesn't handle this case. This could lead to serialization/deserialization inconsistency. Add the following case in consensus_encode:

if self.tx_type() == TransactionType::QuorumCommitment {
    have_witness = false;
}
🔗 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:

  1. The have_witness flag in consensus_encode matches this deserialization behavior
  2. The transaction roundtrip (serialize -> deserialize) works correctly for QuorumCommitment transactions

Let's verify the serialization handling:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for witness handling in consensus_encode
ast-grep --pattern 'consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
  $$$
  let mut have_witness = $$$
  $$$
}'

Length of output: 153


Script:

#!/bin/bash
# Let's try a broader search for consensus_encode implementation
rg -U "consensus_encode.*?\{.*?have_witness" -g "*.rs" --multiline

Length of output: 68


Script:

#!/bin/bash
# Also search for Transaction serialization tests
rg -l "test.*serialization.*Transaction" -g "*.rs"

Length of output: 52


Script:

#!/bin/bash
# Look for QuorumCommitment handling in transaction code
rg "QuorumCommitment" -A 5 -B 5 -g "*.rs"

Length of output: 22043


Script:

#!/bin/bash
# Let's search for Transaction consensus_encode implementation
rg -U "impl.*?Transaction.*?consensus_encode.*?\{.*?have_witness" -g "*.rs" --multiline -A 20

Length of output: 95


Script:

#!/bin/bash
# Also search for Transaction serialization tests specifically for QuorumCommitment
rg "test.*serialization.*QuorumCommitment" -g "*.rs" -A 10

Length of output: 60


Script:

#!/bin/bash
# Try a more general search for Transaction consensus_encode
rg -U "impl.*?Transaction.*?consensus_encode" -g "*.rs" --multiline

Length of output: 69


Script:

#!/bin/bash
# Look for Transaction serialization tests with broader context
rg "test.*Transaction.*serialization" -g "*.rs" -B 5 -A 15

Length of output: 60


Script:

#!/bin/bash
# Search for witness handling in Transaction implementation
rg "have_witness" -g "*.rs" -B 5 -A 5

Length of output: 1822

Comment on lines 65 to 67
if self.version == 2 || self.version == 4 {
len += self.quorum_index.unwrap().consensus_encode(w)?;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Prevent potential panic when unwrapping quorum_index

Similar to the earlier comment, unwrapping quorum_index without checking if it's Some can cause a panic. Ensure that quorum_index is handled safely during encoding.

Apply the same modification as suggested for lines 37-37 to handle quorum_index safely.

Comment on lines +96 to +98
quorum_index,
signers: signers.iter().map(|&b| b as u8).collect(),
valid_members: valid_members.iter().map(|&b| b as u8).collect(),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Simplify conversion from Vec<bool> to Vec<u8>

In the consensus_decode method, you're converting a Vec<bool> to a Vec<u8> by mapping each boolean to a u8. This could be streamlined if the original data is intended to be a byte array.

If signers and valid_members represent bitfields, consider using a dedicated bitset structure or keeping them as Vec<u8> throughout to simplify the code.

Comment on lines 52 to 54
if self.version == 2 || self.version == 4 {
size += 16;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Correct the size calculation for quorum_index

In the size method, when version is 2 or 4, you're adding 16 to the size. However, i16 is 2 bytes, not 16 bytes. This could lead to incorrect size calculations.

Modify the size addition to reflect the actual size of i16:

if self.version == 2 || self.version == 4 {
-    size += 16;
+    size += 2; // i16 is 2 bytes
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if self.version == 2 || self.version == 4 {
size += 16;
}
if self.version == 2 || self.version == 4 {
size += 2; // i16 is 2 bytes
}

@@ -33,6 +34,7 @@
pub version: u16,
pub llmq_type: u8,
pub quorum_hash: QuorumHash,
pub quorum_index: Option<i16>,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Handle potential None value for quorum_index more safely

In the QuorumFinalizationCommitment struct, quorum_index is of type Option<i16>. In the encoding process, you're using .unwrap() when encoding quorum_index, which can cause a panic if quorum_index is None. It's safer to handle the None case explicitly or use .expect() with a clear error message.

Consider modifying the consensus_encode method to handle the None case:

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"));
+    }
}

Committable suggestion was skipped due to low confidence.

@QuantumExplorer QuantumExplorer merged commit e148098 into master Oct 31, 2024
1 of 25 checks passed
@QuantumExplorer QuantumExplorer deleted the fix/block-deser-further branch October 31, 2024 20:12
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between d4e5bea and ca7ad39.

📒 Files selected for processing (1)
  • dash/src/blockdata/transaction/special_transaction/quorum_commitment.rs (8 hunks)
🔇 Additional comments (7)
dash/src/blockdata/transaction/special_transaction/quorum_commitment.rs (7)

37-37: The past review comment for lines 37-37 is still valid. The quorum_index field is being unwrapped without checking if it's Some in the consensus_encode method, which can cause a panic. Please handle the None case safely as suggested in the previous comment.


65-67: The past review comment for lines 65-67 is still valid. Unwrapping quorum_index without checking if it's Some can cause a panic during encoding. Please handle the None case safely as suggested in the previous comment.


83-83: LGTM!

The decoding logic for quorum_index based on the version is implemented correctly using the if expression and Option type.


96-98: The past review comment for lines 96-98 is still valid. Consider simplifying the conversion from Vec<bool> to Vec<u8> by using a dedicated bitset structure or keeping the data as Vec<u8> throughout the encoding and decoding process. This will improve code readability and maintainability.


174-191: Ensure read_fixed_bitset handles edge cases and errors properly.

The read_fixed_bitset function looks good for reading a fixed number of bits into a Vec<bool>. However, please ensure that it handles edge cases and errors properly, such as:

  • When the input data is shorter than expected.
  • When the requested size is not a multiple of 8.
  • When there are any I/O errors during reading.

Add unit tests to cover these edge cases and ensure that the function behaves as expected. For example:

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn read_fixed_bitset_handles_short_input() {
        // Test case when input data is shorter than expected
        let data = [0b1010_1010];
        let mut reader = &data[..];
        let result = read_fixed_bitset(&mut reader, 10);
        assert!(result.is_err());
    }

    #[test]
    fn read_fixed_bitset_handles_non_multiple_of_8() {
        // Test case when requested size is not a multiple of 8
        let data = [0b1010_1010, 0b0101_0101];
        let mut reader = &data[..];
        let result = read_fixed_bitset(&mut reader, 12);
        assert_eq!(result.unwrap(), vec![true, false, true, false, true, false, true, false, false, true, false, true]);
    }

    // Add more test cases as needed
}

214-214: LGTM!

The quorum_index field is initialized with None for the test case, which is correct since the version is 0. The test case looks good.


84-87: Verify if read_compact_size and read_fixed_bitset are used consistently.

The usage of the new utility functions read_compact_size and read_fixed_bitset for decoding signers and valid_members looks good. However, please ensure that these functions are used consistently throughout the codebase wherever similar decoding logic is required.

Run the following script to verify the usage of these functions:

✅ Verification successful

The utility functions are used consistently in their scope

Based on the search results, read_compact_size and read_fixed_bitset are utility functions defined and used specifically within the quorum commitment module (quorum_commitment.rs). They are used consistently for their intended purpose of decoding signers and valid members data.

The search results show:

  • No other manual bitset decoding patterns were found in the codebase
  • The functions are used only where needed in the quorum commitment implementation
  • Other parts of the codebase use different serialization approaches appropriate for their specific needs (e.g., consensus_decode, Vec::with_capacity for different purposes)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify if `read_compact_size` and `read_fixed_bitset` are used consistently in the codebase.

# Test 1: Search for manual decoding of compact size. Expect: No occurrences of manual decoding logic.
rg -U $'let\s+(\w+)\s*=\s*\[\s*0u8\s*;\s*(\d+)\s*\]\s*;[\s\S]*?r\.read_exact\(\&mut\s+\1\)\s*\?;\s*(\w+)::from_le_bytes\(\1\)\s*as\s*u64'

# Test 2: Search for manual decoding of fixed bitsets. Expect: No occurrences of manual decoding logic.
rg -U $'let\s+mut\s+(\w+)\s*=\s*vec!\[0u8;\s*(\w+)\];[\s\S]*?r\.read_exact\(\&mut\s+\1\)\?;[\s\S]*?let\s+mut\s+(\w+)\s*=\s*Vec::with_capacity\(\2\);[\s\S]*?for\s+(\w+)\s+in\s+0\.\.\2\s*\{[\s\S]*?let\s+(\w+)\s*=\s*\1\[\4\s*/\s*8\];[\s\S]*?let\s+(\w+)\s*=\s*\(\5\s*>>\s*\(\4\s*%\s*8\)\)\s*&\s*1;[\s\S]*?\3\.push\(\6\s*!=\s*0\);'

Length of output: 453


Script:

#!/bin/bash
# Let's try a different approach to verify the usage patterns

# Search for all usages of read_compact_size
rg "read_compact_size" -B 2 -A 2

# Search for all usages of read_fixed_bitset
rg "read_fixed_bitset" -B 2 -A 2

# Search for potential manual bitset reading patterns
rg "read_exact.*\[\]" -B 2 -A 2

# Look for Vec::with_capacity followed by push operations (potential manual bitset handling)
rg "Vec::with_capacity" -B 2 -A 2

Length of output: 13852

Comment on lines +52 to +54
if self.version == 2 || self.version == 4 {
size += 2;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Correct the size calculation for quorum_index.

In the size method, when version is 2 or 4, you're adding 2 to the size for quorum_index. However, this should be done conditionally based on whether quorum_index is Some or None. If it's None, the size should not be incremented.

Modify the size calculation to account for the Option type:

if self.version == 2 || self.version == 4 {
-    size += 2;
+    if self.quorum_index.is_some() {
+        size += 2; // Add size only if quorum_index is present
+    }
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if self.version == 2 || self.version == 4 {
size += 2;
}
if self.version == 2 || self.version == 4 {
if self.quorum_index.is_some() {
size += 2; // Add size only if quorum_index is present
}
}

Comment on lines +145 to +172
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)
}
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider reusing existing VarInt decoding instead of read_compact_size.

The read_compact_size function replicates functionality already provided by VarInt::consensus_decode. Reusing existing implementations can reduce code duplication and potential errors.

Replace read_compact_size with VarInt::consensus_decode:

-let signers_count = read_compact_size(r)?;
+let signers_count = VarInt::consensus_decode(r)?.0;

Make similar changes for valid_members_count.

If read_compact_size is no longer used after these changes, consider removing it to keep the codebase lean and maintainable.

Committable suggestion was skipped due to low confidence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants