cfxcore/consensus/consensus_graph/
mining_api.rs1use super::ConsensusGraph;
2
3use crate::consensus::consensus_inner::{ConsensusGraphInner, StateBlameInfo};
4
5use cfx_parameters::consensus::*;
6use cfx_types::{H256, U256};
7use primitives::pos::PosBlockId;
8
9use std::{thread::sleep, time::Duration};
10
11impl ConsensusGraph {
12 pub fn check_mining_adaptive_block(
15 &self, inner: &mut ConsensusGraphInner, parent_hash: &H256,
16 referees: &Vec<H256>, difficulty: &U256,
17 pos_reference: Option<PosBlockId>,
18 ) -> bool {
19 let parent_index =
20 *inner.hash_to_arena_indices.get(parent_hash).expect(
21 "parent_hash is the pivot chain tip,\
22 so should still exist in ConsensusInner",
23 );
24 let referee_indices: Vec<_> = referees
25 .iter()
26 .map(|h| {
27 *inner
28 .hash_to_arena_indices
29 .get(h)
30 .expect("Checked by the caller")
31 })
32 .collect();
33 inner.check_mining_adaptive_block(
34 parent_index,
35 referee_indices,
36 *difficulty,
37 pos_reference,
38 )
39 }
40
41 pub fn wait_for_generation(&self, hash: &H256) {
44 while !self
45 .inner
46 .read_recursive()
47 .hash_to_arena_indices
48 .contains_key(hash)
49 {
50 sleep(Duration::from_millis(1));
51 }
52 let best_state_block =
53 self.inner.read_recursive().best_state_block_hash();
54 match self.executor.wait_for_result(best_state_block) {
55 Ok(_) => (),
56 Err(msg) => warn!("wait_for_generation() gets the following error from the ConsensusExecutor: {}", msg)
57 }
58 self.update_best_info(true);
64 if let Err(e) = self
65 .txpool
66 .notify_new_best_info(self.best_info.read_recursive().clone())
67 {
68 error!("wait for generation: notify_new_best_info err={:?}", e);
69 }
70 }
71
72 pub fn choose_correct_parent(
76 &self, parent_hash: &mut H256, referees: &mut Vec<H256>,
77 blame_info: &mut StateBlameInfo, pos_reference: Option<PosBlockId>,
78 ) {
79 let correct_parent_hash = {
80 if let Some(pos_ref) = &pos_reference {
81 loop {
82 let inner = self.inner.read();
83 let pivot_decision = inner
84 .pos_verifier
85 .get_pivot_decision(pos_ref)
86 .expect("pos ref committed");
87 if inner.hash_to_arena_indices.contains_key(&pivot_decision)
88 || inner.pivot_block_processed(&pivot_decision)
89 {
90 break;
93 } else {
94 drop(inner);
96 warn!("Wait for PoW to catch up with PoS");
97 sleep(Duration::from_secs(1));
98 }
99 }
100 }
101 let mut inner = self.inner.write();
104 referees.retain(|h| inner.hash_to_arena_indices.contains_key(h));
105 let parent_index =
106 *inner.hash_to_arena_indices.get(parent_hash).expect(
107 "parent_hash is the pivot chain tip,\
108 so should still exist in ConsensusInner",
109 );
110 let referee_indices: Vec<_> = referees
111 .iter()
112 .map(|h| {
113 *inner
114 .hash_to_arena_indices
115 .get(h)
116 .expect("Checked by the caller")
117 })
118 .collect();
119 let correct_parent = inner.choose_correct_parent(
120 parent_index,
121 referee_indices,
122 pos_reference,
123 );
124 inner.arena[correct_parent].hash
125 };
126
127 if correct_parent_hash != *parent_hash {
128 debug!(
129 "Change parent from {:?} to {:?}",
130 parent_hash, correct_parent_hash
131 );
132
133 referees.retain(|i| *i != correct_parent_hash);
135
136 if referees.len() < self.config.referee_bound {
138 referees.push(*parent_hash);
139 }
140
141 *blame_info = self
144 .force_compute_blame_and_deferred_state_for_generation(
145 &correct_parent_hash,
146 )
147 .expect("blame info computation error");
148 *parent_hash = correct_parent_hash;
149 }
150 }
151
152 pub fn force_compute_blame_and_deferred_state_for_generation(
155 &self, parent_block_hash: &H256,
156 ) -> Result<StateBlameInfo, String> {
157 {
158 let inner = &mut *self.inner.write();
159 let hash = inner
160 .get_state_block_with_delay(
161 parent_block_hash,
162 DEFERRED_STATE_EPOCH_COUNT as usize - 1,
163 )?
164 .clone();
165 self.executor.compute_state_for_block(&hash, inner)?;
166 }
167 self.executor.get_blame_and_deferred_state_for_generation(
168 parent_block_hash,
169 &self.inner,
170 )
171 }
172
173 pub fn get_blame_and_deferred_state_for_generation(
174 &self, parent_block_hash: &H256,
175 ) -> Result<StateBlameInfo, String> {
176 self.executor.get_blame_and_deferred_state_for_generation(
177 parent_block_hash,
178 &self.inner,
179 )
180 }
181}