1mod base_price;
6pub use base_price::{
7 compute_next_price, compute_next_price_tuple, estimate_gas_used_boundary,
8 estimate_max_possible_gas,
9};
10
11use crate::{
12 block::BlockHeight, bytes::Bytes, hash::keccak, pos::PosBlockId,
13 receipt::BlockReceipts, MERKLE_NULL_NODE, NULL_EPOCH,
14};
15use cfx_parameters::block::{cspace_block_gas_limit, espace_block_gas_limit};
16use cfx_types::{
17 Address, Bloom, Space, SpaceMap, H256, KECCAK_EMPTY_BLOOM, U256,
18};
19use malloc_size_of::{new_malloc_size_ops, MallocSizeOf, MallocSizeOfOps};
20use once_cell::sync::OnceCell;
21use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream};
22use rlp_derive::{RlpDecodable, RlpEncodable};
23use std::{
24 mem,
25 ops::{Deref, DerefMut},
26 sync::Arc,
27};
28
29const HEADER_LIST_MIN_LEN: usize = 13;
30pub static CIP112_TRANSITION_HEIGHT: OnceCell<u64> = OnceCell::new();
33
34pub const BASE_PRICE_CHANGE_DENOMINATOR: usize = 8;
35
36#[derive(Clone, Debug, Eq, PartialEq, Default)]
42pub struct CustomData {
43 raw: Bytes,
44 count: usize,
45 data_len: usize,
47}
48
49impl MallocSizeOf for CustomData {
50 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
51 self.raw.size_of(ops)
52 }
53}
54
55impl CustomData {
56 fn from_items(items: &[Bytes], height: u64) -> Self {
57 if items.is_empty() {
58 return Self::default();
59 }
60 let value_encoded =
61 height >= *CIP112_TRANSITION_HEIGHT.get().expect("initialized");
62 let mut raw = Vec::new();
63 let mut data_len = 0;
64 for item in items {
65 data_len += item.len();
66 if value_encoded {
67 raw.extend_from_slice(rlp::encode(item).as_ref());
68 } else {
69 raw.extend_from_slice(item);
70 }
71 }
72 Self {
73 raw,
74 count: items.len(),
75 data_len,
76 }
77 }
78
79 fn from_rlp(
82 r: &Rlp, custom_start: usize, height: u64,
83 ) -> Result<Self, DecoderError> {
84 let item_count = r.item_count()?;
85 let count = item_count.saturating_sub(custom_start);
86 if count == 0 {
87 return Ok(Self::default());
88 }
89 let value_encoded =
90 height >= *CIP112_TRANSITION_HEIGHT.get().expect("initialized");
91 let mut raw = Vec::new();
92 let mut data_len = 0;
93 if value_encoded {
94 let mut scratch = RlpStream::new();
98 for i in custom_start..item_count {
99 let content: Bytes = r.val_at(i)?;
100 data_len += content.len();
101 scratch.clear();
102 scratch.append(&content);
103 raw.extend_from_slice(scratch.as_raw());
104 }
105 } else {
106 for i in custom_start..item_count {
107 let item_raw = r.at(i)?.as_raw();
108 data_len += item_raw.len();
109 raw.extend_from_slice(item_raw);
110 }
111 }
112 Ok(Self {
113 raw,
114 count,
115 data_len,
116 })
117 }
118
119 fn raw_items(&self) -> RawItemIter<'_> {
120 RawItemIter {
121 raw: &self.raw,
122 offset: 0,
123 }
124 }
125}
126
127struct RawItemIter<'a> {
128 raw: &'a [u8],
129 offset: usize,
130}
131
132impl<'a> Iterator for RawItemIter<'a> {
133 type Item = &'a [u8];
134
135 fn next(&mut self) -> Option<&'a [u8]> {
136 if self.offset >= self.raw.len() {
137 return None;
138 }
139 let pi = Rlp::new(&self.raw[self.offset..]).payload_info();
142 debug_assert!(
143 pi.is_ok(),
144 "corrupt CustomData::raw at offset {}",
145 self.offset
146 );
147 let total = pi.ok()?.total();
148 let item = &self.raw[self.offset..self.offset + total];
149 self.offset += total;
150 Some(item)
151 }
152}
153
154#[derive(Clone, Debug, Eq)]
155pub struct BlockHeaderRlpPart {
156 parent_hash: H256,
158 height: BlockHeight,
160 timestamp: u64,
162 author: Address,
164 transactions_root: H256,
166 deferred_state_root: H256,
168 deferred_receipts_root: H256,
170 deferred_logs_bloom_hash: H256,
172 blame: u32,
177 difficulty: U256,
179 adaptive: bool,
181 gas_limit: U256,
183 referee_hashes: Vec<H256>,
185 custom: CustomData,
187 nonce: U256,
189 pos_reference: Option<H256>,
191 base_price: Option<BasePrice>,
193}
194
195impl PartialEq for BlockHeaderRlpPart {
196 fn eq(&self, o: &BlockHeaderRlpPart) -> bool {
197 self.parent_hash == o.parent_hash
198 && self.height == o.height
199 && self.timestamp == o.timestamp
200 && self.author == o.author
201 && self.transactions_root == o.transactions_root
202 && self.deferred_state_root == o.deferred_state_root
203 && self.deferred_receipts_root == o.deferred_receipts_root
204 && self.deferred_logs_bloom_hash == o.deferred_logs_bloom_hash
205 && self.blame == o.blame
206 && self.difficulty == o.difficulty
207 && self.adaptive == o.adaptive
208 && self.gas_limit == o.gas_limit
209 && self.referee_hashes == o.referee_hashes
210 && self.custom == o.custom
211 && self.pos_reference == o.pos_reference
212 && self.base_price == o.base_price
213 }
214}
215
216#[derive(Clone, Debug, Eq)]
218pub struct BlockHeader {
219 rlp_part: BlockHeaderRlpPart,
220 hash: Option<H256>,
222 pub pow_hash: Option<H256>,
224 pub approximated_rlp_size: usize,
226}
227
228impl Deref for BlockHeader {
229 type Target = BlockHeaderRlpPart;
230
231 fn deref(&self) -> &Self::Target { &self.rlp_part }
232}
233
234impl DerefMut for BlockHeader {
235 fn deref_mut(&mut self) -> &mut BlockHeaderRlpPart { &mut self.rlp_part }
236}
237
238impl MallocSizeOf for BlockHeader {
239 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
240 self.referee_hashes.size_of(ops) + self.custom.size_of(ops)
241 }
242}
243
244impl PartialEq for BlockHeader {
245 fn eq(&self, o: &BlockHeader) -> bool { self.rlp_part == o.rlp_part }
246}
247
248impl BlockHeader {
249 pub fn approximated_rlp_size(&self) -> usize { self.approximated_rlp_size }
251
252 pub fn parent_hash(&self) -> &H256 { &self.parent_hash }
254
255 pub fn height(&self) -> u64 { self.height }
257
258 pub fn timestamp(&self) -> u64 { self.timestamp }
260
261 pub fn author(&self) -> &Address { &self.author }
263
264 pub fn transactions_root(&self) -> &H256 { &self.transactions_root }
266
267 pub fn deferred_state_root(&self) -> &H256 { &self.deferred_state_root }
269
270 pub fn deferred_receipts_root(&self) -> &H256 {
272 &self.deferred_receipts_root
273 }
274
275 pub fn deferred_logs_bloom_hash(&self) -> &H256 {
277 &self.deferred_logs_bloom_hash
278 }
279
280 pub fn blame(&self) -> u32 { self.blame }
282
283 pub fn difficulty(&self) -> &U256 { &self.difficulty }
285
286 pub fn adaptive(&self) -> bool { self.adaptive }
288
289 pub fn gas_limit(&self) -> &U256 { &self.gas_limit }
291
292 pub fn core_space_gas_limit(&self) -> U256 {
293 cspace_block_gas_limit(
294 self.base_price.is_some(),
295 self.gas_limit().to_owned(),
296 )
297 }
298
299 pub fn espace_gas_limit(&self, can_pack: bool) -> U256 {
300 espace_block_gas_limit(can_pack, self.gas_limit().to_owned())
301 }
302
303 pub fn referee_hashes(&self) -> &Vec<H256> { &self.referee_hashes }
305
306 pub fn custom_count(&self) -> usize { self.custom.count }
307
308 pub fn custom_data_len(&self) -> usize { self.custom.data_len }
309
310 pub fn custom_item(&self, idx: usize) -> Option<Bytes> {
314 let raw_item = self.custom.raw_items().nth(idx)?;
315 Some(self.decode_custom_item(raw_item))
316 }
317
318 pub fn custom_items(&self) -> Vec<Bytes> {
320 self.custom
321 .raw_items()
322 .map(|raw_item| self.decode_custom_item(raw_item))
323 .collect()
324 }
325
326 fn custom_value_encoded(&self) -> bool {
327 self.height >= *CIP112_TRANSITION_HEIGHT.get().expect("initialized")
328 }
329
330 fn decode_custom_item(&self, raw_item: &[u8]) -> Bytes {
331 if self.custom_value_encoded() {
332 Rlp::new(raw_item)
334 .data()
335 .map(|d| d.to_vec())
336 .unwrap_or_default()
337 } else {
338 raw_item.to_vec()
339 }
340 }
341
342 pub fn nonce(&self) -> U256 { self.nonce }
344
345 pub fn pos_reference(&self) -> &Option<PosBlockId> { &self.pos_reference }
347
348 pub fn base_price(&self) -> Option<SpaceMap<U256>> {
349 self.base_price.map(
350 |BasePrice {
351 core_base_price,
352 espace_base_price,
353 }| SpaceMap::new(core_base_price, espace_base_price),
354 )
355 }
356
357 pub fn space_base_price(&self, space: Space) -> Option<U256> {
359 self.base_price.map(|x| match space {
360 Space::Native => x.core_base_price,
361 Space::Ethereum => x.espace_base_price,
362 })
363 }
364
365 pub fn set_nonce(&mut self, nonce: U256) { self.nonce = nonce; }
367
368 pub fn set_timestamp(&mut self, timestamp: u64) {
370 self.timestamp = timestamp;
371 }
372
373 pub fn set_custom(&mut self, custom: Vec<Bytes>) {
375 let height = self.height;
376 self.rlp_part.custom = CustomData::from_items(&custom, height);
377 }
378
379 pub fn compute_hash(&mut self) -> H256 {
381 let hash = self.hash();
382 self.hash = Some(hash);
383 hash
384 }
385
386 pub fn hash(&self) -> H256 {
388 self.hash.unwrap_or_else(|| keccak(self.rlp()))
389 }
390
391 pub fn problem_hash(&self) -> H256 { keccak(self.rlp_without_nonce()) }
393
394 pub fn rlp_without_nonce(&self) -> Bytes {
396 let mut stream = RlpStream::new();
397 self.stream_rlp_without_nonce(&mut stream);
398 stream.out().to_vec()
399 }
400
401 pub fn rlp(&self) -> Bytes {
403 let mut stream = RlpStream::new();
404 self.stream_rlp(&mut stream);
405 stream.out().to_vec()
406 }
407
408 fn stream_rlp_without_nonce(&self, stream: &mut RlpStream) {
410 let adaptive_n = if self.adaptive { 1_u8 } else { 0_u8 };
411 let list_len = HEADER_LIST_MIN_LEN
412 + self.pos_reference.is_some() as usize
413 + self.base_price.is_some() as usize
414 + self.custom.count;
415 stream
416 .begin_list(list_len)
417 .append(&self.parent_hash)
418 .append(&self.height)
419 .append(&self.timestamp)
420 .append(&self.author)
421 .append(&self.transactions_root)
422 .append(&self.deferred_state_root)
423 .append(&self.deferred_receipts_root)
424 .append(&self.deferred_logs_bloom_hash)
425 .append(&self.blame)
426 .append(&self.difficulty)
427 .append(&adaptive_n)
428 .append(&self.gas_limit)
429 .append_list(&self.referee_hashes);
430 if self.pos_reference.is_some() {
431 stream.append(&self.pos_reference);
432 }
433 if self.base_price.is_some() {
434 stream.append(&self.base_price);
435 }
436
437 if self.custom.count > 0 {
442 stream.append_raw(&self.custom.raw, self.custom.count);
443 }
444 }
445
446 fn stream_rlp(&self, stream: &mut RlpStream) {
448 let adaptive_n = if self.adaptive { 1_u8 } else { 0_u8 };
449 let list_len = HEADER_LIST_MIN_LEN
450 + 1
451 + self.pos_reference.is_some() as usize
452 + self.base_price.is_some() as usize
453 + self.custom.count;
454 stream
455 .begin_list(list_len)
456 .append(&self.parent_hash)
457 .append(&self.height)
458 .append(&self.timestamp)
459 .append(&self.author)
460 .append(&self.transactions_root)
461 .append(&self.deferred_state_root)
462 .append(&self.deferred_receipts_root)
463 .append(&self.deferred_logs_bloom_hash)
464 .append(&self.blame)
465 .append(&self.difficulty)
466 .append(&adaptive_n)
467 .append(&self.gas_limit)
468 .append_list(&self.referee_hashes)
469 .append(&self.nonce);
470 if self.pos_reference.is_some() {
471 stream.append(&self.pos_reference);
472 }
473 if self.base_price.is_some() {
474 stream.append(&self.base_price);
475 }
476 if self.custom.count > 0 {
478 stream.append_raw(&self.custom.raw, self.custom.count);
479 }
480 }
481
482 pub fn stream_rlp_with_pow_hash(&self, stream: &mut RlpStream) {
484 let adaptive_n = if self.adaptive { 1_u8 } else { 0_u8 };
485 let list_len = HEADER_LIST_MIN_LEN
486 + 2
487 + self.pos_reference.is_some() as usize
488 + self.base_price.is_some() as usize
489 + self.custom.count;
490 stream
491 .begin_list(list_len)
492 .append(&self.parent_hash)
493 .append(&self.height)
494 .append(&self.timestamp)
495 .append(&self.author)
496 .append(&self.transactions_root)
497 .append(&self.deferred_state_root)
498 .append(&self.deferred_receipts_root)
499 .append(&self.deferred_logs_bloom_hash)
500 .append(&self.blame)
501 .append(&self.difficulty)
502 .append(&adaptive_n)
503 .append(&self.gas_limit)
504 .append_list(&self.referee_hashes)
505 .append(&self.nonce)
506 .append(&self.pow_hash);
509 if self.pos_reference.is_some() {
510 stream.append(&self.pos_reference);
511 }
512 if self.base_price.is_some() {
513 stream.append(&self.base_price);
514 }
515
516 if self.custom.count > 0 {
518 stream.append_raw(&self.custom.raw, self.custom.count);
519 }
520 }
521
522 pub fn decode_with_pow_hash(bytes: &[u8]) -> Result<Self, DecoderError> {
523 let r = Rlp::new(bytes);
524 let mut rlp_part = BlockHeaderRlpPart {
525 parent_hash: r.val_at(0)?,
526 height: r.val_at(1)?,
527 timestamp: r.val_at(2)?,
528 author: r.val_at(3)?,
529 transactions_root: r.val_at(4)?,
530 deferred_state_root: r.val_at(5)?,
531 deferred_receipts_root: r.val_at(6)?,
532 deferred_logs_bloom_hash: r.val_at(7)?,
533 blame: r.val_at(8)?,
534 difficulty: r.val_at(9)?,
535 adaptive: r.val_at::<u8>(10)? == 1,
536 gas_limit: r.val_at(11)?,
537 referee_hashes: r.list_at(12)?,
538 custom: CustomData::default(),
539 nonce: r.val_at(13)?,
540 pos_reference: r.val_at(15).unwrap_or(None),
541 base_price: r.val_at(16).unwrap_or(None),
542 };
543 let pow_hash = r.val_at(14)?;
544
545 let custom_start = 15
546 + rlp_part.pos_reference.is_some() as usize
547 + rlp_part.base_price.is_some() as usize;
548 rlp_part.custom =
549 CustomData::from_rlp(&r, custom_start, rlp_part.height)?;
550
551 let mut header = BlockHeader {
552 rlp_part,
553 hash: None,
554 pow_hash,
555 approximated_rlp_size: bytes.len(),
556 };
557 header.compute_hash();
558 Ok(header)
559 }
560
561 pub fn size(&self) -> usize {
562 0
565 }
566}
567
568pub struct BlockHeaderBuilder {
569 parent_hash: H256,
570 height: u64,
571 timestamp: u64,
572 author: Address,
573 transactions_root: H256,
574 deferred_state_root: H256,
575 deferred_receipts_root: H256,
576 deferred_logs_bloom_hash: H256,
577 blame: u32,
578 difficulty: U256,
579 adaptive: bool,
580 gas_limit: U256,
581 referee_hashes: Vec<H256>,
582 custom: Vec<Bytes>,
583 nonce: U256,
584 pos_reference: Option<PosBlockId>,
585 base_price: Option<BasePrice>,
586}
587
588impl Default for BlockHeaderBuilder {
589 fn default() -> Self { Self::new() }
590}
591
592impl BlockHeaderBuilder {
593 pub fn new() -> Self {
594 Self {
595 parent_hash: NULL_EPOCH,
596 height: 0,
597 timestamp: 0,
598 author: Address::default(),
599 transactions_root: MERKLE_NULL_NODE,
600 deferred_state_root: Default::default(),
601 deferred_receipts_root: Default::default(),
602 deferred_logs_bloom_hash: KECCAK_EMPTY_BLOOM,
603 blame: 0,
604 difficulty: U256::default(),
605 adaptive: false,
606 gas_limit: U256::zero(),
607 referee_hashes: Vec::new(),
608 custom: Vec::new(),
609 nonce: U256::zero(),
610 pos_reference: None,
611 base_price: None,
612 }
613 }
614
615 pub fn with_parent_hash(&mut self, parent_hash: H256) -> &mut Self {
616 self.parent_hash = parent_hash;
617 self
618 }
619
620 pub fn with_height(&mut self, height: u64) -> &mut Self {
621 self.height = height;
622 self
623 }
624
625 pub fn with_timestamp(&mut self, timestamp: u64) -> &mut Self {
626 self.timestamp = timestamp;
627 self
628 }
629
630 pub fn with_author(&mut self, author: Address) -> &mut Self {
631 self.author = author;
632 self
633 }
634
635 pub fn with_transactions_root(
636 &mut self, transactions_root: H256,
637 ) -> &mut Self {
638 self.transactions_root = transactions_root;
639 self
640 }
641
642 pub fn with_deferred_state_root(
643 &mut self, deferred_state_root: H256,
644 ) -> &mut Self {
645 self.deferred_state_root = deferred_state_root;
646 self
647 }
648
649 pub fn with_deferred_receipts_root(
650 &mut self, deferred_receipts_root: H256,
651 ) -> &mut Self {
652 self.deferred_receipts_root = deferred_receipts_root;
653 self
654 }
655
656 pub fn with_deferred_logs_bloom_hash(
657 &mut self, deferred_logs_bloom_hash: H256,
658 ) -> &mut Self {
659 self.deferred_logs_bloom_hash = deferred_logs_bloom_hash;
660 self
661 }
662
663 pub fn with_blame(&mut self, blame: u32) -> &mut Self {
664 self.blame = blame;
665 self
666 }
667
668 pub fn with_difficulty(&mut self, difficulty: U256) -> &mut Self {
669 self.difficulty = difficulty;
670 self
671 }
672
673 pub fn with_adaptive(&mut self, adaptive: bool) -> &mut Self {
674 self.adaptive = adaptive;
675 self
676 }
677
678 pub fn with_gas_limit(&mut self, gas_limit: U256) -> &mut Self {
679 self.gas_limit = gas_limit;
680 self
681 }
682
683 pub fn with_referee_hashes(
684 &mut self, referee_hashes: Vec<H256>,
685 ) -> &mut Self {
686 self.referee_hashes = referee_hashes;
687 self
688 }
689
690 pub fn with_custom(&mut self, custom: Vec<Bytes>) -> &mut Self {
691 self.custom = custom;
692 self
693 }
694
695 pub fn with_nonce(&mut self, nonce: U256) -> &mut Self {
696 self.nonce = nonce;
697 self
698 }
699
700 pub fn with_pos_reference(
701 &mut self, pos_reference: Option<PosBlockId>,
702 ) -> &mut Self {
703 self.pos_reference = pos_reference;
704 self
705 }
706
707 pub fn with_base_price(
708 &mut self, maybe_base_price: Option<SpaceMap<U256>>,
709 ) -> &mut Self {
710 self.base_price = maybe_base_price.map(|x| BasePrice {
711 core_base_price: x[Space::Native],
712 espace_base_price: x[Space::Ethereum],
713 });
714 self
715 }
716
717 pub fn build(&self) -> BlockHeader {
718 let mut block_header = BlockHeader {
719 rlp_part: BlockHeaderRlpPart {
720 parent_hash: self.parent_hash,
721 height: self.height,
722 timestamp: self.timestamp,
723 author: self.author,
724 transactions_root: self.transactions_root,
725 deferred_state_root: self.deferred_state_root,
726 deferred_receipts_root: self.deferred_receipts_root,
727 deferred_logs_bloom_hash: self.deferred_logs_bloom_hash,
728 blame: self.blame,
729 difficulty: self.difficulty,
730 adaptive: self.adaptive,
731 gas_limit: self.gas_limit,
732 referee_hashes: self.referee_hashes.clone(),
733 custom: CustomData::from_items(&self.custom, self.height),
734 nonce: self.nonce,
735 pos_reference: self.pos_reference,
736 base_price: self.base_price,
737 },
738 hash: None,
739 pow_hash: None,
740 approximated_rlp_size: 0,
741 };
742
743 block_header.approximated_rlp_size =
744 mem::size_of::<BlockHeaderRlpPart>()
745 + block_header
746 .referee_hashes
747 .size_of(&mut new_malloc_size_ops());
748
749 block_header
750 }
751
752 pub fn compute_block_logs_bloom_hash(
753 receipts: &[Arc<BlockReceipts>],
754 ) -> H256 {
755 let bloom = receipts.iter().flat_map(|x| &x.receipts).fold(
756 Bloom::zero(),
757 |mut b, r| {
758 b.accrue_bloom(&r.log_bloom);
759 b
760 },
761 );
762
763 keccak(bloom)
764 }
765
766 pub fn compute_aggregated_bloom(blooms: Vec<Bloom>) -> Bloom {
767 blooms.into_iter().fold(Bloom::zero(), |mut res, bloom| {
768 res.accrue_bloom(&bloom);
769 res
770 })
771 }
772
773 pub fn compute_blame_state_root_vec_root(roots: Vec<H256>) -> H256 {
774 let mut accumulated_root = *roots.last().unwrap();
775 for i in (0..(roots.len() - 1)).rev() {
776 accumulated_root =
777 BlockHeaderBuilder::compute_blame_state_root_incremental(
778 roots[i],
779 accumulated_root,
780 );
781 }
782 accumulated_root
783 }
784
785 pub fn compute_blame_state_root_incremental(
786 first_root: H256, remaining_root: H256,
787 ) -> H256 {
788 let mut buffer = Vec::with_capacity(H256::len_bytes() * 2);
789 buffer.extend_from_slice(first_root.as_bytes());
790 buffer.extend_from_slice(remaining_root.as_bytes());
791 keccak(&buffer)
792 }
793}
794
795impl Encodable for BlockHeader {
796 fn rlp_append(&self, stream: &mut RlpStream) { self.stream_rlp(stream); }
797}
798
799impl Decodable for BlockHeader {
800 fn decode(r: &Rlp) -> Result<Self, DecoderError> {
801 let rlp_size = r.as_raw().len();
802 let mut rlp_part = BlockHeaderRlpPart {
803 parent_hash: r.val_at(0)?,
804 height: r.val_at(1)?,
805 timestamp: r.val_at(2)?,
806 author: r.val_at(3)?,
807 transactions_root: r.val_at(4)?,
808 deferred_state_root: r.val_at(5)?,
809 deferred_receipts_root: r.val_at(6)?,
810 deferred_logs_bloom_hash: r.val_at(7)?,
811 blame: r.val_at(8)?,
812 difficulty: r.val_at(9)?,
813 adaptive: r.val_at::<u8>(10)? == 1,
814 gas_limit: r.val_at(11)?,
815 referee_hashes: r.list_at(12)?,
816 custom: CustomData::default(),
817 nonce: r.val_at(13)?,
818 pos_reference: r.val_at(14).unwrap_or(None),
819 base_price: r.val_at(15).unwrap_or(None),
820 };
821 let custom_start = 14
822 + rlp_part.pos_reference.is_some() as usize
823 + rlp_part.base_price.is_some() as usize;
824 rlp_part.custom =
825 CustomData::from_rlp(r, custom_start, rlp_part.height)?;
826
827 let mut header = BlockHeader {
828 rlp_part,
829 hash: None,
830 pow_hash: None,
831 approximated_rlp_size: rlp_size,
832 };
833 header.compute_hash();
834
835 Ok(header)
836 }
837}
838
839#[derive(Clone, Copy, Debug, Eq, RlpDecodable, RlpEncodable, PartialEq)]
840pub struct BasePrice {
841 pub core_base_price: U256,
842 pub espace_base_price: U256,
843}
844#[cfg(test)]
845mod tests {
846 use super::BlockHeaderBuilder;
847 use crate::{
848 hash::keccak,
849 receipt::{BlockReceipts, Receipt},
850 TransactionStatus,
851 };
852 use cfx_types::{Bloom, KECCAK_EMPTY_BLOOM, U256};
853 use std::{str::FromStr, sync::Arc};
854
855 #[test]
856 fn test_logs_bloom_hash_no_receipts() {
857 let receipts = vec![]; let hash = BlockHeaderBuilder::compute_block_logs_bloom_hash(&receipts);
859 assert_eq!(hash, KECCAK_EMPTY_BLOOM);
860
861 let receipts: Vec<Arc<BlockReceipts>> = (1..11)
862 .map(|_| {
863 Arc::new(BlockReceipts {
864 receipts: vec![],
865 block_number: 0,
866 secondary_reward: U256::zero(),
867 tx_execution_error_messages: vec![],
868 })
869 })
870 .collect();
871 let hash = BlockHeaderBuilder::compute_block_logs_bloom_hash(&receipts);
872 assert_eq!(hash, KECCAK_EMPTY_BLOOM);
873 }
874
875 #[test]
876 fn test_logs_bloom_hash_empty_receipts() {
877 let receipt = Receipt {
878 accumulated_gas_used: U256::zero(),
879 gas_fee: U256::zero(),
880 gas_sponsor_paid: false,
881 logs: vec![],
882 outcome_status: TransactionStatus::Success,
883 log_bloom: Bloom::zero(),
884 storage_sponsor_paid: false,
885 storage_collateralized: vec![],
886 storage_released: vec![],
887 burnt_gas_fee: None,
888 };
889
890 let receipts: Vec<Arc<BlockReceipts>> = (1..11)
892 .map(|_| {
893 Arc::new(BlockReceipts {
894 receipts: (1..11).map(|_| receipt.clone()).collect(),
895 block_number: 0,
896 secondary_reward: U256::zero(),
897 tx_execution_error_messages: vec!["".into(); 10],
898 })
899 })
900 .collect();
901 let hash = BlockHeaderBuilder::compute_block_logs_bloom_hash(&receipts);
902 assert_eq!(hash, KECCAK_EMPTY_BLOOM);
903 }
904
905 #[test]
906 fn test_logs_bloom_hash() {
907 let block1 = BlockReceipts {
908 receipts: vec![
909 Receipt {
910 accumulated_gas_used: 0.into(),
911 gas_fee: 0.into(),
912 gas_sponsor_paid: false,
913 logs: vec![],
914 outcome_status: TransactionStatus::Success,
915 log_bloom: Bloom::from_str(
916 "11111111111111111111111111111111\
917 00000000000000000000000000000000\
918 00000000000000000000000000000000\
919 00000000000000000000000000000000\
920 00000000000000000000000000000000\
921 00000000000000000000000000000000\
922 00000000000000000000000000000000\
923 00000000000000000000000000000000\
924 00000000000000000000000000000000\
925 00000000000000000000000000000000\
926 00000000000000000000000000000000\
927 00000000000000000000000000000000\
928 00000000000000000000000000000000\
929 00000000000000000000000000000000\
930 00000000000000000000000000000000\
931 00000000000000000000000000000000",
932 )
933 .unwrap(),
934 storage_sponsor_paid: false,
935 storage_collateralized: vec![],
936 storage_released: vec![],
937 burnt_gas_fee: None,
938 },
939 Receipt {
940 accumulated_gas_used: U256::zero(),
941 gas_fee: U256::zero(),
942 gas_sponsor_paid: false,
943 logs: vec![],
944 outcome_status: TransactionStatus::Success,
945 log_bloom: Bloom::from_str(
946 "00000000000000000000000000000000\
947 22222222222222222222222222222222\
948 00000000000000000000000000000000\
949 00000000000000000000000000000000\
950 00000000000000000000000000000000\
951 00000000000000000000000000000000\
952 00000000000000000000000000000000\
953 00000000000000000000000000000000\
954 00000000000000000000000000000000\
955 00000000000000000000000000000000\
956 00000000000000000000000000000000\
957 00000000000000000000000000000000\
958 00000000000000000000000000000000\
959 00000000000000000000000000000000\
960 00000000000000000000000000000000\
961 00000000000000000000000000000000",
962 )
963 .unwrap(),
964 storage_sponsor_paid: false,
965 storage_collateralized: vec![],
966 storage_released: vec![],
967 burnt_gas_fee: None,
968 },
969 ],
970 block_number: 0,
971 secondary_reward: U256::zero(),
972 tx_execution_error_messages: vec!["".into(); 2],
973 };
974
975 let block2 = BlockReceipts {
976 receipts: vec![Receipt {
977 accumulated_gas_used: U256::zero(),
978 gas_fee: U256::zero(),
979 gas_sponsor_paid: false,
980 logs: vec![],
981 outcome_status: TransactionStatus::Success,
982 log_bloom: Bloom::from_str(
983 "44444444444444440000000000000000\
984 44444444444444440000000000000000\
985 44444444444444440000000000000000\
986 44444444444444440000000000000000\
987 00000000000000000000000000000000\
988 00000000000000000000000000000000\
989 00000000000000000000000000000000\
990 00000000000000000000000000000000\
991 00000000000000000000000000000000\
992 00000000000000000000000000000000\
993 00000000000000000000000000000000\
994 00000000000000000000000000000000\
995 00000000000000000000000000000000\
996 00000000000000000000000000000000\
997 00000000000000000000000000000000\
998 00000000000000000000000000000000",
999 )
1000 .unwrap(),
1001 storage_sponsor_paid: false,
1002 storage_collateralized: vec![],
1003 storage_released: vec![],
1004 burnt_gas_fee: None,
1005 }],
1006 block_number: 0,
1007 secondary_reward: U256::zero(),
1008 tx_execution_error_messages: vec!["".into()],
1009 };
1010
1011 let expected = keccak(
1012 "55555555555555551111111111111111\
1013 66666666666666662222222222222222\
1014 44444444444444440000000000000000\
1015 44444444444444440000000000000000\
1016 00000000000000000000000000000000\
1017 00000000000000000000000000000000\
1018 00000000000000000000000000000000\
1019 00000000000000000000000000000000\
1020 00000000000000000000000000000000\
1021 00000000000000000000000000000000\
1022 00000000000000000000000000000000\
1023 00000000000000000000000000000000\
1024 00000000000000000000000000000000\
1025 00000000000000000000000000000000\
1026 00000000000000000000000000000000\
1027 00000000000000000000000000000000"
1028 .parse::<Bloom>()
1029 .unwrap(),
1030 );
1031
1032 let receipts = vec![Arc::new(block1), Arc::new(block2)];
1033 let hash = BlockHeaderBuilder::compute_block_logs_bloom_hash(&receipts);
1034 assert_eq!(hash, expected);
1035 }
1036
1037 use super::{BlockHeader, CIP112_TRANSITION_HEIGHT};
1038 use crate::bytes::Bytes;
1039 use rlp::{Decodable, Rlp};
1040
1041 const CIP112: u64 = 1000;
1044
1045 fn init_cip112() { CIP112_TRANSITION_HEIGHT.get_or_init(|| CIP112); }
1046
1047 fn header_with_custom(height: u64, custom: Vec<Bytes>) -> BlockHeader {
1048 init_cip112();
1049 BlockHeaderBuilder::new()
1050 .with_height(height)
1051 .with_custom(custom)
1052 .build()
1053 }
1054
1055 fn assert_roundtrip(height: u64, custom: Vec<Bytes>) {
1058 let header = header_with_custom(height, custom.clone());
1059 let encoded = header.rlp();
1060
1061 let decoded = BlockHeader::decode(&Rlp::new(&encoded)).unwrap();
1062 assert_eq!(decoded.rlp(), encoded, "re-encoding must be identical");
1063 assert_eq!(decoded.hash(), header.hash(), "hash must be preserved");
1064
1065 assert_eq!(decoded.custom_count(), custom.len());
1066 assert_eq!(decoded.custom_items(), custom);
1067 assert_eq!(
1068 decoded.custom_data_len(),
1069 custom.iter().map(|x| x.len()).sum::<usize>()
1070 );
1071 for (i, item) in custom.iter().enumerate() {
1072 assert_eq!(decoded.custom_item(i).as_ref(), Some(item));
1073 }
1074 assert_eq!(decoded.custom_item(custom.len()), None);
1075 }
1076
1077 #[test]
1078 fn custom_roundtrip_post_cip112() {
1079 assert_roundtrip(
1080 CIP112 + 5,
1081 vec![vec![1u8, 2, 3], vec![], vec![0xab; 40], vec![0x42]],
1082 );
1083 }
1084
1085 #[test]
1086 fn custom_roundtrip_empty_post_cip112() {
1087 assert_roundtrip(CIP112 + 5, vec![]);
1088 }
1089
1090 #[test]
1091 fn custom_roundtrip_pre_cip112() {
1092 let items = vec![
1094 rlp::encode(&vec![1u8, 2, 3]).to_vec(),
1095 rlp::encode(&Vec::<u8>::new()).to_vec(),
1096 rlp::encode(&vec![0xcd_u8; 30]).to_vec(),
1097 ];
1098 assert_roundtrip(CIP112 - 5, items);
1099 }
1100
1101 #[test]
1102 fn custom_many_empty_items_no_amplification() {
1103 let n = 5000usize;
1104 let header = header_with_custom(CIP112 + 5, vec![Vec::new(); n]);
1105 let encoded = header.rlp();
1106
1107 let decoded = BlockHeader::decode(&Rlp::new(&encoded)).unwrap();
1108 assert_eq!(decoded.custom_count(), n);
1109 assert_eq!(decoded.custom_data_len(), 0);
1110 assert_eq!(decoded.custom.raw.len(), n);
1112 assert_eq!(decoded.rlp(), encoded);
1113 assert_eq!(decoded.hash(), header.hash());
1114 }
1115
1116 #[test]
1117 fn custom_roundtrip_with_pow_hash() {
1118 init_cip112();
1119 let custom = vec![vec![9u8, 8, 7], vec![], vec![0x11; 33]];
1120 let mut header = BlockHeaderBuilder::new()
1121 .with_height(CIP112 + 5)
1122 .with_custom(custom.clone())
1123 .build();
1124 header.pow_hash = Some(crate::hash::keccak(b"pow"));
1125
1126 let mut stream = rlp::RlpStream::new();
1127 header.stream_rlp_with_pow_hash(&mut stream);
1128 let encoded = stream.out().to_vec();
1129
1130 let decoded = BlockHeader::decode_with_pow_hash(&encoded).unwrap();
1131 assert_eq!(decoded.custom_items(), custom);
1132 assert_eq!(decoded.pow_hash, header.pow_hash);
1133
1134 let mut stream2 = rlp::RlpStream::new();
1135 decoded.stream_rlp_with_pow_hash(&mut stream2);
1136 assert_eq!(stream2.out().to_vec(), encoded);
1137 }
1138
1139 #[test]
1146 fn custom_empty_header_nested_in_compact_block() {
1147 use crate::block::CompactBlock;
1148 use cfx_types::H256;
1149 init_cip112();
1150 for (height, custom) in [(1u64, vec![vec![1u8]]), (2u64, vec![])] {
1151 let header = BlockHeaderBuilder::new()
1152 .with_height(height)
1153 .with_custom(custom)
1154 .with_pos_reference(Some(H256::zero()))
1155 .build();
1156 let cb = CompactBlock {
1157 block_header: header,
1158 nonce: 0,
1159 tx_short_ids: vec![],
1160 reconstructed_txns: vec![],
1161 };
1162 let enc = rlp::encode(&cb);
1163 CompactBlock::decode(&Rlp::new(&enc)).unwrap_or_else(|e| {
1164 panic!("CompactBlock decode (height={height}): {e:?}")
1165 });
1166 }
1167 }
1168}