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 pub fn new(
45 graph: SharedSynchronizationGraph, txpool: SharedTransactionPool,
46 sync: SharedSynchronizationService,
47 maybe_txgen: Option<SharedTransactionGenerator>,
48 pow_config: ProofOfWorkConfig, pow: Arc<PowComputer>,
49 mining_author: Address, pos_verifier: Arc<PosVerifier>,
50 ) -> Self {
51 let consensus = graph.consensus.clone();
52 let assembler = BlockAssembler::new(
53 graph,
54 txpool,
55 maybe_txgen,
56 mining_author,
57 pos_verifier,
58 );
59 BlockGenerator {
60 pow_config,
61 pow,
62 consensus,
63 sync,
64 assembler,
65 status: RwLock::new(MiningStatus::Start),
66 }
67 }
68
69 fn is_running(&self) -> bool {
70 matches!(*self.status.read(), MiningStatus::Start)
71 }
72
73 pub fn stop(&self) {
75 {
76 let mut write = self.status.write();
77 *write = MiningStatus::Stop;
78 }
79 self.assembler.stop();
80 }
81
82 fn on_mined_block(&self, block: Block) {
84 self.sync.on_mined_block(block).ok();
86 }
87
88 pub fn test_api(self: &Arc<Self>) -> BlockGeneratorTestApi {
89 BlockGeneratorTestApi::new(self.clone())
90 }
91
92 pub fn mine(self: &Arc<Self>) {
93 let miner_type = if self.pow_config.use_stratum() {
94 miner::MinerType::Stratum
95 } else {
96 miner::MinerType::Cpu(1)
97 };
98
99 let (miner, solution_rx) = miner::spawn(self.clone(), miner_type);
100
101 MiningSession::new(&*self, &*miner, solution_rx).run();
102 }
103}
104
105impl Stopable for BlockGenerator {
106 fn stop(&self) { BlockGenerator::stop(self) }
107}