1mod assembler;
5mod mine_session;
6mod miner;
7mod test_api;
8
9pub use crate::test_api::BlockGeneratorTestApi;
10
11use crate::{
12 assembler::BlockAssembler, mine_session::MiningSession, miner::MineWorker,
13};
14
15use cfx_types::Address;
16use cfxcore::{
17 consensus::pos_handler::PosVerifier, pow::*, ConsensusGraph,
18 SharedSynchronizationGraph, SharedSynchronizationService,
19 SharedTransactionPool, Stopable,
20};
21use parking_lot::RwLock;
22use primitives::Block;
23use std::sync::{mpsc, Arc};
24use txgen::SharedTransactionGenerator;
25
26enum MiningStatus {
27 Start,
28 Stop,
29}
30
31type SolutionReceiver = mpsc::Receiver<ProofOfWorkSolution>;
32
33pub struct BlockGenerator {
35 pub(crate) pow_config: ProofOfWorkConfig,
36 pub(crate) pow: Arc<PowComputer>,
37 consensus: Arc<ConsensusGraph>,
38 sync: SharedSynchronizationService,
39 status: RwLock<MiningStatus>,
40 assembler: BlockAssembler,
41}
42
43impl BlockGenerator {
44 #[allow(clippy::too_many_arguments)]
45 pub fn new(
46 graph: SharedSynchronizationGraph, txpool: SharedTransactionPool,
47 sync: SharedSynchronizationService,
48 maybe_txgen: Option<SharedTransactionGenerator>,
49 pow_config: ProofOfWorkConfig, pow: Arc<PowComputer>,
50 mining_author: Address, pos_verifier: Arc<PosVerifier>,
51 ) -> Self {
52 let consensus = graph.consensus.clone();
53 let assembler = BlockAssembler::new(
54 graph,
55 txpool,
56 maybe_txgen,
57 mining_author,
58 pos_verifier,
59 );
60 BlockGenerator {
61 pow_config,
62 pow,
63 consensus,
64 sync,
65 assembler,
66 status: RwLock::new(MiningStatus::Start),
67 }
68 }
69
70 fn is_running(&self) -> bool {
71 matches!(*self.status.read(), MiningStatus::Start)
72 }
73
74 pub fn stop(&self) {
76 {
77 let mut write = self.status.write();
78 *write = MiningStatus::Stop;
79 }
80 self.assembler.stop();
81 }
82
83 fn on_mined_block(&self, block: Block) {
85 self.sync.on_mined_block(block).ok();
87 }
88
89 pub fn test_api(self: &Arc<Self>) -> BlockGeneratorTestApi {
90 BlockGeneratorTestApi::new(self.clone())
91 }
92
93 pub fn mine(self: &Arc<Self>) {
94 let miner_type = if self.pow_config.use_stratum() {
95 miner::MinerType::Stratum
96 } else {
97 miner::MinerType::Cpu(1)
98 };
99
100 let (miner, solution_rx) = miner::spawn(self.clone(), miner_type);
101
102 MiningSession::new(self, &*miner, solution_rx).run();
103 }
104}
105
106impl Stopable for BlockGenerator {
107 fn stop(&self) { BlockGenerator::stop(self) }
108}