blvm_primitives/serialization/
block.rs1use super::transaction::{deserialize_transaction_with_witness, serialize_transaction};
7use super::varint::{decode_varint, encode_varint};
8use crate::error::{ConsensusError, Result};
9use crate::types::*;
10use std::borrow::Cow;
11
12#[derive(Debug, Clone, PartialEq, Eq)]
14pub enum BlockParseError {
15 InsufficientBytes,
16 InvalidVersion,
17 InvalidTimestamp,
18 InvalidBits,
19 InvalidNonce,
20 InvalidTransactionCount,
21 InvalidWitnessMarker,
22}
23
24impl std::fmt::Display for BlockParseError {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 match self {
27 BlockParseError::InsufficientBytes => {
28 write!(f, "Insufficient bytes to parse block header")
29 }
30 BlockParseError::InvalidVersion => write!(f, "Invalid block version"),
31 BlockParseError::InvalidTimestamp => write!(f, "Invalid block timestamp"),
32 BlockParseError::InvalidBits => write!(f, "Invalid block bits"),
33 BlockParseError::InvalidNonce => write!(f, "Invalid block nonce"),
34 BlockParseError::InvalidTransactionCount => write!(f, "Invalid transaction count"),
35 BlockParseError::InvalidWitnessMarker => write!(f, "Invalid witness marker"),
36 }
37 }
38}
39
40impl std::error::Error for BlockParseError {}
41
42pub fn serialize_block_header(header: &BlockHeader) -> Vec<u8> {
44 let mut result = Vec::with_capacity(80);
45 result.extend_from_slice(&(header.version as i32).to_le_bytes());
46 result.extend_from_slice(&header.prev_block_hash);
47 result.extend_from_slice(&header.merkle_root);
48 result.extend_from_slice(&(header.timestamp as u32).to_le_bytes());
49 result.extend_from_slice(&(header.bits as u32).to_le_bytes());
50 result.extend_from_slice(&(header.nonce as u32).to_le_bytes());
51 assert_eq!(result.len(), 80);
52 result
53}
54
55pub fn deserialize_block_header(data: &[u8]) -> Result<BlockHeader> {
57 if data.len() < 80 {
58 return Err(ConsensusError::Serialization(Cow::Owned(
59 BlockParseError::InsufficientBytes.to_string(),
60 )));
61 }
62
63 let mut offset = 0;
64
65 let version = i32::from_le_bytes([
66 data[offset],
67 data[offset + 1],
68 data[offset + 2],
69 data[offset + 3],
70 ]) as i64;
71 offset += 4;
72
73 let mut prev_block_hash = [0u8; 32];
74 prev_block_hash.copy_from_slice(&data[offset..offset + 32]);
75 offset += 32;
76
77 let mut merkle_root = [0u8; 32];
78 merkle_root.copy_from_slice(&data[offset..offset + 32]);
79 offset += 32;
80
81 let timestamp = u32::from_le_bytes([
82 data[offset],
83 data[offset + 1],
84 data[offset + 2],
85 data[offset + 3],
86 ]) as u64;
87 offset += 4;
88
89 let bits = u32::from_le_bytes([
90 data[offset],
91 data[offset + 1],
92 data[offset + 2],
93 data[offset + 3],
94 ]) as u64;
95 offset += 4;
96
97 let nonce = u32::from_le_bytes([
98 data[offset],
99 data[offset + 1],
100 data[offset + 2],
101 data[offset + 3],
102 ]) as u64;
103
104 Ok(BlockHeader {
105 version,
106 prev_block_hash,
107 merkle_root,
108 timestamp,
109 bits,
110 nonce,
111 })
112}
113
114pub fn deserialize_block_with_witnesses(data: &[u8]) -> Result<(Block, Vec<Vec<Witness>>)> {
116 if data.len() < 80 {
117 return Err(ConsensusError::Serialization(Cow::Owned(
118 BlockParseError::InsufficientBytes.to_string(),
119 )));
120 }
121
122 let mut offset = 0;
123
124 let header = deserialize_block_header(&data[offset..offset + 80])?;
125 offset += 80;
126
127 let (tx_count, varint_len) = decode_varint(&data[offset..])?;
128 offset += varint_len;
129
130 if tx_count == 0 {
131 return Err(ConsensusError::Serialization(Cow::Owned(
132 BlockParseError::InvalidTransactionCount.to_string(),
133 )));
134 }
135
136 let mut transactions = Vec::new();
137 let mut all_witnesses: Vec<Vec<Witness>> = Vec::new();
138
139 for _ in 0..tx_count {
140 let (tx, input_witnesses, bytes_consumed) =
141 deserialize_transaction_with_witness(&data[offset..])?;
142 offset += bytes_consumed;
143 transactions.push(tx);
144 all_witnesses.push(input_witnesses);
145 }
146
147 while all_witnesses.len() < transactions.len() {
148 all_witnesses.push(Vec::new());
149 }
150
151 Ok((
152 Block {
153 header,
154 transactions: transactions.into_boxed_slice(),
155 },
156 all_witnesses,
157 ))
158}
159
160pub fn serialize_block_with_witnesses(
162 block: &Block,
163 witnesses: &[Vec<Witness>],
164 include_witness: bool,
165) -> Vec<u8> {
166 let mut result = Vec::new();
167
168 result.extend_from_slice(&serialize_block_header(&block.header));
169 result.extend_from_slice(&encode_varint(block.transactions.len() as u64));
170
171 let has_witness = include_witness
172 && witnesses
173 .iter()
174 .any(|tx_witnesses| tx_witnesses.iter().any(|w| !w.is_empty()));
175
176 if has_witness {
177 result.push(0x00);
178 result.push(0x01);
179 }
180
181 for tx in block.transactions.iter() {
182 result.extend_from_slice(&serialize_transaction(tx));
183 }
184
185 if has_witness {
186 for tx_witnesses in witnesses.iter().take(block.transactions.len()) {
187 for witness in tx_witnesses {
188 result.extend_from_slice(&encode_varint(witness.len() as u64));
189 for element in witness {
190 result.extend_from_slice(&encode_varint(element.len() as u64));
191 result.extend_from_slice(element);
192 }
193 }
194 }
195 }
196
197 result
198}
199
200pub fn serialize_block(block: &Block) -> Vec<u8> {
202 let witnesses: Vec<Vec<Witness>> = block.transactions.iter().map(|_| Vec::new()).collect();
203 serialize_block_with_witnesses(block, &witnesses, false)
204}
205
206pub fn validate_block_serialized_size(
208 block: &Block,
209 witnesses: &[Vec<Witness>],
210 include_witness: bool,
211 provided_size: usize,
212) -> bool {
213 let serialized = serialize_block_with_witnesses(block, witnesses, include_witness);
214 serialized.len() == provided_size
215}