blockgen/
test_api.rs

1use cfx_parameters::consensus::GENESIS_GAS_LIMIT;
2use cfx_types::{H256, U256};
3
4use cfxcore::pow::{ProofOfWorkProblem, ProofOfWorkSolution};
5use log::debug;
6
7use primitives::*;
8use std::{ops::Deref, sync::Arc, thread, time::Duration};
9
10use crate::BlockGenerator;
11
12pub struct BlockGeneratorTestApi(Arc<BlockGenerator>);
13
14// Generate Block APIs for test only
15impl BlockGeneratorTestApi {
16    pub(crate) fn new(bg: Arc<BlockGenerator>) -> Self {
17        BlockGeneratorTestApi(bg)
18    }
19
20    pub fn auto_block_generation(&self, interval_ms: u64) {
21        let interval = Duration::from_millis(interval_ms);
22        while self.is_running() {
23            if !self.sync.catch_up_mode() {
24                let block =
25                    self.assembler.assemble_new_mining_block(Some(3000));
26                self.generate_block_impl(block);
27            }
28            thread::sleep(interval);
29        }
30    }
31
32    // This function is used in test only to simulate attacker behavior.
33    pub fn generate_fixed_block(
34        &self, parent_hash: H256, referee: Vec<H256>, num_txs: usize,
35        difficulty: u64, adaptive: bool, pos_reference: Option<H256>,
36    ) -> Result<H256, String> {
37        let block = self.assembler.assemble_new_fixed_block(
38            parent_hash,
39            referee,
40            num_txs,
41            difficulty,
42            adaptive,
43            GENESIS_GAS_LIMIT,
44            pos_reference,
45        )?;
46        Ok(self.generate_block_impl(block))
47    }
48
49    /// Generate a block with transactions in the pool
50    /// This is used for testing only
51    pub fn generate_block(
52        &self, num_txs: usize, block_size_limit: usize,
53        additional_transactions: Vec<Arc<SignedTransaction>>,
54    ) -> H256 {
55        let block = self.assembler.assemble_new_block(
56            num_txs,
57            block_size_limit,
58            additional_transactions,
59        );
60        self.generate_block_impl(block)
61    }
62
63    /// Generate a block with transactions in the pool.
64    /// This is used for testing only
65    pub fn generate_block_with_blame_info(
66        &self, num_txs: usize, block_size_limit: usize,
67        additional_transactions: Vec<Arc<SignedTransaction>>,
68        blame: Option<u32>, state_root: Option<H256>,
69        receipts_root: Option<H256>, logs_bloom_hash: Option<H256>,
70    ) -> H256 {
71        let block = self.assembler.assemble_new_block_with_blame_info(
72            num_txs,
73            block_size_limit,
74            additional_transactions,
75            blame,
76            state_root,
77            receipts_root,
78            logs_bloom_hash,
79        );
80        self.generate_block_impl(block)
81    }
82
83    pub fn generate_custom_block(
84        &self, transactions: Vec<Arc<SignedTransaction>>,
85        adaptive: Option<bool>,
86    ) -> H256 {
87        let block =
88            self.assembler.assemble_custom_block(transactions, adaptive);
89
90        self.generate_block_impl(block)
91    }
92
93    pub fn generate_custom_block_with_parent(
94        &self, parent_hash: H256, referee: Vec<H256>,
95        transactions: Vec<Arc<SignedTransaction>>, adaptive: bool,
96        maybe_custom: Option<Vec<Vec<u8>>>,
97    ) -> Result<H256, String> {
98        let block = self.assembler.assemble_custom_block_with_parent(
99            parent_hash,
100            referee,
101            transactions,
102            adaptive,
103            maybe_custom,
104        )?;
105
106        Ok(self.generate_block_impl(block))
107    }
108
109    pub fn generate_block_with_nonce_and_timestamp(
110        &self, parent_hash: H256, referee: Vec<H256>,
111        transactions: Vec<Arc<SignedTransaction>>, nonce: U256, timestamp: u64,
112        adaptive: bool,
113    ) -> Result<H256, String> {
114        let block = self.assembler.assemble_block_with_nonce_and_timestamp(
115            parent_hash,
116            referee,
117            transactions,
118            nonce,
119            timestamp,
120            adaptive,
121        )?;
122
123        Ok(self.generate_block_impl(block))
124    }
125
126    fn generate_block_impl(&self, block_init: Block) -> H256 {
127        let mut block = block_init;
128        let difficulty = block.block_header.difficulty();
129        let problem = ProofOfWorkProblem::new(
130            block.block_header.height(),
131            block.block_header.problem_hash(),
132            *difficulty,
133        );
134        let mut nonce: u64 = rand::random();
135        loop {
136            if self.pow.validate(
137                &problem,
138                &ProofOfWorkSolution {
139                    nonce: U256::from(nonce),
140                },
141            ) {
142                block.block_header.set_nonce(U256::from(nonce));
143                break;
144            }
145            nonce += 1;
146        }
147        let hash = block.block_header.compute_hash();
148        debug!(
149            "generate_block with block header:{:?} tx_number:{}, block_size:{}",
150            block.block_header,
151            block.transactions.len(),
152            block.size(),
153        );
154        self.on_mined_block(block);
155
156        debug!("generate_block finished on_mined_block()");
157        // FIXME: We should add a flag to enable/disable this wait
158        // Ensure that when `generate**` function returns, the block has been
159        // handled by Consensus This order is assumed by some tests, and
160        // this function is also only used in tests.
161        self.consensus.wait_for_generation(&hash);
162        debug!("generate_block finished wait_for_generation()");
163
164        hash
165    }
166}
167
168impl Deref for BlockGeneratorTestApi {
169    type Target = BlockGenerator;
170
171    fn deref(&self) -> &Self::Target { &*self.0 }
172}