Skip to content

Commit db9ad0d

Browse files
authored
refactor: block serialisation and addition of tests (#47)
* added: write_compact_size and test * more work * suggestions * suggestions * safety check on write_fixed_bitset
1 parent d224400 commit db9ad0d

File tree

4 files changed

+328
-100
lines changed

4 files changed

+328
-100
lines changed

dash/src/blockdata/block.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -476,11 +476,11 @@ mod tests {
476476
"010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b0201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac"
477477
);
478478

479-
let prevhash = hex!("85691f6a060e65346c281ed25b99dbd18c139053562ccd001d00000000000000");
480-
let merkle = hex!("377b6aa24658b7a0ae7b73f0673d047a291de5cbc06907038b288b2ebf491c2c");
479+
let prevhash = hex!("0ec684405b58b3a0f0144c9a92c7d4296587ba6fc71041fff2130a038a000000");
480+
let merkle = hex!("78e259b490cfc8a8e50e1933afde3f777a47bdac8b61d504a51b68dede2ac181");
481481

482482
let work_bytes: [u8; 32] =
483-
hex!("000000000000000000000000000000000000000000000000050ec30af44bf25e")
483+
hex!("0000000000000000000000000000000000000000000000000000000000f7b6f1")
484484
.try_into()
485485
.unwrap();
486486
let work = Work::from_be_bytes(work_bytes);
@@ -493,16 +493,16 @@ mod tests {
493493
assert_eq!(serialize(&real_decode.header.prev_blockhash), prevhash);
494494
assert_eq!(real_decode.header.merkle_root, real_decode.compute_merkle_root().unwrap());
495495
assert_eq!(serialize(&real_decode.header.merkle_root), merkle);
496-
assert_eq!(real_decode.header.time, 1685447065);
497-
assert_eq!(real_decode.header.bits, CompactTarget::from_consensus(422747587));
498-
assert_eq!(real_decode.header.nonce, 2456102546);
496+
assert_eq!(real_decode.header.time, 1730283725);
497+
assert_eq!(real_decode.header.bits, CompactTarget::from_consensus(503384208));
498+
assert_eq!(real_decode.header.nonce, 394542);
499499
assert_eq!(real_decode.header.work(), work);
500500
assert_eq!(
501501
real_decode.header.validate_pow(real_decode.header.target()).unwrap(),
502502
real_decode.block_hash()
503503
);
504-
assert_eq!(real_decode.header.difficulty(), 84852220);
505-
assert_eq!(real_decode.header.difficulty_float(), 84852220.19239795);
504+
assert_eq!(real_decode.header.difficulty(), 0);
505+
assert_eq!(real_decode.header.difficulty_float(), 0.0037797675075301206);
506506
// [test] TODO: check the transaction data
507507

508508
assert_eq!(real_decode.size(), some_block.len());

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

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crate::hash_types::{MerkleRootMasternodeList, MerkleRootQuorums};
2323
use crate::io::{Error, ErrorKind};
2424
use crate::{VarInt, io};
2525
use crate::bls_sig_utils::BLSSignature;
26+
use crate::consensus::encode::{compact_size_len, read_compact_size, write_compact_size};
2627

2728
/// A Coinbase payload. This is contained as the payload of a coinbase special transaction.
2829
/// The Coinbase payload is described in DIP4.
@@ -43,15 +44,16 @@ pub struct CoinbasePayload {
4344
impl CoinbasePayload {
4445
/// The size of the payload in bytes.
4546
/// version(2) + height(4) + merkle_root_masternode_list(32) + merkle_root_quorums(32)
46-
/// in addition to the above, if version >= 3: asset_locked_amount(8) + best_cl_height(4) +
47-
/// best_cl_signature(VarInt(len) + len)
47+
/// in addition to the above, if version >= 3: asset_locked_amount(8) + best_cl_height(compact_size) +
48+
/// best_cl_signature(96)
4849
pub fn size(&self) -> usize {
4950
let mut size: usize = 2 + 4 + 32 + 32;
5051
if self.version >= 3 {
51-
size += 4 + 8;
52-
if let Some(sig) = &self.best_cl_signature {
53-
size += VarInt(sig.len() as u64).len() + sig.len()
52+
size += 96;
53+
if let Some(best_cl_height) = self.best_cl_height {
54+
size += compact_size_len(best_cl_height);
5455
}
56+
size += 8;
5557
}
5658
size
5759
}
@@ -66,7 +68,7 @@ impl Encodable for CoinbasePayload {
6668
len += self.merkle_root_quorums.consensus_encode(w)?;
6769
if self.version >= 3 {
6870
if let Some(best_cl_height) = self.best_cl_height {
69-
len += best_cl_height.consensus_encode(w)?;
71+
len += write_compact_size(w, best_cl_height)?;
7072
} else {
7173
return Err(Error::new(ErrorKind::InvalidInput, "best_cl_height is not set"));
7274
}
@@ -94,12 +96,7 @@ impl Decodable for CoinbasePayload {
9496
let merkle_root_masternode_list = MerkleRootMasternodeList::consensus_decode(r)?;
9597
let merkle_root_quorums = MerkleRootQuorums::consensus_decode(r)?;
9698
let best_cl_height = if version >= 3 {
97-
let value = u8::consensus_decode(r)?;
98-
match value {
99-
253 => Some(u16::consensus_decode(r)? as u32),
100-
254 => Some(u32::consensus_decode(r)?),
101-
_ => Some(value as u32)
102-
}
99+
Some(read_compact_size(r)?)
103100
} else { None };
104101
let best_cl_signature =
105102
if version >= 3 { Some(BLSSignature::consensus_decode(r)?) } else { None };
@@ -126,7 +123,7 @@ mod tests {
126123

127124
#[test]
128125
fn size() {
129-
let test_cases: &[(usize, u16)] = &[(70, 2), (179, 3)];
126+
let test_cases: &[(usize, u16)] = &[(70, 2), (177, 3)];
130127
for (want, version) in test_cases.iter() {
131128
let payload = CoinbasePayload {
132129
height: 1000,

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

Lines changed: 57 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crate::consensus::{Decodable, Encodable, encode};
2323
use crate::hash_types::{QuorumHash, QuorumVVecHash};
2424
use crate::prelude::*;
2525
use crate::{VarInt, io};
26+
use crate::consensus::encode::{compact_size_len, fixed_bitset_len, read_compact_size, read_fixed_bitset, write_compact_size, write_fixed_bitset};
2627

2728
/// A Quorum Finalization Commitment. It is described in the finalization section of DIP6:
2829
/// [dip-0006.md#6-finalization-phase](https://github.com/dashpay/dips/blob/master/dip-0006.md#6-finalization-phase)
@@ -35,8 +36,8 @@ pub struct QuorumFinalizationCommitment {
3536
pub llmq_type: u8,
3637
pub quorum_hash: QuorumHash,
3738
pub quorum_index: Option<i16>,
38-
pub signers: Vec<u8>,
39-
pub valid_members: Vec<u8>,
39+
pub signers: Vec<bool>,
40+
pub valid_members: Vec<bool>,
4041
pub quorum_public_key: BLSPublicKey,
4142
pub quorum_vvec_hash: QuorumVVecHash,
4243
pub quorum_sig: BLSSignature,
@@ -47,8 +48,10 @@ impl QuorumFinalizationCommitment {
4748
/// The size of the payload in bytes.
4849
pub fn size(&self) -> usize {
4950
let mut size = 2 + 1 + 32 + 48 + 32 + 96 + 96;
50-
size += VarInt(self.signers.len() as u64).len() + self.signers.len();
51-
size += VarInt(self.valid_members.len() as u64).len() + self.valid_members.len();
51+
size += compact_size_len(self.signers.len() as u32);
52+
size += fixed_bitset_len(self.signers.as_slice(), self.signers.len());
53+
size += compact_size_len(self.valid_members.len() as u32);
54+
size += fixed_bitset_len(self.valid_members.as_slice(), self.valid_members.len());
5255
if self.version == 2 || self.version == 4 {
5356
size += 2;
5457
}
@@ -67,8 +70,10 @@ impl Encodable for QuorumFinalizationCommitment {
6770
len += q_index.consensus_encode(w)?;
6871
}
6972
}
70-
len += self.signers.consensus_encode(w)?;
71-
len += self.valid_members.consensus_encode(w)?;
73+
len += write_compact_size(w, self.signers.len() as u32)?;
74+
len += write_fixed_bitset(w, self.signers.as_slice(), self.signers.iter().len())?;
75+
len += write_compact_size(w, self.valid_members.len() as u32)?;
76+
len += write_fixed_bitset(w, self.valid_members.as_slice(), self.valid_members.iter().len())?;
7277
len += self.quorum_public_key.consensus_encode(w)?;
7378
len += self.quorum_vvec_hash.consensus_encode(w)?;
7479
len += self.quorum_sig.consensus_encode(w)?;
@@ -96,8 +101,8 @@ impl Decodable for QuorumFinalizationCommitment {
96101
llmq_type,
97102
quorum_hash,
98103
quorum_index,
99-
signers: signers.iter().map(|&b| b as u8).collect(),
100-
valid_members: valid_members.iter().map(|&b| b as u8).collect(),
104+
signers,
105+
valid_members,
101106
quorum_public_key,
102107
quorum_vvec_hash,
103108
quorum_sig,
@@ -144,86 +149,60 @@ impl Decodable for QuorumCommitmentPayload {
144149
}
145150
}
146151

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-
195152
#[cfg(test)]
196153
mod tests {
197154
use hashes::Hash;
198155

199156
use crate::bls_sig_utils::{BLSPublicKey, BLSSignature};
200157
use crate::consensus::Encodable;
201158
use crate::hash_types::{QuorumHash, QuorumVVecHash};
202-
use crate::transaction::special_transaction::quorum_commitment::{
203-
QuorumCommitmentPayload, QuorumFinalizationCommitment,
204-
};
159+
use crate::transaction::special_transaction::quorum_commitment::{QuorumCommitmentPayload, QuorumFinalizationCommitment};
205160

206161
#[test]
207162
fn size() {
208-
let want = 325;
209-
let payload = QuorumCommitmentPayload {
210-
version: 0,
211-
height: 0,
212-
finalization_commitment: QuorumFinalizationCommitment {
163+
{
164+
let want = 317;
165+
let payload = QuorumCommitmentPayload {
166+
version: 0,
167+
height: 0,
168+
finalization_commitment: QuorumFinalizationCommitment {
169+
version: 1,
170+
llmq_type: 0,
171+
quorum_hash: QuorumHash::all_zeros(),
172+
quorum_index: None,
173+
signers: vec![true, false, true, true, false],
174+
valid_members: vec![false, true, false, true],
175+
quorum_public_key: BLSPublicKey::from([0; 48]),
176+
quorum_vvec_hash: QuorumVVecHash::all_zeros(),
177+
quorum_sig: BLSSignature::from([0; 96]),
178+
sig: BLSSignature::from([0; 96]),
179+
},
180+
};
181+
let actual = payload.consensus_encode(&mut Vec::new()).unwrap();
182+
assert_eq!(payload.size(), want);
183+
assert_eq!(actual, want);
184+
}
185+
{
186+
let want = 319;
187+
let payload = QuorumCommitmentPayload {
213188
version: 0,
214-
llmq_type: 0,
215-
quorum_hash: QuorumHash::all_zeros(),
216-
quorum_index: None,
217-
signers: vec![1, 2, 3, 4, 5],
218-
valid_members: vec![6, 7, 8, 9, 0],
219-
quorum_public_key: BLSPublicKey::from([0; 48]),
220-
quorum_vvec_hash: QuorumVVecHash::all_zeros(),
221-
quorum_sig: BLSSignature::from([0; 96]),
222-
sig: BLSSignature::from([0; 96]),
223-
},
224-
};
225-
let actual = payload.consensus_encode(&mut Vec::new()).unwrap();
226-
assert_eq!(payload.size(), want);
227-
assert_eq!(actual, want);
189+
height: 0,
190+
finalization_commitment: QuorumFinalizationCommitment {
191+
version: 2,
192+
llmq_type: 0,
193+
quorum_hash: QuorumHash::all_zeros(),
194+
quorum_index: Some(1),
195+
signers: vec![true, false, true, true, false, true, false],
196+
valid_members: vec![false, true, false, true, false, true],
197+
quorum_public_key: BLSPublicKey::from([0; 48]),
198+
quorum_vvec_hash: QuorumVVecHash::all_zeros(),
199+
quorum_sig: BLSSignature::from([0; 96]),
200+
sig: BLSSignature::from([0; 96]),
201+
},
202+
};
203+
let actual = payload.consensus_encode(&mut Vec::new()).unwrap();
204+
assert_eq!(payload.size(), want);
205+
assert_eq!(actual, want);
206+
}
228207
}
229208
}

0 commit comments

Comments
 (0)