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
12#[derive(Clone)]
13pub struct BlockGeneratorTestApi(Arc<BlockGenerator>);
14
15impl BlockGeneratorTestApi {
17 pub(crate) fn new(bg: Arc<BlockGenerator>) -> Self {
18 BlockGeneratorTestApi(bg)
19 }
20
21 pub fn auto_block_generation(&self, interval_ms: u64) {
22 let interval = Duration::from_millis(interval_ms);
23 while self.is_running() {
24 if !self.sync.catch_up_mode() {
25 let block =
26 self.assembler.assemble_new_mining_block(Some(3000));
27 self.generate_block_impl(block);
28 }
29 thread::sleep(interval);
30 }
31 }
32
33 pub fn generate_fixed_block(
35 &self, parent_hash: H256, referee: Vec<H256>, num_txs: usize,
36 difficulty: u64, adaptive: bool, pos_reference: Option<H256>,
37 ) -> Result<H256, String> {
38 let block = self.assembler.assemble_new_fixed_block(
39 parent_hash,
40 referee,
41 num_txs,
42 difficulty,
43 adaptive,
44 GENESIS_GAS_LIMIT,
45 pos_reference,
46 )?;
47 Ok(self.generate_block_impl(block))
48 }
49
50 pub fn generate_block(
53 &self, num_txs: usize, block_size_limit: usize,
54 additional_transactions: Vec<Arc<SignedTransaction>>,
55 ) -> H256 {
56 let block = self.assembler.assemble_new_block(
57 num_txs,
58 block_size_limit,
59 additional_transactions,
60 );
61 self.generate_block_impl(block)
62 }
63
64 #[allow(clippy::too_many_arguments)]
67 pub fn generate_block_with_blame_info(
68 &self, num_txs: usize, block_size_limit: usize,
69 additional_transactions: Vec<Arc<SignedTransaction>>,
70 blame: Option<u32>, state_root: Option<H256>,
71 receipts_root: Option<H256>, logs_bloom_hash: Option<H256>,
72 ) -> H256 {
73 let block = self.assembler.assemble_new_block_with_blame_info(
74 num_txs,
75 block_size_limit,
76 additional_transactions,
77 blame,
78 state_root,
79 receipts_root,
80 logs_bloom_hash,
81 );
82 self.generate_block_impl(block)
83 }
84
85 pub fn generate_custom_block(
86 &self, transactions: Vec<Arc<SignedTransaction>>,
87 adaptive: Option<bool>,
88 ) -> H256 {
89 let block =
90 self.assembler.assemble_custom_block(transactions, adaptive);
91
92 self.generate_block_impl(block)
93 }
94
95 pub fn generate_custom_block_with_parent(
96 &self, parent_hash: H256, referee: Vec<H256>,
97 transactions: Vec<Arc<SignedTransaction>>, adaptive: bool,
98 maybe_custom: Option<Vec<Vec<u8>>>,
99 ) -> Result<H256, String> {
100 let block = self.assembler.assemble_custom_block_with_parent(
101 parent_hash,
102 referee,
103 transactions,
104 adaptive,
105 maybe_custom,
106 )?;
107
108 Ok(self.generate_block_impl(block))
109 }
110
111 pub fn generate_block_with_nonce_and_timestamp(
112 &self, parent_hash: H256, referee: Vec<H256>,
113 transactions: Vec<Arc<SignedTransaction>>, nonce: U256, timestamp: u64,
114 adaptive: bool,
115 ) -> Result<H256, String> {
116 let block = self.assembler.assemble_block_with_nonce_and_timestamp(
117 parent_hash,
118 referee,
119 transactions,
120 nonce,
121 timestamp,
122 adaptive,
123 )?;
124
125 Ok(self.generate_block_impl(block))
126 }
127
128 fn generate_block_impl(&self, block_init: Block) -> H256 {
129 let mut block = block_init;
130 let difficulty = block.block_header.difficulty();
131 let problem = ProofOfWorkProblem::new(
132 block.block_header.height(),
133 block.block_header.problem_hash(),
134 *difficulty,
135 );
136 let mut nonce: u64 = rand::random();
137 loop {
138 if self.pow.validate(
139 &problem,
140 &ProofOfWorkSolution {
141 nonce: U256::from(nonce),
142 },
143 ) {
144 block.block_header.set_nonce(U256::from(nonce));
145 break;
146 }
147 nonce += 1;
148 }
149 let hash = block.block_header.compute_hash();
150 debug!(
151 "generate_block with block header:{:?} tx_number:{}, block_size:{}",
152 block.block_header,
153 block.transactions.len(),
154 block.size(),
155 );
156 self.on_mined_block(block);
157
158 debug!("generate_block finished on_mined_block()");
159 self.consensus.wait_for_generation(&hash);
164 debug!("generate_block finished wait_for_generation()");
165
166 hash
167 }
168}
169
170impl Deref for BlockGeneratorTestApi {
171 type Target = BlockGenerator;
172
173 fn deref(&self) -> &Self::Target { &self.0 }
174}