1use crate::{BlockHeader, SignedTransaction, TransactionWithSignature};
6use byteorder::{ByteOrder, LittleEndian};
7use cfx_types::{Space, H256, U256};
8use keccak_hash::keccak;
9use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
10use rand::Rng;
11use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream};
12use siphasher::sip::SipHasher24;
13use std::{
14 fmt::{Debug, Formatter},
15 hash::Hasher,
16 sync::Arc,
17};
18
19pub type BlockNumber = u64;
20pub type BlockHeight = u64;
21
22#[derive(Debug, Clone, PartialEq)]
24pub struct Block {
25 pub block_header: BlockHeader,
27 pub transactions: Vec<Arc<SignedTransaction>>,
29 pub approximated_rlp_size: usize,
31 pub approximated_rlp_size_with_public: usize,
33}
34
35impl MallocSizeOf for Block {
36 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
37 self.block_header.size_of(ops) + self.transactions.size_of(ops)
38 }
39}
40
41impl Block {
42 pub fn new(
43 block_header: BlockHeader, transactions: Vec<Arc<SignedTransaction>>,
44 ) -> Self {
45 Self::new_with_rlp_size(block_header, transactions, None, None)
46 }
47
48 pub fn new_with_rlp_size(
49 block_header: BlockHeader, transactions: Vec<Arc<SignedTransaction>>,
50 rlp_size: Option<usize>, rlp_size_with_public: Option<usize>,
51 ) -> Self {
52 let approximated_rlp_size = match rlp_size {
53 Some(size) => size,
54 None => transactions
55 .iter()
56 .fold(block_header.approximated_rlp_size(), |accum, tx| {
57 accum + tx.rlp_size()
58 }),
59 };
60
61 let approximated_rlp_size_with_public = match rlp_size_with_public {
62 Some(size) => size,
63 None => approximated_rlp_size + transactions.len() * 84, };
65
66 Block {
67 block_header,
68 transactions,
69 approximated_rlp_size,
70 approximated_rlp_size_with_public,
71 }
72 }
73
74 pub fn hash(&self) -> H256 { self.block_header.hash() }
75
76 pub fn approximated_rlp_size(&self) -> usize { self.approximated_rlp_size }
78
79 pub fn approximated_rlp_size_with_public(&self) -> usize {
81 self.approximated_rlp_size_with_public
82 }
83
84 pub fn total_gas(&self) -> U256 {
85 let mut sum = U256::from(0);
86 for t in &self.transactions {
87 sum += *t.gas();
88 }
89 sum
90 }
91
92 pub fn size(&self) -> usize {
95 self.transactions
101 .iter()
102 .fold(0, |accum, tx| accum + tx.rlp_size())
103 }
104
105 pub fn transaction_hashes(&self, space_filter: Option<Space>) -> Vec<H256> {
106 if let Some(space) = space_filter {
107 self.transactions
108 .iter()
109 .filter(|tx| tx.space() == space)
110 .map(|tx| tx.hash())
111 .collect()
112 } else {
113 self.transactions.iter().map(|tx| tx.hash()).collect()
114 }
115 }
116
117 pub fn to_compact(&self) -> CompactBlock {
121 let nonce: u64 = rand::rng().random();
122 let (k0, k1) =
123 CompactBlock::get_shortid_key(&self.block_header, &nonce);
124 CompactBlock {
125 block_header: self.block_header.clone(),
126 nonce,
127 tx_short_ids: CompactBlock::create_shortids(
128 &self.transactions,
129 k0,
130 k1,
131 ),
132 reconstructed_txns: Vec::new(),
134 }
135 }
136
137 pub fn encode_body_with_tx_public(&self) -> Vec<u8> {
138 let mut stream = RlpStream::new();
139 stream.begin_list(self.transactions.len());
140 for tx in &self.transactions {
141 stream.append(tx.as_ref());
142 }
143 stream.drain()
144 }
145
146 pub fn decode_body_with_tx_public(
147 rlp: &Rlp,
148 ) -> Result<Vec<Arc<SignedTransaction>>, DecoderError> {
149 if rlp.as_raw().len() != rlp.payload_info()?.total() {
150 return Err(DecoderError::RlpIsTooBig);
151 }
152
153 let signed_transactions = rlp.as_list()?;
154 let mut transactions = Vec::with_capacity(signed_transactions.len());
155 for tx in signed_transactions {
156 transactions.push(Arc::new(tx));
157 }
158
159 Ok(transactions)
160 }
161
162 pub fn encode_with_tx_public(&self) -> Vec<u8> {
163 let mut stream = RlpStream::new();
164 stream
165 .begin_list(2)
166 .append(&self.block_header)
167 .append_raw(&*self.encode_body_with_tx_public(), 1);
168 stream.drain()
169 }
170
171 pub fn decode_with_tx_public(rlp: &Rlp) -> Result<Self, DecoderError> {
172 if rlp.as_raw().len() != rlp.payload_info()?.total() {
173 return Err(DecoderError::RlpIsTooBig);
174 }
175 if rlp.item_count()? != 2 {
176 return Err(DecoderError::RlpIncorrectListLen);
177 }
178
179 Ok(Block::new_with_rlp_size(
180 rlp.val_at(0)?,
181 Self::decode_body_with_tx_public(&rlp.at(1)?)?,
182 None,
183 Some(rlp.as_raw().len()),
184 ))
185 }
186}
187
188impl Encodable for Block {
191 fn rlp_append(&self, stream: &mut RlpStream) {
192 stream.begin_list(2).append(&self.block_header);
193 stream.begin_list(self.transactions.len());
194 for tx in &self.transactions {
195 stream.append(&tx.transaction);
196 }
197 }
198}
199
200impl Decodable for Block {
203 fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
204 if rlp.as_raw().len() != rlp.payload_info()?.total() {
205 return Err(DecoderError::RlpIsTooBig);
206 }
207 if rlp.item_count()? != 2 {
208 return Err(DecoderError::RlpIncorrectListLen);
209 }
210
211 let transactions = rlp.list_at::<TransactionWithSignature>(1)?;
212
213 let mut signed_transactions = Vec::with_capacity(transactions.len());
214 for tx in transactions {
215 let signed = SignedTransaction::new_unsigned(tx);
216 signed_transactions.push(Arc::new(signed));
217 }
218
219 Ok(Block::new_with_rlp_size(
220 rlp.val_at(0)?,
221 signed_transactions,
222 Some(rlp.as_raw().len()),
223 None,
224 ))
225 }
226}
227
228#[derive(Clone, PartialEq)]
231pub struct CompactBlock {
232 pub block_header: BlockHeader,
234 pub nonce: u64,
236 pub tx_short_ids: Vec<u8>,
238 pub reconstructed_txns: Vec<Option<Arc<SignedTransaction>>>,
240}
241
242impl Debug for CompactBlock {
243 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
244 write!(
245 f,
246 "CompactBlock{{ block_header: {:?}, nonce: {:?}}}",
247 self.block_header, self.nonce
248 )
249 }
250}
251
252impl MallocSizeOf for CompactBlock {
253 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
254 self.tx_short_ids.size_of(ops) + self.reconstructed_txns.size_of(ops)
255 }
256}
257
258impl CompactBlock {
259 const SHORT_ID_SIZE_IN_BYTES: usize = 6;
260
261 pub fn len(&self) -> usize {
262 self.tx_short_ids.len() / CompactBlock::SHORT_ID_SIZE_IN_BYTES
263 }
264
265 pub fn hash(&self) -> H256 { self.block_header.hash() }
266
267 pub fn get_shortid_key(header: &BlockHeader, nonce: &u64) -> (u64, u64) {
268 let mut stream = RlpStream::new();
269 stream.begin_list(2).append(header).append(nonce);
270 let to_hash = stream.out();
271 let key_hash: [u8; 32] = keccak(to_hash).into();
272 let k0 = LittleEndian::read_u64(&key_hash[0..8]);
273 let k1 = LittleEndian::read_u64(&key_hash[8..16]);
274 (k0, k1)
275 }
276
277 pub fn create_shortids(
279 transactions: &Vec<Arc<SignedTransaction>>, k0: u64, k1: u64,
280 ) -> Vec<u8> {
281 let mut short_ids: Vec<u8> = vec![];
282
283 for tx in transactions {
284 let hash = tx.hash();
285 let random = CompactBlock::get_random_bytes(&hash, k0, k1);
286
287 short_ids.push(((random & 0xff00) >> 8) as u8);
288 short_ids.push((random & 0xff) as u8);
289 short_ids.push(hash[28]);
290 short_ids.push(hash[29]);
291 short_ids.push(hash[30]);
292 short_ids.push(hash[31]);
293 }
294 short_ids
295 }
296
297 pub fn to_u16(v1: u8, v2: u8) -> u16 { ((v1 as u16) << 8) + v2 as u16 }
298
299 pub fn to_u32(v1: u8, v2: u8, v3: u8, v4: u8) -> u32 {
300 ((v1 as u32) << 24)
301 + ((v2 as u32) << 16)
302 + ((v3 as u32) << 8)
303 + v4 as u32
304 }
305
306 pub fn get_random_bytes(
307 transaction_id: &H256, key1: u64, key2: u64,
308 ) -> u16 {
309 let mut hasher = SipHasher24::new_with_keys(key1, key2);
310 hasher.write(transaction_id.as_ref());
311 (hasher.finish() & 0xffff) as u16
312 }
313
314 pub fn get_decomposed_short_ids(&self) -> (Vec<u16>, Vec<u32>) {
315 let mut random_bytes_vector: Vec<u16> = Vec::new();
316 let mut fixed_bytes_vector: Vec<u32> = Vec::new();
317
318 for i in (0..self.tx_short_ids.len())
319 .step_by(CompactBlock::SHORT_ID_SIZE_IN_BYTES)
320 {
321 random_bytes_vector.push(CompactBlock::to_u16(
322 self.tx_short_ids[i],
323 self.tx_short_ids[i + 1],
324 ));
325 fixed_bytes_vector.push(CompactBlock::to_u32(
326 self.tx_short_ids[i + 2],
327 self.tx_short_ids[i + 3],
328 self.tx_short_ids[i + 4],
329 self.tx_short_ids[i + 5],
330 ));
331 }
332
333 (random_bytes_vector, fixed_bytes_vector)
334 }
335}
336
337impl Encodable for CompactBlock {
338 fn rlp_append(&self, steam: &mut RlpStream) {
339 steam
340 .begin_list(3)
341 .append(&self.block_header)
342 .append(&self.nonce)
343 .append(&self.tx_short_ids);
344 }
345}
346
347impl Decodable for CompactBlock {
348 fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
349 let short_ids: Vec<u8> = rlp.val_at(2)?;
350 if short_ids.len() % CompactBlock::SHORT_ID_SIZE_IN_BYTES != 0 {
351 return Err(DecoderError::Custom("Compact Block length Error!"));
352 }
353 Ok(CompactBlock {
354 block_header: rlp.val_at(0)?,
355 nonce: rlp.val_at(1)?,
356 tx_short_ids: short_ids,
357 reconstructed_txns: Vec::new(),
358 })
359 }
360}