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 pub fn generate_block_with_blame_info(
67 &self, num_txs: usize, block_size_limit: usize,
68 additional_transactions: Vec<Arc<SignedTransaction>>,
69 blame: Option<u32>, state_root: Option<H256>,
70 receipts_root: Option<H256>, logs_bloom_hash: Option<H256>,
71 ) -> H256 {
72 let block = self.assembler.assemble_new_block_with_blame_info(
73 num_txs,
74 block_size_limit,
75 additional_transactions,
76 blame,
77 state_root,
78 receipts_root,
79 logs_bloom_hash,
80 );
81 self.generate_block_impl(block)
82 }
83
84 pub fn generate_custom_block(
85 &self, transactions: Vec<Arc<SignedTransaction>>,
86 adaptive: Option<bool>,
87 ) -> H256 {
88 let block =
89 self.assembler.assemble_custom_block(transactions, adaptive);
90
91 self.generate_block_impl(block)
92 }
93
94 pub fn generate_custom_block_with_parent(
95 &self, parent_hash: H256, referee: Vec<H256>,
96 transactions: Vec<Arc<SignedTransaction>>, adaptive: bool,
97 maybe_custom: Option<Vec<Vec<u8>>>,
98 ) -> Result<H256, String> {
99 let block = self.assembler.assemble_custom_block_with_parent(
100 parent_hash,
101 referee,
102 transactions,
103 adaptive,
104 maybe_custom,
105 )?;
106
107 Ok(self.generate_block_impl(block))
108 }
109
110 pub fn generate_block_with_nonce_and_timestamp(
111 &self, parent_hash: H256, referee: Vec<H256>,
112 transactions: Vec<Arc<SignedTransaction>>, nonce: U256, timestamp: u64,
113 adaptive: bool,
114 ) -> Result<H256, String> {
115 let block = self.assembler.assemble_block_with_nonce_and_timestamp(
116 parent_hash,
117 referee,
118 transactions,
119 nonce,
120 timestamp,
121 adaptive,
122 )?;
123
124 Ok(self.generate_block_impl(block))
125 }
126
127 fn generate_block_impl(&self, block_init: Block) -> H256 {
128 let mut block = block_init;
129 let difficulty = block.block_header.difficulty();
130 let problem = ProofOfWorkProblem::new(
131 block.block_header.height(),
132 block.block_header.problem_hash(),
133 *difficulty,
134 );
135 let mut nonce: u64 = rand::random();
136 loop {
137 if self.pow.validate(
138 &problem,
139 &ProofOfWorkSolution {
140 nonce: U256::from(nonce),
141 },
142 ) {
143 block.block_header.set_nonce(U256::from(nonce));
144 break;
145 }
146 nonce += 1;
147 }
148 let hash = block.block_header.compute_hash();
149 debug!(
150 "generate_block with block header:{:?} tx_number:{}, block_size:{}",
151 block.block_header,
152 block.transactions.len(),
153 block.size(),
154 );
155 self.on_mined_block(block);
156
157 debug!("generate_block finished on_mined_block()");
158 self.consensus.wait_for_generation(&hash);
163 debug!("generate_block finished wait_for_generation()");
164
165 hash
166 }
167}
168
169impl Deref for BlockGeneratorTestApi {
170 type Target = BlockGenerator;
171
172 fn deref(&self) -> &Self::Target { &*self.0 }
173}