primitives/
block_header.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5mod 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;
30/// The height to start fixing the wrong encoding/decoding of the `custom`
31/// field.
32pub static CIP112_TRANSITION_HEIGHT: OnceCell<u64> = OnceCell::new();
33
34pub const BASE_PRICE_CHANGE_DENOMINATOR: usize = 8;
35
36/// Block-header `custom` fields as one raw-RLP blob instead of a `Vec<Bytes>`,
37/// so a peer header packed with tiny RLP items can't amplify into a per-item
38/// allocation (remote OOM). `raw` is re-emitted verbatim via
39/// `append_raw(&raw, count)`, byte-identical to the old encoding — block hashes
40/// unchanged, no hardfork.
41#[derive(Clone, Debug, Eq, PartialEq, Default)]
42pub struct CustomData {
43    raw: Bytes,
44    count: usize,
45    /// Old per-item length sum (raw len pre-CIP112, content len post-CIP112).
46    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    /// Byte-for-byte reproduces the old decode: post-CIP112 decode then
80    /// canonically re-encode; pre-CIP112 keep raw RLP verbatim.
81    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            // Re-encode each item canonically, reusing one stream (its buffer
95            // survives `clear`) so a header with many items can't force a fresh
96            // allocation per item.
97            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        // `raw` is always a concatenation of valid RLP items, so this never
140        // fails; assert it to catch a construction bug in tests.
141        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.
157    parent_hash: H256,
158    /// Block height
159    height: BlockHeight,
160    /// Block timestamp.
161    timestamp: u64,
162    /// Block author.
163    author: Address,
164    /// Transactions root.
165    transactions_root: H256,
166    /// Deferred state root.
167    deferred_state_root: H256,
168    /// Deferred block receipts root.
169    deferred_receipts_root: H256,
170    /// Deferred block logs bloom hash.
171    deferred_logs_bloom_hash: H256,
172    /// Blame indicates the number of ancestors whose
173    /// state_root/receipts_root/logs_bloom_hash/blame are not correct.
174    /// It acts as a vote to help light client determining the
175    /// state_root/receipts_root/logs_bloom_hash are correct or not.
176    blame: u32,
177    /// Block difficulty.
178    difficulty: U256,
179    /// Whether it is an adaptive block (from GHAST algorithm)
180    adaptive: bool,
181    /// Gas limit.
182    gas_limit: U256,
183    /// Referee hashes
184    referee_hashes: Vec<H256>,
185    /// Customized information
186    custom: CustomData,
187    /// Nonce of the block
188    nonce: U256,
189    /// Referred PoS block ID.
190    pos_reference: Option<H256>,
191    /// `[core_space_base_price, espace_base_price]`.
192    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/// A block header.
217#[derive(Clone, Debug, Eq)]
218pub struct BlockHeader {
219    rlp_part: BlockHeaderRlpPart,
220    /// Hash of the block
221    hash: Option<H256>,
222    /// POW quality of the block
223    pub pow_hash: Option<H256>,
224    /// Approximated rlp size of the block header
225    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    /// Approximated rlp size of the block header.
250    pub fn approximated_rlp_size(&self) -> usize { self.approximated_rlp_size }
251
252    /// Get the parent_hash field of the header.
253    pub fn parent_hash(&self) -> &H256 { &self.parent_hash }
254
255    /// Get the block height
256    pub fn height(&self) -> u64 { self.height }
257
258    /// Get the timestamp field of the header.
259    pub fn timestamp(&self) -> u64 { self.timestamp }
260
261    /// Get the author field of the header.
262    pub fn author(&self) -> &Address { &self.author }
263
264    /// Get the transactions root field of the header.
265    pub fn transactions_root(&self) -> &H256 { &self.transactions_root }
266
267    /// Get the deferred state root field of the header.
268    pub fn deferred_state_root(&self) -> &H256 { &self.deferred_state_root }
269
270    /// Get the deferred block receipts root field of the header.
271    pub fn deferred_receipts_root(&self) -> &H256 {
272        &self.deferred_receipts_root
273    }
274
275    /// Get the deferred block logs bloom hash field of the header.
276    pub fn deferred_logs_bloom_hash(&self) -> &H256 {
277        &self.deferred_logs_bloom_hash
278    }
279
280    /// Get the blame field of the header
281    pub fn blame(&self) -> u32 { self.blame }
282
283    /// Get the difficulty field of the header.
284    pub fn difficulty(&self) -> &U256 { &self.difficulty }
285
286    /// Get the adaptive field of the header
287    pub fn adaptive(&self) -> bool { self.adaptive }
288
289    /// Get the gas limit field of the header.
290    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    /// Get the referee hashes field of the header.
304    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    /// O(idx) — walks from the start of the blob; for multi-item access prefer
311    /// `custom_items()`. Bounded, so it can't be forced to materialise a huge
312    /// header.
313    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    /// For already-validated headers only (e.g. RPC).
319    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            // `raw_item` is canonical RLP we produced, so `data()` can't fail.
333            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    /// Get the nonce field of the header.
343    pub fn nonce(&self) -> U256 { self.nonce }
344
345    /// Get the PoS reference.
346    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    // Get the base price for the given space after 1559 hardfork.
358    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    /// Set the nonce field of the header.
366    pub fn set_nonce(&mut self, nonce: U256) { self.nonce = nonce; }
367
368    /// Set the timestamp filed of the header.
369    pub fn set_timestamp(&mut self, timestamp: u64) {
370        self.timestamp = timestamp;
371    }
372
373    /// Set the custom filed of the header.
374    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    /// Compute the hash of the block.
380    pub fn compute_hash(&mut self) -> H256 {
381        let hash = self.hash();
382        self.hash = Some(hash);
383        hash
384    }
385
386    /// Get the hash of the block.
387    pub fn hash(&self) -> H256 {
388        self.hash.unwrap_or_else(|| keccak(self.rlp()))
389    }
390
391    /// Get the hash of PoW problem.
392    pub fn problem_hash(&self) -> H256 { keccak(self.rlp_without_nonce()) }
393
394    /// Get the RLP representation of this header(except nonce).
395    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    /// Get the RLP representation of this header.
402    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    /// Place this header(except nonce) into an RLP stream `stream`.
409    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        // Skip when empty: appending `append_raw(&[], 0)` after the header
438        // list has already finished would clear the stream's `finished_list`
439        // flag, double-counting the header when it is nested in a parent list
440        // (e.g. CompactBlock/Block) and truncating that list on decode.
441        if self.custom.count > 0 {
442            stream.append_raw(&self.custom.raw, self.custom.count);
443        }
444    }
445
446    /// Place this header into an RLP stream `stream`.
447    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        // Guard empty custom; see `stream_rlp_without_nonce`.
477        if self.custom.count > 0 {
478            stream.append_raw(&self.custom.raw, self.custom.count);
479        }
480    }
481
482    /// Place this header and its `pow_hash` into an RLP stream `stream`.
483    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            // Just encode the Option for future compatibility.
507            // It should always be Some when it is being inserted to db.
508            .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        // Guard empty custom; see `stream_rlp_without_nonce`.
517        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        // FIXME: We need to revisit the size of block header once we finished
563        // the persistent storage part
564        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![]; // Vec<_>
858        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        // 10 blocks with 10 empty receipts each
891        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    // CIP112_TRANSITION_HEIGHT is a process-global OnceCell, shared by all
1042    // tests.
1043    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    /// Decode→re-encode is byte-identical (hash preserved) and items
1056    /// round-trip.
1057    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        // Pre-CIP112 items are raw RLP verbatim, so feed encoded byte strings.
1093        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        // One byte (0x80) per empty item — no per-item Vec overhead.
1111        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    /// A header nested in a `CompactBlock`/`Block` must round-trip even with
1140    /// empty custom: a trailing `append_raw(&[], 0)` used to clobber the RLP
1141    /// stream's `finished_list` flag, double-counting the header in the parent
1142    /// list and truncating it (`RlpIsTooShort` on decode). Standalone
1143    /// `header.rlp()` hides this (no enclosing list), so it needs the nested
1144    /// case.
1145    #[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}