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
14impl 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 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 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 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 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}