1use std::{
6 cmp::max,
7 collections::{BinaryHeap, HashMap, HashSet, VecDeque},
8 mem, panic,
9 sync::{
10 atomic::{AtomicUsize, Ordering},
11 Arc,
12 },
13 thread,
14 time::{Duration, SystemTime, UNIX_EPOCH},
15};
16
17use cfx_parameters::consensus_internal::ELASTICITY_MULTIPLIER;
18use parking_lot::{Mutex, RwLock};
19use slab::Slab;
20use tokio::sync::mpsc::error::TryRecvError;
21use unexpected::{Mismatch, OutOfBounds};
22
23use cfx_executor::machine::Machine;
24use cfx_types::{H256, U256};
25use cfxcore_errors::ProviderBlockError;
26use dag::{Graph, RichDAG, RichTreeGraph, TreeGraph, DAG};
27use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
28use malloc_size_of_derive::MallocSizeOf as DeriveMallocSizeOf;
29use metrics::{
30 register_meter_with_group, register_queue, Meter, MeterTimer, Queue,
31};
32use primitives::{
33 pos::PosBlockId, transaction::SignedTransaction, Block, BlockHeader,
34 EpochNumber,
35};
36
37use crate::{
38 block_data_manager::{BlockDataManager, BlockStatus},
39 channel::Channel,
40 consensus::{pos_handler::PosVerifier, SharedConsensusGraph},
41 core_error::{BlockError, CoreError as Error},
42 pow::{PowComputer, ProofOfWorkConfig},
43 state_exposer::{SyncGraphBlockState, STATE_EXPOSER},
44 statistics::SharedStatistics,
45 sync::synchronization_protocol_handler::FutureBlockContainer,
46 verification::*,
47 Notifications,
48};
49
50lazy_static! {
51 static ref SYNC_INSERT_HEADER: Arc<dyn Meter> =
52 register_meter_with_group("timer", "sync::insert_block_header");
53 static ref SYNC_INSERT_BLOCK: Arc<dyn Meter> =
54 register_meter_with_group("timer", "sync::insert_block");
55 static ref CONSENSUS_WORKER_QUEUE: Arc<dyn Queue> =
56 register_queue("consensus_worker_queue");
57}
58
59const NULL: usize = !0;
60const BLOCK_INVALID: u8 = 0;
61const BLOCK_HEADER_ONLY: u8 = 1;
62const BLOCK_HEADER_GRAPH_READY: u8 = 2;
63const BLOCK_GRAPH_READY: u8 = 3;
64
65#[derive(Copy, Clone)]
66pub struct SyncGraphConfig {
67 pub future_block_buffer_capacity: usize,
68 pub enable_state_expose: bool,
69 pub is_consortium: bool,
70}
71
72#[derive(Debug)]
73pub struct SyncGraphStatistics {
74 pub inserted_block_count: usize,
75 pub inserted_header_count: usize,
76}
77
78impl SyncGraphStatistics {
79 pub fn new() -> SyncGraphStatistics {
80 SyncGraphStatistics {
81 inserted_header_count: 1,
83 inserted_block_count: 1,
84 }
85 }
86
87 pub fn clear(&mut self) {
88 self.inserted_header_count = 1;
89 self.inserted_block_count = 1;
90 }
91}
92
93#[derive(DeriveMallocSizeOf)]
94pub struct SynchronizationGraphNode {
95 pub block_header: Arc<BlockHeader>,
96 pub graph_status: u8,
98 pub block_ready: bool,
100 pub parent_reclaimed: bool,
102 pub parent: usize,
104 pub children: Vec<usize>,
106 pub referees: Vec<usize>,
108 pub pending_referee_count: usize,
111 pub referrers: Vec<usize>,
113 pub last_update_timestamp: u64,
115}
116
117#[derive(DeriveMallocSizeOf)]
118pub struct UnreadyBlockFrontier {
119 frontier: HashSet<usize>,
120 updated: bool,
121}
122
123impl UnreadyBlockFrontier {
124 fn new() -> Self {
125 UnreadyBlockFrontier {
126 frontier: HashSet::new(),
127 updated: false,
128 }
129 }
130
131 pub fn reset_update_state(&mut self) { self.updated = false; }
132
133 pub fn updated(&self) -> bool { self.updated }
134
135 pub fn get_frontier(&self) -> &HashSet<usize> { &self.frontier }
136
137 pub fn remove(&mut self, index: &usize) -> bool {
138 self.updated = true;
139 self.frontier.remove(index)
140 }
141
142 pub fn contains(&self, index: &usize) -> bool {
143 self.frontier.contains(index)
144 }
145
146 pub fn insert(&mut self, index: usize) -> bool {
147 self.updated = true;
148 self.frontier.insert(index)
149 }
150
151 pub fn len(&self) -> usize { self.frontier.len() }
152}
153
154pub struct SynchronizationGraphInner {
155 pub arena: Slab<SynchronizationGraphNode>,
156 pub hash_to_arena_indices: HashMap<H256, usize>,
157 pub data_man: Arc<BlockDataManager>,
158 children_by_hash: HashMap<H256, Vec<usize>>,
159 referrers_by_hash: HashMap<H256, Vec<usize>>,
160 pub pow_config: ProofOfWorkConfig,
161 pub pow: Arc<PowComputer>,
162 pub config: SyncGraphConfig,
163 pub not_ready_blocks_frontier: UnreadyBlockFrontier,
169
170 pub pos_not_ready_blocks_frontier: HashSet<usize>,
174 pub old_era_blocks_frontier: VecDeque<usize>,
175 pub old_era_blocks_frontier_set: HashSet<usize>,
176
177 pub locked_for_catchup: bool,
181 pub block_to_fill_set: HashSet<H256>,
184 machine: Arc<Machine>,
185 pub pos_verifier: Arc<PosVerifier>,
186}
187
188impl MallocSizeOf for SynchronizationGraphInner {
189 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
190 self.arena.size_of(ops)
191 + self.hash_to_arena_indices.size_of(ops)
192 + self.data_man.size_of(ops)
193 + self.children_by_hash.size_of(ops)
194 + self.referrers_by_hash.size_of(ops)
195 + self.pow_config.size_of(ops)
196 + self.not_ready_blocks_frontier.size_of(ops)
197 + self.old_era_blocks_frontier.size_of(ops)
198 + self.old_era_blocks_frontier_set.size_of(ops)
199 }
201}
202
203impl SynchronizationGraphInner {
204 pub fn with_genesis_block(
205 genesis_header: Arc<BlockHeader>, pow_config: ProofOfWorkConfig,
206 pow: Arc<PowComputer>, config: SyncGraphConfig,
207 data_man: Arc<BlockDataManager>, machine: Arc<Machine>,
208 pos_verifier: Arc<PosVerifier>,
209 ) -> Self {
210 let mut inner = SynchronizationGraphInner {
211 arena: Slab::new(),
212 hash_to_arena_indices: HashMap::new(),
213 data_man,
214 children_by_hash: HashMap::new(),
215 referrers_by_hash: HashMap::new(),
216 pow_config,
217 pow,
218 config,
219 not_ready_blocks_frontier: UnreadyBlockFrontier::new(),
220 pos_not_ready_blocks_frontier: Default::default(),
221 old_era_blocks_frontier: Default::default(),
222 old_era_blocks_frontier_set: Default::default(),
223 block_to_fill_set: Default::default(),
224 locked_for_catchup: false,
225 machine,
226 pos_verifier,
227 };
228 let genesis_hash = genesis_header.hash();
229 let genesis_block_index = inner.insert(genesis_header);
230 debug!(
231 "genesis block {:?} has index {} in sync graph",
232 genesis_hash, genesis_block_index
233 );
234
235 inner.old_era_blocks_frontier.push_back(genesis_block_index);
236 inner
237 .old_era_blocks_frontier_set
238 .insert(genesis_block_index);
239
240 inner
241 }
242
243 fn get_genesis_in_current_era(&self) -> usize {
244 let genesis_hash = self.data_man.get_cur_consensus_era_genesis_hash();
245 *self.hash_to_arena_indices.get(&genesis_hash).unwrap()
246 }
247
248 pub fn get_genesis_hash_and_height_in_current_era(&self) -> (H256, u64) {
249 let era_genesis = self.get_genesis_in_current_era();
250 (
251 self.arena[era_genesis].block_header.hash(),
252 self.arena[era_genesis].block_header.height(),
253 )
254 }
255
256 pub fn get_stable_hash_and_height_in_current_era(&self) -> (H256, u64) {
257 let stable_hash = self.data_man.get_cur_consensus_era_stable_hash();
258 let height = self
262 .data_man
263 .block_header_by_hash(&stable_hash)
264 .expect("stable block must exist in data manager")
265 .height();
266 (stable_hash, height)
267 }
268
269 fn try_clear_old_era_blocks(&mut self) {
270 let max_num_of_cleared_blocks = 2;
271 let mut num_cleared = 0;
272 let era_genesis = self.get_genesis_in_current_era();
273 let genesis_seq_num = self
274 .data_man
275 .local_block_info_by_hash(
276 &self.data_man.get_cur_consensus_era_genesis_hash(),
277 )
278 .expect("local_block_info for genesis must exist")
279 .get_seq_num();
280 let mut era_genesis_in_frontier = false;
281
282 while let Some(index) = self.old_era_blocks_frontier.pop_front() {
283 if index == era_genesis {
284 era_genesis_in_frontier = true;
285 continue;
286 }
287
288 if !self.old_era_blocks_frontier_set.contains(&index) {
290 continue;
291 }
292
293 let hash = self.arena[index].block_header.hash();
294 assert!(self.arena[index].parent == NULL);
295
296 if !self.is_graph_ready_in_db(&hash, genesis_seq_num) {
297 continue;
305 }
306
307 let referees: Vec<usize> =
308 self.arena[index].referees.iter().map(|x| *x).collect();
309 for referee in referees {
310 self.arena[referee].referrers.retain(|&x| x != index);
311 }
312 let referee_hashes: Vec<H256> = self.arena[index]
313 .block_header
314 .referee_hashes()
315 .iter()
316 .map(|x| *x)
317 .collect();
318 for referee_hash in referee_hashes {
319 let mut remove_referee_hash: bool = false;
320 if let Some(referrers) =
321 self.referrers_by_hash.get_mut(&referee_hash)
322 {
323 referrers.retain(|&x| x != index);
324 remove_referee_hash = referrers.len() == 0;
325 }
326 if remove_referee_hash {
328 self.referrers_by_hash.remove(&referee_hash);
329 }
330 }
331
332 let children: Vec<usize> =
333 self.arena[index].children.iter().map(|x| *x).collect();
334 for child in children {
335 self.arena[child].parent = NULL;
336 self.arena[child].parent_reclaimed = true;
337 self.old_era_blocks_frontier.push_back(child);
342 assert!(!self.old_era_blocks_frontier_set.contains(&child));
343 self.old_era_blocks_frontier_set.insert(child);
344 }
345
346 let referrers: Vec<usize> =
347 self.arena[index].referrers.iter().map(|x| *x).collect();
348 for referrer in referrers {
349 self.arena[referrer].referees.retain(|&x| x != index);
350 }
351
352 self.old_era_blocks_frontier_set.remove(&index);
353 self.arena.remove(index);
354 self.hash_to_arena_indices.remove(&hash);
355 self.data_man
357 .remove_block_header(&hash, false );
358
359 num_cleared += 1;
360 if num_cleared == max_num_of_cleared_blocks {
361 break;
362 }
363 }
364
365 if era_genesis_in_frontier {
366 self.old_era_blocks_frontier.push_front(era_genesis);
367 }
368 }
369
370 pub fn insert_invalid(&mut self, header: Arc<BlockHeader>) -> usize {
371 let hash = header.hash();
372 let me = self.arena.insert(SynchronizationGraphNode {
373 graph_status: BLOCK_INVALID,
374 block_ready: false,
375 parent_reclaimed: false,
376 parent: NULL,
377 children: Vec::new(),
378 referees: Vec::new(),
379 pending_referee_count: 0,
380 referrers: Vec::new(),
381 block_header: header,
382 last_update_timestamp: SystemTime::now()
383 .duration_since(UNIX_EPOCH)
384 .unwrap()
385 .as_secs(),
386 });
387 self.hash_to_arena_indices.insert(hash, me);
388
389 if let Some(children) = self.children_by_hash.remove(&hash) {
390 for child in &children {
391 self.arena[*child].parent = me;
392 }
393 self.arena[me].children = children;
394 }
395 if let Some(referrers) = self.referrers_by_hash.remove(&hash) {
396 for referrer in &referrers {
397 let ref mut node_referrer = self.arena[*referrer];
398 node_referrer.referees.push(me);
399 debug_assert!(node_referrer.pending_referee_count > 0);
400 if node_referrer.pending_referee_count > 0 {
401 node_referrer.pending_referee_count =
402 node_referrer.pending_referee_count - 1;
403 }
404 }
405 self.arena[me].referrers = referrers;
406 }
407
408 me
409 }
410
411 pub fn insert(&mut self, header: Arc<BlockHeader>) -> usize {
413 let hash = header.hash();
414 let is_genesis =
415 hash == self.data_man.get_cur_consensus_era_genesis_hash();
416
417 let me = self.arena.insert(SynchronizationGraphNode {
418 graph_status: if is_genesis {
419 BLOCK_GRAPH_READY
420 } else {
421 BLOCK_HEADER_ONLY
422 },
423 block_ready: is_genesis,
424 parent_reclaimed: false,
425 parent: NULL,
426 children: Vec::new(),
427 referees: Vec::new(),
428 pending_referee_count: 0,
429 referrers: Vec::new(),
430 block_header: header.clone(),
431 last_update_timestamp: SystemTime::now()
432 .duration_since(UNIX_EPOCH)
433 .unwrap()
434 .as_secs(),
435 });
436 self.hash_to_arena_indices.insert(hash, me);
437
438 if !is_genesis {
439 let parent_hash = header.parent_hash().clone();
440 if let Some(parent) =
441 self.hash_to_arena_indices.get(&parent_hash).cloned()
442 {
443 self.arena[me].parent = parent;
444 self.arena[parent].children.push(me);
445 } else {
446 self.children_by_hash
447 .entry(parent_hash)
448 .or_insert(Vec::new())
449 .push(me);
450 }
451 }
452 for referee_hash in header.referee_hashes() {
453 if let Some(referee) =
454 self.hash_to_arena_indices.get(referee_hash).cloned()
455 {
456 self.arena[me].referees.push(referee);
457 self.arena[referee].referrers.push(me);
458 } else {
459 self.arena[me].pending_referee_count =
460 self.arena[me].pending_referee_count + 1;
461 self.referrers_by_hash
462 .entry(*referee_hash)
463 .or_insert(Vec::new())
464 .push(me);
465 }
466 }
467
468 if let Some(children) = self.children_by_hash.remove(&hash) {
469 for child in &children {
470 self.arena[*child].parent = me;
471 }
472 self.arena[me].children = children;
473 }
474 if let Some(referrers) = self.referrers_by_hash.remove(&hash) {
475 for referrer in &referrers {
476 let ref mut node_referrer = self.arena[*referrer];
477 node_referrer.referees.push(me);
478 debug_assert!(node_referrer.pending_referee_count > 0);
479 if node_referrer.pending_referee_count > 0 {
480 node_referrer.pending_referee_count =
481 node_referrer.pending_referee_count - 1;
482 }
483 }
484 self.arena[me].referrers = referrers;
485 }
486
487 me
488 }
489
490 fn is_graph_ready_in_db(
493 &self, parent_or_referee_hash: &H256, genesis_seq_num: u64,
494 ) -> bool {
495 if let Some(info) = self
496 .data_man
497 .local_block_info_by_hash(parent_or_referee_hash)
498 {
499 if info.get_status() == BlockStatus::Invalid {
500 false
501 } else {
502 info.get_seq_num() < genesis_seq_num
503 || info.get_instance_id() == self.data_man.get_instance_id()
504 }
505 } else {
506 false
507 }
508 }
509
510 fn new_to_be_graph_ready(
511 &mut self, index: usize, minimal_status: u8,
512 ) -> bool {
513 let ref node_me = self.arena[index];
514 if node_me.graph_status >= minimal_status {
520 return false;
521 }
522
523 let genesis_hash = self.data_man.get_cur_consensus_era_genesis_hash();
524 let genesis_seq_num = self
525 .data_man
526 .local_block_info_by_hash(&genesis_hash)
527 .expect("local_block_info for genesis must exist")
528 .get_seq_num();
529 let parent = self.arena[index].parent;
530 let parent_graph_ready = if parent == NULL {
531 self.arena[index].parent_reclaimed
532 || self.is_graph_ready_in_db(
533 self.arena[index].block_header.parent_hash(),
534 genesis_seq_num,
535 )
536 } else {
537 self.arena[parent].graph_status >= minimal_status
538 };
539
540 if !parent_graph_ready {
541 return false;
542 } else if parent == NULL {
543 self.arena[index].parent_reclaimed = true;
544 }
545
546 let mut referee_hash_in_mem = HashSet::new();
553 for referee in self.arena[index].referees.iter() {
554 if self.arena[*referee].graph_status < minimal_status {
555 return false;
556 } else {
557 referee_hash_in_mem
558 .insert(self.arena[*referee].block_header.hash());
559 }
560 }
561
562 for referee_hash in self.arena[index].block_header.referee_hashes() {
563 if !referee_hash_in_mem.contains(referee_hash) {
564 if !self.is_graph_ready_in_db(referee_hash, genesis_seq_num) {
565 return false;
566 }
567 }
568 }
569
570 if !self.is_pos_reference_graph_ready(
571 index,
572 genesis_seq_num,
573 minimal_status,
574 ) {
575 debug!(
576 "Block {:?} not ready for its pos_reference: {:?}",
577 self.arena[index].block_header.hash(),
578 self.pos_verifier.get_pivot_decision(
579 self.arena[index]
580 .block_header
581 .pos_reference()
582 .as_ref()
583 .unwrap()
584 )
585 );
586 self.pos_not_ready_blocks_frontier.insert(index);
588 return false;
589 }
590
591 true
593 }
594
595 fn new_to_be_header_graph_ready(&mut self, index: usize) -> bool {
596 self.new_to_be_graph_ready(index, BLOCK_HEADER_GRAPH_READY)
597 }
598
599 fn new_to_be_block_graph_ready(&mut self, index: usize) -> bool {
600 self.new_to_be_graph_ready(index, BLOCK_GRAPH_READY)
601 && self.arena[index].block_ready
602 }
603
604 fn is_pos_reference_graph_ready(
605 &self, index: usize, genesis_seq_num: u64, minimal_status: u8,
606 ) -> bool {
607 match self.arena[index].block_header.pos_reference() {
609 Some(pos_reference) => {
612 match self.pos_verifier.get_pivot_decision(pos_reference) {
613 None => false,
615 Some(pivot_decision) => {
616 match self.hash_to_arena_indices.get(&pivot_decision) {
618 None => self.is_graph_ready_in_db(
619 &pivot_decision,
620 genesis_seq_num,
621 ),
622 Some(index) => {
623 self.arena[*index].graph_status
624 >= minimal_status
625 }
626 }
627 }
628 }
629 }
630 None => true,
631 }
632 }
633
634 fn get_parent_and_referee_info(
638 &self, index: usize,
639 ) -> (u64, u64, U256, U256, Vec<Option<PosBlockId>>) {
640 let parent_height;
641 let parent_timestamp;
642 let parent_gas_limit;
643 let parent_difficulty;
644 let mut pos_references = Vec::new();
647 let parent = self.arena[index].parent;
648
649 if parent != NULL {
651 parent_height = self.arena[parent].block_header.height();
652 parent_timestamp = self.arena[parent].block_header.timestamp();
653 parent_gas_limit = *self.arena[parent].block_header.gas_limit();
654 parent_difficulty = *self.arena[parent].block_header.difficulty();
655 pos_references
656 .push(self.arena[parent].block_header.pos_reference().clone())
657 } else {
658 let parent_hash = self.arena[index].block_header.parent_hash();
659 let parent_header = self
660 .data_man
661 .block_header_by_hash(parent_hash)
662 .unwrap()
663 .clone();
664 parent_height = parent_header.height();
665 parent_timestamp = parent_header.timestamp();
666 parent_gas_limit = *parent_header.gas_limit();
667 parent_difficulty = *parent_header.difficulty();
668 pos_references.push(parent_header.pos_reference().clone());
669 }
670
671 let mut referee_hash_in_mem = HashSet::new();
673 for referee in self.arena[index].referees.iter() {
674 pos_references.push(
675 self.arena[*referee].block_header.pos_reference().clone(),
676 );
677 referee_hash_in_mem
678 .insert(self.arena[*referee].block_header.hash());
679 }
680
681 for referee_hash in self.arena[index].block_header.referee_hashes() {
682 if !referee_hash_in_mem.contains(referee_hash) {
683 let referee_header = self
684 .data_man
685 .block_header_by_hash(referee_hash)
686 .unwrap()
687 .clone();
688 pos_references.push(referee_header.pos_reference().clone());
689 }
690 }
691
692 (
693 parent_height,
694 parent_timestamp,
695 parent_gas_limit,
696 parent_difficulty,
697 pos_references,
698 )
699 }
700
701 fn verify_header_graph_ready_block(
702 &self, index: usize,
703 ) -> Result<(), Error> {
704 let epoch = self.arena[index].block_header.height();
705 let (
706 parent_height,
707 parent_timestamp,
708 parent_gas_limit,
709 parent_difficulty,
710 predecessor_pos_references,
711 ) = self.get_parent_and_referee_info(index);
712
713 if parent_height + 1 != epoch {
715 warn!("Invalid height. mine {}, parent {}", epoch, parent_height);
716 return Err(From::from(BlockError::InvalidHeight(Mismatch {
717 expected: parent_height + 1,
718 found: epoch,
719 })));
720 }
721
722 let my_timestamp = self.arena[index].block_header.timestamp();
741 if parent_timestamp > my_timestamp {
742 let my_timestamp = UNIX_EPOCH + Duration::from_secs(my_timestamp);
743 let pa_timestamp =
744 UNIX_EPOCH + Duration::from_secs(parent_timestamp);
745
746 warn!("Invalid timestamp: parent {:?} timestamp {}, me {:?} timestamp {}",
747 self.arena[index].block_header.parent_hash().clone(),
748 parent_timestamp,
749 self.arena[index].block_header.hash(),
750 self.arena[index].block_header.timestamp());
751 return Err(From::from(BlockError::InvalidTimestamp(
752 OutOfBounds {
753 max: Some(my_timestamp),
754 min: Some(pa_timestamp),
755 found: my_timestamp,
756 },
757 )));
758 }
759
760 let parent_gas_limit = parent_gas_limit
761 * if epoch == self.machine.params().transition_heights.cip1559 {
762 ELASTICITY_MULTIPLIER
763 } else {
764 1
765 };
766
767 let self_gas_limit = *self.arena[index].block_header.gas_limit();
769 let gas_limit_divisor = self.machine.params().gas_limit_bound_divisor;
770 let min_gas_limit = self.machine.params().min_gas_limit;
771 let gas_upper =
772 parent_gas_limit + parent_gas_limit / gas_limit_divisor - 1;
773 let gas_lower = max(
774 parent_gas_limit - parent_gas_limit / gas_limit_divisor + 1,
775 min_gas_limit,
776 );
777
778 if self_gas_limit < gas_lower || self_gas_limit > gas_upper {
779 return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds {
780 min: Some(gas_lower),
781 max: Some(gas_upper),
782 found: self_gas_limit,
783 })));
784 }
785
786 if !self.config.is_consortium {
787 let mut difficulty_invalid = false;
789 let my_diff = *self.arena[index].block_header.difficulty();
790 let mut min_diff = my_diff;
791 let mut max_diff = my_diff;
792 let initial_difficulty: U256 =
793 self.pow_config.initial_difficulty.into();
794
795 if parent_height
796 < self
797 .pow_config
798 .difficulty_adjustment_epoch_period(parent_height)
799 {
800 if my_diff != initial_difficulty {
801 difficulty_invalid = true;
802 min_diff = initial_difficulty;
803 max_diff = initial_difficulty;
804 }
805 } else {
806 let last_period_upper = (parent_height
807 / self
808 .pow_config
809 .difficulty_adjustment_epoch_period(parent_height))
810 * self
811 .pow_config
812 .difficulty_adjustment_epoch_period(parent_height);
813 if last_period_upper != parent_height {
814 if my_diff != parent_difficulty {
816 difficulty_invalid = true;
817 min_diff = parent_difficulty;
818 max_diff = parent_difficulty;
819 }
820 } else {
821 let (lower, upper) =
822 self.pow_config.get_adjustment_bound(parent_difficulty);
823 min_diff = lower;
824 max_diff = upper;
825 if my_diff < min_diff || my_diff > max_diff {
826 difficulty_invalid = true;
827 }
828 }
829 }
830
831 if difficulty_invalid {
832 return Err(From::from(BlockError::InvalidDifficulty(
833 OutOfBounds {
834 min: Some(min_diff),
835 max: Some(max_diff),
836 found: my_diff,
837 },
838 )));
839 }
840 }
841
842 if let Some(pos_reference) =
843 self.arena[index].block_header.pos_reference()
844 {
845 let mut pred_pos_ref_list = Vec::new();
846 for maybe_pos_ref in predecessor_pos_references {
847 if let Some(pos_ref) = maybe_pos_ref {
848 pred_pos_ref_list.push(pos_ref);
849 }
850 }
851 if !self
852 .pos_verifier
853 .verify_against_predecessors(pos_reference, &pred_pos_ref_list)
854 {
855 bail!(BlockError::InvalidPosReference);
856 }
857 }
858
859 Ok(())
860 }
861
862 fn verify_graph_ready_block(
863 &self, index: usize, verification_config: &VerificationConfig,
864 ) -> Result<(), Error> {
865 let block_header = &self.arena[index].block_header;
866 let parent = self
869 .data_man
870 .block_header_by_hash(block_header.parent_hash())
871 .expect("headers will not be deleted");
872 let block = self
873 .data_man
874 .block_by_hash(&block_header.hash(), true)
875 .expect("received");
876 verification_config.verify_sync_graph_ready_block(&block, &parent)
877 }
878
879 fn process_invalid_blocks(&mut self, invalid_set: &HashSet<usize>) {
880 for index in invalid_set {
881 let hash = self.arena[*index].block_header.hash();
882 self.data_man.invalidate_block(hash);
885 }
886 self.remove_blocks(&invalid_set);
887 }
888
889 fn remove_blocks(&mut self, to_remove_set: &HashSet<usize>) {
890 for index in to_remove_set {
891 let hash = self.arena[*index].block_header.hash();
892 self.not_ready_blocks_frontier.remove(index);
893 self.pos_not_ready_blocks_frontier.remove(index);
894 self.old_era_blocks_frontier_set.remove(index);
895 self.block_to_fill_set.remove(&hash);
898
899 let parent = self.arena[*index].parent;
900 if parent != NULL {
901 self.arena[parent].children.retain(|&x| x != *index);
902 }
903 let parent_hash = *self.arena[*index].block_header.parent_hash();
904 let mut remove_parent_hash: bool = false;
905 if let Some(children) = self.children_by_hash.get_mut(&parent_hash)
906 {
907 children.retain(|&x| x != *index);
908 remove_parent_hash = children.len() == 0;
909 }
910 if remove_parent_hash {
912 self.children_by_hash.remove(&parent_hash);
913 }
914
915 let referees: Vec<usize> =
916 self.arena[*index].referees.iter().map(|x| *x).collect();
917 for referee in referees {
918 self.arena[referee].referrers.retain(|&x| x != *index);
919 }
920 let referee_hashes: Vec<H256> = self.arena[*index]
921 .block_header
922 .referee_hashes()
923 .iter()
924 .map(|x| *x)
925 .collect();
926 for referee_hash in referee_hashes {
927 let mut remove_referee_hash: bool = false;
928 if let Some(referrers) =
929 self.referrers_by_hash.get_mut(&referee_hash)
930 {
931 referrers.retain(|&x| x != *index);
932 remove_referee_hash = referrers.len() == 0;
933 }
934 if remove_referee_hash {
936 self.referrers_by_hash.remove(&referee_hash);
937 }
938 }
939
940 let children: Vec<usize> =
941 self.arena[*index].children.iter().map(|x| *x).collect();
942 for child in children {
943 debug_assert!(to_remove_set.contains(&child));
944 self.arena[child].parent = NULL;
945 }
946
947 let referrers: Vec<usize> =
948 self.arena[*index].referrers.iter().map(|x| *x).collect();
949 for referrer in referrers {
950 debug_assert!(to_remove_set.contains(&referrer));
951 self.arena[referrer].referees.retain(|&x| x != *index);
952 }
953
954 self.arena.remove(*index);
955 self.hash_to_arena_indices.remove(&hash);
956 self.data_man
958 .remove_useless_block(&hash, true );
959 }
960 }
961
962 fn set_and_propagate_invalid(
963 &mut self, queue: &mut VecDeque<usize>,
964 invalid_set: &mut HashSet<usize>, index: usize,
965 ) {
966 let children =
967 mem::replace(&mut self.arena[index].children, Vec::new());
968 for child in &children {
969 if !invalid_set.contains(&child) {
970 self.arena[*child].graph_status = BLOCK_INVALID;
971 queue.push_back(*child);
972 invalid_set.insert(*child);
973 }
974 }
975 self.arena[index].children = children;
976 let referrers =
977 mem::replace(&mut self.arena[index].referrers, Vec::new());
978 for referrer in &referrers {
979 if !invalid_set.contains(&referrer) {
980 self.arena[*referrer].graph_status = BLOCK_INVALID;
981 queue.push_back(*referrer);
982 invalid_set.insert(*referrer);
983 }
984 }
985 self.arena[index].referrers = referrers;
986 }
987}
988
989struct ConsensusWorkerHandle {
993 thread: Mutex<Option<thread::JoinHandle<()>>>,
994 new_block_hashes: Arc<Channel<H256>>,
996 worker_subscription_id: u64,
997}
998
999impl ConsensusWorkerHandle {
1000 fn stop(&self) {
1001 self.new_block_hashes
1002 .unsubscribe(self.worker_subscription_id);
1003 if let Some(handle) = self.thread.lock().take() {
1004 handle.join().expect("Consensus Worker should not panic");
1005 }
1006 }
1007}
1008
1009impl Drop for ConsensusWorkerHandle {
1010 fn drop(&mut self) { self.stop(); }
1011}
1012
1013pub struct SynchronizationGraph {
1014 pub inner: Arc<RwLock<SynchronizationGraphInner>>,
1015 pub consensus: SharedConsensusGraph,
1016 pub data_man: Arc<BlockDataManager>,
1017 pub pow: Arc<PowComputer>,
1018 pub verification_config: VerificationConfig,
1019 pub sync_config: SyncGraphConfig,
1020 pub statistics: SharedStatistics,
1021 consensus_unprocessed_count: Arc<AtomicUsize>,
1025
1026 new_block_hashes: Arc<Channel<H256>>,
1029
1030 pub future_blocks: FutureBlockContainer,
1033
1034 machine: Arc<Machine>,
1035
1036 #[allow(unused)]
1038 consensus_worker_handle: ConsensusWorkerHandle,
1039}
1040
1041impl MallocSizeOf for SynchronizationGraph {
1042 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1043 let inner_size = self.inner.read().size_of(ops);
1044 let mut malloc_size = inner_size + self.data_man.size_of(ops);
1045
1046 if !self.is_consortium() {
1048 let consensus_graph = &*self.consensus;
1049 malloc_size += consensus_graph.size_of(ops);
1050 }
1051 malloc_size
1054 }
1055}
1056
1057pub type SharedSynchronizationGraph = Arc<SynchronizationGraph>;
1058
1059impl SynchronizationGraph {
1060 pub fn new(
1061 consensus: SharedConsensusGraph, data_man: Arc<BlockDataManager>,
1062 statistics: SharedStatistics, verification_config: VerificationConfig,
1063 pow_config: ProofOfWorkConfig, pow: Arc<PowComputer>,
1064 sync_config: SyncGraphConfig, notifications: Arc<Notifications>,
1065 machine: Arc<Machine>, pos_verifier: Arc<PosVerifier>,
1066 ) -> Self {
1067 let genesis_hash = data_man.get_cur_consensus_era_genesis_hash();
1068 let genesis_block_header = data_man
1069 .block_header_by_hash(&genesis_hash)
1070 .expect("genesis block header should exist here");
1071
1072 let consensus_unprocessed_count = Arc::new(AtomicUsize::new(0));
1075 let mut consensus_receiver = notifications.new_block_hashes.subscribe();
1076 let inner = Arc::new(RwLock::new(
1077 SynchronizationGraphInner::with_genesis_block(
1078 genesis_block_header.clone(),
1079 pow_config,
1080 pow.clone(),
1081 sync_config,
1082 data_man.clone(),
1083 machine.clone(),
1084 pos_verifier.clone(),
1085 ),
1086 ));
1087 let worker_subscription_id = consensus_receiver.id;
1088
1089 let worker_data_man = data_man.clone();
1091 let worker_consensus = consensus.clone();
1092 let worker_unprocessed_count = consensus_unprocessed_count.clone();
1093
1094 let handle = thread::Builder::new()
1097 .name("Consensus Worker".into())
1098 .spawn(move || {
1100 let mut priority_queue: BinaryHeap<(u64, H256)> = BinaryHeap::new();
1106 let mut reverse_map : HashMap<H256, Vec<H256>> = HashMap::new();
1107 let mut counter_map = HashMap::new();
1108 let mut pos_started = false;
1109
1110 'outer: loop {
1111 let mut blocking = priority_queue.is_empty();
1113 'inner: loop {
1114 let maybe_item = if blocking {
1117 blocking = false;
1118 match consensus_receiver.recv_blocking() {
1119 Some(item) => Ok(item),
1120 None => break 'outer, }
1122 } else {
1123 consensus_receiver.try_recv()
1124 };
1125
1126 match maybe_item {
1127 Ok(hash) => if !reverse_map.contains_key(&hash) {
1129 debug!("Worker thread receive: block = {}", hash);
1130 let header = worker_data_man.block_header_by_hash(&hash).expect("Header must exist before sending to the consensus worker!");
1131
1132 if !pos_started && pos_verifier.is_enabled_at_height(header.height() + worker_consensus.config().inner_conf.era_epoch_count) {
1134 if let Err(e) = pos_verifier.initialize(worker_consensus.clone()) {
1135 info!("PoS cannot be started at the expected height: e={}", e);
1136 } else {
1137 pos_started = true;
1138 }
1139 }
1140
1141 let mut cnt: usize = 0;
1142 let parent_hash = header.parent_hash();
1143 if let Some(v) = reverse_map.get_mut(parent_hash) {
1144 v.push(hash.clone());
1145 cnt += 1;
1146 }
1147 for referee in header.referee_hashes() {
1148 if let Some(v) = reverse_map.get_mut(referee) {
1149 v.push(hash.clone());
1150 cnt += 1;
1151 }
1152 }
1153 if let Some(pivot_decision) = header.pos_reference().as_ref().and_then(|pos_reference| pos_verifier.get_pivot_decision(pos_reference)) {
1154 if let Some(v) = reverse_map.get_mut(&pivot_decision) {
1155 v.push(hash.clone());
1156 cnt += 1;
1157 }
1158 }
1159 reverse_map.insert(hash.clone(), Vec::new());
1160 if cnt == 0 {
1161 let epoch_number = worker_consensus.get_block_epoch_number(parent_hash).unwrap_or(0);
1162 priority_queue.push((epoch_number, hash));
1163 } else {
1164 counter_map.insert(hash, cnt);
1165 }
1166 } else {
1167 warn!("Duplicate block = {} sent to the consensus worker", hash);
1168 },
1169 Err(TryRecvError::Empty) => break 'inner,
1170 Err(TryRecvError::Disconnected) => break 'outer,
1171 }
1172 }
1173 if let Some((_, hash)) = priority_queue.pop() {
1174 CONSENSUS_WORKER_QUEUE.dequeue(1);
1175 let successors = reverse_map.remove(&hash).unwrap();
1176 for succ in successors {
1177 let cnt_tuple = counter_map.get_mut(&succ).unwrap();
1178 *cnt_tuple -= 1;
1179 if *cnt_tuple == 0 {
1180 counter_map.remove(&succ);
1181 let header_succ = worker_data_man.block_header_by_hash(&succ).expect("Header must exist before sending to the consensus worker!");
1182 let parent_succ = header_succ.parent_hash();
1183 let epoch_number = worker_consensus.get_block_epoch_number(parent_succ).unwrap_or(0);
1184 priority_queue.push((epoch_number, succ));
1185 }
1186 }
1187 worker_consensus.on_new_block(
1188 &hash,
1189 );
1190 worker_unprocessed_count.fetch_sub(1, Ordering::SeqCst);
1191 }
1192 }
1193 })
1194 .expect("Cannot fail");
1195
1196 let consensus_worker_handle = ConsensusWorkerHandle {
1197 thread: Mutex::new(Some(handle)),
1198 new_block_hashes: notifications.new_block_hashes.clone(),
1199 worker_subscription_id,
1200 };
1201
1202 let sync_graph = SynchronizationGraph {
1203 inner: inner.clone(),
1204 future_blocks: FutureBlockContainer::new(
1205 sync_config.future_block_buffer_capacity,
1206 ),
1207 data_man: data_man.clone(),
1208 pow: pow.clone(),
1209 verification_config,
1210 sync_config,
1211 consensus: consensus.clone(),
1212 statistics: statistics.clone(),
1213 consensus_unprocessed_count: consensus_unprocessed_count.clone(),
1214 new_block_hashes: notifications.new_block_hashes.clone(),
1215 machine,
1216 consensus_worker_handle,
1217 };
1218 sync_graph
1219 }
1220
1221 pub fn is_consortium(&self) -> bool { self.sync_config.is_consortium }
1222
1223 pub fn machine(&self) -> Arc<Machine> { self.machine.clone() }
1224
1225 pub fn get_genesis_hash_and_height_in_current_era(&self) -> (H256, u64) {
1226 self.inner
1227 .read()
1228 .get_genesis_hash_and_height_in_current_era()
1229 }
1230
1231 pub fn expected_difficulty(&self, parent_hash: &H256) -> U256 {
1234 self.consensus.expected_difficulty(parent_hash)
1235 }
1236
1237 pub fn get_to_propagate_trans(
1238 &self,
1239 ) -> HashMap<H256, Arc<SignedTransaction>> {
1240 self.consensus.tx_pool().get_to_be_propagated_transactions()
1241 }
1242
1243 pub fn set_to_propagate_trans(
1244 &self, transactions: HashMap<H256, Arc<SignedTransaction>>,
1245 ) {
1246 self.consensus
1247 .tx_pool()
1248 .set_to_be_propagated_transactions(transactions);
1249 }
1250
1251 pub fn recover_graph_from_db(&self) {
1256 info!("Start fast recovery of the block DAG from database");
1257
1258 let genesis_hash = self.data_man.get_cur_consensus_era_genesis_hash();
1261 let genesis_local_info =
1262 self.data_man.local_block_info_by_hash(&genesis_hash);
1263 if genesis_local_info.is_none() {
1264 panic!(
1266 "failed to get local block info from db for genesis[{}]",
1267 genesis_hash
1268 );
1269 }
1270 let genesis_seq_num = genesis_local_info.unwrap().get_seq_num();
1271 self.consensus.set_initial_sequence_number(genesis_seq_num);
1272 let genesis_header =
1273 self.data_man.block_header_by_hash(&genesis_hash).unwrap();
1274 debug!(
1275 "Get current genesis_block hash={:?}, height={}, seq_num={}",
1276 genesis_hash,
1277 genesis_header.height(),
1278 genesis_seq_num
1279 );
1280
1281 let terminals_opt = self.data_man.terminals_from_db();
1283 if terminals_opt.is_none() {
1284 return;
1285 }
1286 let terminals = terminals_opt.unwrap();
1287 debug!("Get terminals {:?}", terminals);
1288
1289 let mut queue = VecDeque::new();
1297 let mut visited_blocks: HashSet<H256> = HashSet::new();
1298 for terminal in terminals {
1299 if !visited_blocks.contains(&terminal) {
1301 queue.push_back(terminal);
1302 visited_blocks.insert(terminal);
1303 }
1304 }
1305
1306 let mut missed_hashes = HashSet::new();
1310 while let Some(hash) = queue.pop_front() {
1311 if hash == genesis_hash {
1312 continue;
1314 }
1315
1316 if let Some(block_local_info) =
1320 self.data_man.local_block_info_by_hash(&hash)
1321 {
1322 if block_local_info.get_seq_num() < genesis_seq_num {
1323 debug!(
1324 "Skip block {:?} before checkpoint: seq_num={}",
1325 hash,
1326 block_local_info.get_seq_num()
1327 );
1328 continue;
1329 }
1330 }
1331
1332 if let Some(block_header) =
1333 self.data_man.block_header_by_hash(&hash)
1334 {
1335 self.insert_block_header(
1336 &mut block_header.as_ref().clone(),
1337 true, false, true, false, );
1342 let parent = block_header.parent_hash().clone();
1343 let referees = block_header.referee_hashes().clone();
1344 if !visited_blocks.contains(&parent) {
1345 queue.push_back(parent);
1346 visited_blocks.insert(parent);
1347 }
1348 for referee in referees {
1349 if !visited_blocks.contains(&referee) {
1350 queue.push_back(referee);
1351 visited_blocks.insert(referee);
1352 }
1353 }
1354 } else {
1355 missed_hashes.insert(hash);
1356 }
1357 }
1358
1359 debug!(
1360 "Current frontier after recover from db: {:?}",
1361 self.inner.read().not_ready_blocks_frontier.get_frontier()
1362 );
1363
1364 info!("Finish reconstructing the pivot chain of length {}, start to sync from peers", self.consensus.best_epoch_number());
1365 }
1366
1367 pub fn block_header_by_hash(&self, hash: &H256) -> Option<BlockHeader> {
1369 if !self.contains_block_header(hash) {
1370 return None;
1372 }
1373 self.data_man
1374 .block_header_by_hash(hash)
1375 .map(|header_ref| header_ref.as_ref().clone())
1376 }
1377
1378 pub fn block_height_by_hash(&self, hash: &H256) -> Option<u64> {
1380 self.block_header_by_hash(hash)
1381 .map(|header| header.height())
1382 }
1383
1384 pub fn block_timestamp_by_hash(&self, hash: &H256) -> Option<u64> {
1386 self.block_header_by_hash(hash)
1387 .map(|header| header.timestamp())
1388 }
1389
1390 pub fn block_by_hash(&self, hash: &H256) -> Option<Arc<Block>> {
1393 self.data_man.block_by_hash(hash, true )
1394 }
1395
1396 pub fn contains_block_header(&self, hash: &H256) -> bool {
1397 self.inner.read().hash_to_arena_indices.contains_key(hash)
1398 || self.future_blocks.contains(hash)
1399 }
1400
1401 fn parent_or_referees_invalid(&self, header: &BlockHeader) -> bool {
1402 self.data_man.verified_invalid(header.parent_hash()).0
1403 || header
1404 .referee_hashes()
1405 .iter()
1406 .any(|referee| self.data_man.verified_invalid(referee).0)
1407 }
1408
1409 fn propagate_header_graph_status(
1411 &self, inner: &mut SynchronizationGraphInner,
1412 frontier_index_list: Vec<usize>, need_to_verify: bool,
1413 header_index_to_insert: usize, insert_to_consensus: bool,
1414 persistent: bool,
1415 ) -> (HashSet<usize>, Vec<H256>) {
1416 let now = SystemTime::now()
1417 .duration_since(UNIX_EPOCH)
1418 .unwrap()
1419 .as_secs();
1420 let mut need_to_relay: Vec<H256> = Vec::new();
1421 let mut invalid_set: HashSet<usize> = HashSet::new();
1422 let mut queue = VecDeque::new();
1423
1424 for index in frontier_index_list {
1425 if inner.arena[index].graph_status == BLOCK_INVALID {
1426 invalid_set.insert(index);
1427 }
1428 queue.push_back(index);
1429 }
1430
1431 while let Some(index) = queue.pop_front() {
1432 if inner.arena[index].graph_status == BLOCK_INVALID {
1433 inner.set_and_propagate_invalid(
1434 &mut queue,
1435 &mut invalid_set,
1436 index,
1437 );
1438 } else if inner.new_to_be_header_graph_ready(index) {
1439 inner.arena[index].graph_status = BLOCK_HEADER_GRAPH_READY;
1440 inner.arena[index].last_update_timestamp = now;
1441 debug!("BlockIndex {} parent_index {} hash {:?} is header graph ready", index,
1442 inner.arena[index].parent, inner.arena[index].block_header.hash());
1443
1444 let r = inner.verify_header_graph_ready_block(index);
1445
1446 if need_to_verify && r.is_err() {
1447 warn!(
1448 "Invalid header_arc! inserted_header={:?} err={:?}",
1449 inner.arena[index].block_header.clone(),
1450 r
1451 );
1452 invalid_set.insert(index);
1453 inner.arena[index].graph_status = BLOCK_INVALID;
1454 inner.set_and_propagate_invalid(
1455 &mut queue,
1456 &mut invalid_set,
1457 index,
1458 );
1459 continue;
1460 }
1461
1462 if inner.arena[index].parent_reclaimed {
1465 inner.old_era_blocks_frontier.push_back(index);
1466 inner.old_era_blocks_frontier_set.insert(index);
1467 }
1468
1469 if index == header_index_to_insert && persistent {
1476 self.data_man.insert_block_header(
1477 inner.arena[index].block_header.hash(),
1478 inner.arena[index].block_header.clone(),
1479 true,
1480 );
1481 }
1482 if insert_to_consensus {
1483 CONSENSUS_WORKER_QUEUE.enqueue(1);
1484
1485 self.consensus_unprocessed_count
1486 .fetch_add(1, Ordering::SeqCst);
1487 assert!(
1488 self.new_block_hashes
1489 .send(inner.arena[index].block_header.hash(),),
1490 "consensus receiver dropped"
1491 );
1492
1493 inner.not_ready_blocks_frontier.remove(&index);
1495 inner.pos_not_ready_blocks_frontier.remove(&index);
1498 for child in &inner.arena[index].children {
1499 inner.not_ready_blocks_frontier.insert(*child);
1500 }
1501 }
1502
1503 if inner.arena[index].block_ready {
1505 need_to_relay.push(inner.arena[index].block_header.hash());
1506 }
1507
1508 for child in &inner.arena[index].children {
1509 if inner.arena[*child].graph_status
1510 < BLOCK_HEADER_GRAPH_READY
1511 {
1512 queue.push_back(*child);
1513 }
1514 }
1515 for referrer in &inner.arena[index].referrers {
1516 if inner.arena[*referrer].graph_status
1517 < BLOCK_HEADER_GRAPH_READY
1518 {
1519 queue.push_back(*referrer);
1520 }
1521 }
1522 } else {
1523 debug!(
1524 "BlockIndex {} parent_index {} hash {:?} is not ready",
1525 index,
1526 inner.arena[index].parent,
1527 inner.arena[index].block_header.hash()
1528 );
1529 if index == header_index_to_insert && persistent {
1530 self.data_man.insert_block_header(
1531 inner.arena[index].block_header.hash(),
1532 inner.arena[index].block_header.clone(),
1533 true,
1534 );
1535 }
1536 }
1537 }
1538 (invalid_set, need_to_relay)
1539 }
1540
1541 pub fn insert_block_header(
1542 &self, header: &mut BlockHeader, need_to_verify: bool,
1543 bench_mode: bool, insert_to_consensus: bool, persistent: bool,
1544 ) -> (BlockHeaderInsertionResult, Vec<H256>) {
1545 let _timer = MeterTimer::time_func(SYNC_INSERT_HEADER.as_ref());
1546 self.statistics.inc_sync_graph_inserted_header_count();
1547 let inner = &mut *self.inner.write();
1548 if inner.locked_for_catchup {
1549 return (BlockHeaderInsertionResult::TemporarySkipped, Vec::new());
1551 }
1552 let hash = header.hash();
1553
1554 let (invalid, local_info_opt) = self.data_man.verified_invalid(&hash);
1555 if invalid {
1556 return (BlockHeaderInsertionResult::Invalid, Vec::new());
1557 }
1558
1559 if let Some(info) = local_info_opt {
1560 let already_processed = info.get_seq_num()
1565 < self.consensus.current_era_genesis_seq_num()
1566 || info.get_instance_id() == self.data_man.get_instance_id();
1567 if already_processed {
1568 if need_to_verify && !self.is_consortium() {
1569 VerificationConfig::get_or_fill_header_pow_quality(
1572 &self.pow, header,
1573 );
1574 }
1575 return (
1576 BlockHeaderInsertionResult::AlreadyProcessedInConsensus,
1577 Vec::new(),
1578 );
1579 }
1580 }
1581
1582 if inner.hash_to_arena_indices.contains_key(&hash) {
1583 if need_to_verify {
1584 VerificationConfig::get_or_fill_header_pow_quality(
1587 &self.pow, header,
1588 );
1589 }
1590 return (
1591 BlockHeaderInsertionResult::AlreadyProcessedInSync,
1592 Vec::new(),
1593 );
1594 }
1595
1596 debug!("is_consortium={:?}", self.is_consortium());
1598 let verification_passed = if need_to_verify {
1599 self.is_consortium()
1600 || !(self.parent_or_referees_invalid(header)
1601 || self
1602 .verification_config
1603 .verify_header_params(&self.pow, header)
1604 .or_else(|e| {
1605 warn!(
1606 "Invalid header: err={} header={:?}",
1607 e, header
1608 );
1609 Err(e)
1610 })
1611 .is_err())
1612 } else {
1613 if !bench_mode && !self.is_consortium() {
1614 self.verification_config
1615 .verify_pow(&self.pow, header)
1616 .expect("local mined block should pass this check!");
1617 }
1618 true
1619 };
1620
1621 let header_arc = Arc::new(header.clone());
1622 let me = if verification_passed {
1623 inner.insert(header_arc.clone())
1624 } else {
1625 inner.insert_invalid(header_arc.clone())
1626 };
1627
1628 if inner.arena[me].graph_status != BLOCK_GRAPH_READY {
1633 if inner.arena[me].parent == NULL
1642 || inner.arena[inner.arena[me].parent].graph_status
1643 == BLOCK_GRAPH_READY
1644 || (insert_to_consensus
1645 && inner.arena[inner.arena[me].parent].graph_status
1646 == BLOCK_HEADER_GRAPH_READY)
1647 {
1648 inner.not_ready_blocks_frontier.insert(me);
1649 }
1650 let mut to_be_removed = Vec::new();
1651 for child in &inner.arena[me].children {
1652 if inner.not_ready_blocks_frontier.contains(child) {
1653 to_be_removed.push(*child);
1654 }
1655 }
1656 for x in to_be_removed {
1657 inner.not_ready_blocks_frontier.remove(&x);
1658 }
1659 }
1660
1661 debug!("insert_block_header() Block = {:?}, index = {}, need_to_verify = {}, bench_mode = {} insert_to_consensus = {}",
1662 header.hash(), me, need_to_verify, bench_mode, insert_to_consensus);
1663
1664 let (invalid_set, need_to_relay) = self.propagate_header_graph_status(
1666 inner,
1667 vec![me],
1668 need_to_verify,
1669 me,
1670 insert_to_consensus,
1671 persistent,
1672 );
1673
1674 let me_invalid = invalid_set.contains(&me);
1675
1676 inner.process_invalid_blocks(&invalid_set);
1678
1679 if me_invalid {
1680 return (BlockHeaderInsertionResult::Invalid, need_to_relay);
1681 }
1682
1683 inner.try_clear_old_era_blocks();
1684
1685 (BlockHeaderInsertionResult::NewValid, need_to_relay)
1686 }
1687
1688 pub fn contains_block(&self, hash: &H256) -> bool {
1689 let inner = self.inner.read();
1690 if let Some(index) = inner.hash_to_arena_indices.get(hash) {
1691 inner.arena[*index].block_ready
1692 } else {
1693 false
1694 }
1695 }
1696
1697 fn set_graph_ready(
1698 &self, inner: &mut SynchronizationGraphInner, index: usize,
1699 ) {
1700 inner.arena[index].graph_status = BLOCK_GRAPH_READY;
1701
1702 inner.not_ready_blocks_frontier.remove(&index);
1704 inner.pos_not_ready_blocks_frontier.remove(&index);
1707 for child in &inner.arena[index].children {
1708 inner.not_ready_blocks_frontier.insert(*child);
1709 }
1710
1711 let h = inner.arena[index].block_header.hash();
1712 debug!("Block {:?} is graph ready", h);
1713 CONSENSUS_WORKER_QUEUE.enqueue(1);
1714
1715 self.consensus_unprocessed_count
1716 .fetch_add(1, Ordering::SeqCst);
1717 assert!(self.new_block_hashes.send(h), "consensus receiver dropped");
1718
1719 if inner.config.enable_state_expose {
1720 STATE_EXPOSER.sync_graph.lock().ready_block_vec.push(
1721 SyncGraphBlockState {
1722 block_hash: h,
1723 parent: inner.arena[index]
1724 .block_header
1725 .parent_hash()
1726 .clone(),
1727 referees: inner.arena[index]
1728 .block_header
1729 .referee_hashes()
1730 .clone(),
1731 nonce: inner.arena[index].block_header.nonce(),
1732 timestamp: inner.arena[index].block_header.timestamp(),
1733 adaptive: inner.arena[index].block_header.adaptive(),
1734 },
1735 );
1736 }
1737 }
1738
1739 fn propagate_graph_status(
1741 &self, inner: &mut SynchronizationGraphInner,
1742 frontier_index_list: Vec<usize>,
1743 ) -> HashSet<usize> {
1744 let mut queue = VecDeque::new();
1745 let mut invalid_set = HashSet::new();
1746 for index in frontier_index_list {
1747 if inner.arena[index].graph_status == BLOCK_INVALID {
1748 invalid_set.insert(index);
1749 }
1750 queue.push_back(index);
1751 }
1752
1753 while let Some(index) = queue.pop_front() {
1754 if inner.arena[index].graph_status == BLOCK_INVALID {
1755 inner.set_and_propagate_invalid(
1756 &mut queue,
1757 &mut invalid_set,
1758 index,
1759 );
1760 } else if inner.new_to_be_block_graph_ready(index) {
1761 let verify_result = inner
1762 .verify_graph_ready_block(index, &self.verification_config);
1763 if verify_result.is_err() {
1764 warn!(
1765 "Invalid block! inserted_header={:?} err={:?}",
1766 inner.arena[index].block_header.clone(),
1767 verify_result
1768 );
1769 invalid_set.insert(index);
1770 inner.arena[index].graph_status = BLOCK_INVALID;
1771 inner.set_and_propagate_invalid(
1772 &mut queue,
1773 &mut invalid_set,
1774 index,
1775 );
1776 continue;
1777 }
1778 self.set_graph_ready(inner, index);
1779 for child in &inner.arena[index].children {
1780 debug_assert!(
1781 inner.arena[*child].graph_status < BLOCK_GRAPH_READY
1782 );
1783 queue.push_back(*child);
1784 }
1785 for referrer in &inner.arena[index].referrers {
1786 debug_assert!(
1787 inner.arena[*referrer].graph_status < BLOCK_GRAPH_READY
1788 );
1789 queue.push_back(*referrer);
1790 }
1791 } else {
1792 trace!("Block index {:?} not block_graph_ready, current frontier: {:?}", index, inner.not_ready_blocks_frontier.get_frontier());
1793 }
1794 }
1795
1796 invalid_set
1797 }
1798
1799 pub fn insert_block(
1800 &self, block: Block, need_to_verify: bool, persistent: bool,
1801 recover_from_db: bool,
1802 ) -> BlockInsertionResult {
1803 let _timer = MeterTimer::time_func(SYNC_INSERT_BLOCK.as_ref());
1804 let hash = block.hash();
1805
1806 debug!("insert_block {:?}", hash);
1807
1808 let inner = &mut *self.inner.write();
1809
1810 let contains_block =
1811 if let Some(index) = inner.hash_to_arena_indices.get(&hash) {
1812 inner.arena[*index].block_ready
1813 } else {
1814 return BlockInsertionResult::Ignored;
1817 };
1818
1819 if contains_block {
1820 return BlockInsertionResult::AlreadyProcessed;
1821 }
1822
1823 debug_assert!(!self.data_man.verified_invalid(&hash).0);
1826
1827 self.statistics.inc_sync_graph_inserted_block_count();
1828
1829 let me = *inner.hash_to_arena_indices.get(&hash).unwrap();
1830
1831 debug_assert!(hash == inner.arena[me].block_header.hash());
1832 debug_assert!(!inner.arena[me].block_ready);
1833 inner.arena[me].block_ready = true;
1834
1835 if need_to_verify {
1836 let r = self.verification_config.verify_sync_graph_block_basic(
1837 &block,
1838 self.consensus.best_chain_id(),
1839 );
1840 match r {
1841 Err(Error::Block(BlockError::InvalidTransactionsRoot(e))) => {
1842 warn!("BlockTransactionRoot not match! inserted_block={:?} err={:?}", block, e);
1843 inner.arena[me].block_ready = false;
1851 return BlockInsertionResult::RequestAgain;
1852 }
1853 Err(e) => {
1854 warn!(
1855 "Invalid block! inserted_block={:?} err={:?}",
1856 block.block_header, e
1857 );
1858 inner.arena[me].graph_status = BLOCK_INVALID;
1859 }
1860 _ => {}
1861 };
1862 }
1863
1864 let block = Arc::new(block);
1865 if inner.arena[me].graph_status != BLOCK_INVALID {
1866 if !recover_from_db {
1869 self.data_man.insert_compact_block(block.to_compact());
1872 self.data_man.insert_block_body(
1875 block.hash(),
1876 block.clone(),
1877 persistent,
1878 );
1879 }
1880 }
1881
1882 if inner.locked_for_catchup {
1885 if inner.arena[me].graph_status == BLOCK_INVALID {
1886 let invalid_set = self.propagate_graph_status(inner, vec![me]);
1887 inner.process_invalid_blocks(&invalid_set);
1891 return BlockInsertionResult::Invalid;
1892 } else {
1893 debug!("Downloaded block body for {:?}", hash);
1894 inner.block_to_fill_set.remove(&hash);
1895 return BlockInsertionResult::AlreadyProcessed;
1896 }
1897 }
1898
1899 let invalid_set = self.propagate_graph_status(inner, vec![me]);
1900
1901 inner.process_invalid_blocks(&invalid_set);
1903
1904 debug!(
1905 "new block inserted into graph: block_header={:?}, tx_count={}, block_size={}",
1906 block.block_header,
1907 block.transactions.len(),
1908 block.size(),
1909 );
1910
1911 if invalid_set.contains(&me) {
1914 BlockInsertionResult::Invalid
1915 } else if inner.arena[me].graph_status >= BLOCK_HEADER_GRAPH_READY {
1916 BlockInsertionResult::ShouldRelay
1917 } else {
1918 BlockInsertionResult::SuccessWithoutRelay
1919 }
1920 }
1921
1922 pub fn get_all_block_hashes_by_epoch(
1923 &self, epoch_number: u64,
1924 ) -> Result<Vec<H256>, ProviderBlockError> {
1925 let mut res = self.consensus.get_skipped_block_hashes_by_epoch(
1926 EpochNumber::Number(epoch_number.into()),
1927 )?;
1928 res.append(&mut self.consensus.get_block_hashes_by_epoch(
1929 EpochNumber::Number(epoch_number.into()),
1930 )?);
1931 Ok(res)
1932 }
1933
1934 pub fn log_statistics(&self) { self.statistics.log_statistics(); }
1935
1936 pub fn update_total_weight_delta_heartbeat(&self) {
1937 self.consensus.update_total_weight_delta_heartbeat();
1938 }
1939
1940 pub fn block_count(&self) -> usize { self.data_man.cached_block_count() }
1944
1945 pub fn remove_expire_blocks(&self, expire_time: u64) {
1950 let inner = &mut *self.inner.write();
1951 let now = SystemTime::now()
1952 .duration_since(UNIX_EPOCH)
1953 .unwrap()
1954 .as_secs();
1955 let frontier = inner.not_ready_blocks_frontier.get_frontier().clone();
1956 let all_not_ready: HashSet<_> = inner.get_future(frontier);
1957 let mut expire_set = HashSet::new();
1958 for index in all_not_ready {
1959 if inner.arena[index].last_update_timestamp + expire_time < now {
1960 expire_set.insert(index);
1961 }
1962 }
1963
1964 let all_expire: HashSet<_> = inner.get_future(expire_set);
1966 debug!("all_expire: {:?}", all_expire);
1967 inner.remove_blocks(&all_expire);
1968 }
1969
1970 pub fn remove_blocks_and_future(&self, to_remove_set: &HashSet<H256>) {
1973 let mut inner = self.inner.write();
1974 let mut index_set = Vec::new();
1975 for block_hash in to_remove_set {
1976 if let Some(index) = inner.hash_to_arena_indices.get(block_hash) {
1977 index_set.push(*index);
1978 }
1979 }
1980 let index_set_and_future: HashSet<_> = inner.get_future(index_set);
1981 inner.remove_blocks(&index_set_and_future);
1982 }
1983
1984 pub fn is_consensus_worker_busy(&self) -> bool {
1985 self.consensus_unprocessed_count.load(Ordering::SeqCst) != 0
1986 }
1987
1988 pub fn is_fill_block_completed(&self) -> bool {
1989 self.inner.read().block_to_fill_set.is_empty()
1990 }
1991
1992 pub fn complete_filling_block_bodies(&self) -> bool {
2003 {
2004 let inner = &mut *self.inner.write();
2005
2006 let received: Vec<usize> = inner
2009 .hash_to_arena_indices
2010 .values()
2011 .copied()
2012 .filter(|index| {
2013 inner.arena[*index].graph_status == BLOCK_HEADER_GRAPH_READY
2014 && inner.arena[*index].block_ready
2015 })
2016 .collect();
2017 let mut invalid_frontier = Vec::new();
2018 for index in received {
2019 if let Err(e) = inner
2020 .verify_graph_ready_block(index, &self.verification_config)
2021 {
2022 warn!(
2023 "Invalid block! inserted_header={:?} err={:?}",
2024 inner.arena[index].block_header, e
2025 );
2026 inner.arena[index].graph_status = BLOCK_INVALID;
2027 invalid_frontier.push(index);
2028 }
2029 }
2030 let invalid_set =
2031 self.propagate_graph_status(inner, invalid_frontier);
2032 inner.process_invalid_blocks(&invalid_set);
2033
2034 let to_remove = {
2037 let arena = &mut inner.arena;
2038 inner
2039 .hash_to_arena_indices
2040 .iter()
2041 .filter_map(|(_, index)| {
2042 let graph_node = &mut arena[*index];
2043 if graph_node.graph_status == BLOCK_HEADER_GRAPH_READY {
2044 graph_node.block_ready = true;
2045 graph_node.graph_status = BLOCK_GRAPH_READY;
2046 }
2047 if graph_node.graph_status != BLOCK_GRAPH_READY {
2048 Some(*index)
2049 } else {
2050 None
2051 }
2052 })
2053 .collect()
2054 };
2055 inner.remove_blocks(&to_remove);
2056
2057 let skipped_body_blocks =
2062 self.consensus.get_blocks_needing_bodies();
2063 if !skipped_body_blocks.is_empty() || !invalid_set.is_empty() {
2064 warn!("Has invalid blocks after downloading block bodies!");
2065 self.consensus.reset();
2069
2070 let all_block_indices: HashSet<_> = inner
2071 .hash_to_arena_indices
2072 .iter()
2073 .map(|(_, i)| *i)
2074 .collect();
2075 let sorted_blocks = inner.topological_sort(all_block_indices);
2077 for i in sorted_blocks {
2078 self.consensus
2079 .on_new_block(&inner.arena[i].block_header.hash());
2080 }
2081 let new_to_fill_blocks: HashSet<_> =
2082 self.consensus.get_blocks_needing_bodies();
2083 if !new_to_fill_blocks.is_empty() {
2084 warn!(
2088 "{} new block bodies to get",
2089 new_to_fill_blocks.len()
2090 );
2091 inner.block_to_fill_set = new_to_fill_blocks;
2092 return false;
2093 }
2094 }
2095 }
2096 self.consensus.construct_pivot_state();
2097 self.inner.write().locked_for_catchup = false;
2098 true
2099 }
2100
2101 pub fn check_not_ready_frontier(&self, header_only: bool) {
2106 debug!("check_not_ready_frontier starts");
2107 let mut inner = self.inner.write();
2108 if inner.locked_for_catchup {
2109 return;
2112 }
2113 if header_only {
2114 for b in inner.pos_not_ready_blocks_frontier.clone() {
2115 debug!(
2116 "check_not_ready_frontier: check {:?}",
2117 inner.arena[b].block_header.hash()
2118 );
2119 if inner.new_to_be_header_graph_ready(b) {
2120 self.propagate_header_graph_status(
2121 &mut *inner,
2122 vec![b],
2123 true, b,
2125 true, true, );
2128 }
2129 }
2130 } else {
2131 for b in inner.pos_not_ready_blocks_frontier.clone() {
2132 debug!(
2133 "check_not_ready_frontier: check {:?}",
2134 inner.arena[b].block_header.hash()
2135 );
2136 if inner.new_to_be_header_graph_ready(b) {
2137 self.propagate_header_graph_status(
2138 &mut *inner,
2139 vec![b],
2140 true, b,
2142 false, true, );
2145 }
2146 if inner.new_to_be_block_graph_ready(b) {
2149 debug!("new graph ready found");
2150 self.propagate_graph_status(&mut *inner, vec![b]);
2151 }
2152 }
2153 }
2154 }
2155}
2156
2157impl Graph for SynchronizationGraphInner {
2158 type NodeIndex = usize;
2159}
2160
2161impl TreeGraph for SynchronizationGraphInner {
2162 fn parent(&self, node_index: Self::NodeIndex) -> Option<Self::NodeIndex> {
2163 if self.arena[node_index].parent != NULL {
2164 Some(self.arena[node_index].parent)
2165 } else {
2166 None
2167 }
2168 }
2169
2170 fn referees(&self, node_index: Self::NodeIndex) -> Vec<Self::NodeIndex> {
2171 self.arena[node_index].referees.clone()
2172 }
2173}
2174
2175impl RichTreeGraph for SynchronizationGraphInner {
2176 fn children(&self, node_index: Self::NodeIndex) -> Vec<Self::NodeIndex> {
2177 self.arena[node_index].children.clone()
2178 }
2179
2180 fn referrers(&self, node_index: Self::NodeIndex) -> Vec<Self::NodeIndex> {
2181 self.arena[node_index].referrers.clone()
2182 }
2183}
2184
2185pub enum BlockInsertionResult {
2186 AlreadyProcessed,
2188 ShouldRelay,
2190 SuccessWithoutRelay,
2192 Invalid,
2195 RequestAgain,
2199 Ignored,
2203}
2204
2205impl BlockInsertionResult {
2206 pub fn is_valid(&self) -> bool {
2207 matches!(
2208 self,
2209 BlockInsertionResult::AlreadyProcessed
2210 | BlockInsertionResult::ShouldRelay
2211 | BlockInsertionResult::SuccessWithoutRelay
2212 )
2213 }
2214
2215 pub fn is_invalid(&self) -> bool {
2216 matches!(self, BlockInsertionResult::Invalid)
2217 }
2218
2219 pub fn should_relay(&self) -> bool {
2220 matches!(self, BlockInsertionResult::ShouldRelay)
2221 }
2222
2223 pub fn request_again(&self) -> bool {
2224 matches!(self, BlockInsertionResult::RequestAgain)
2225 }
2226}
2227
2228pub enum BlockHeaderInsertionResult {
2229 AlreadyProcessedInConsensus,
2232 AlreadyProcessedInSync,
2235 NewValid,
2237 Invalid,
2240 TemporarySkipped,
2242}
2243
2244impl BlockHeaderInsertionResult {
2245 pub fn is_new_valid(&self) -> bool {
2246 matches!(self, BlockHeaderInsertionResult::NewValid)
2247 }
2248
2249 pub fn is_invalid(&self) -> bool {
2250 matches!(self, BlockHeaderInsertionResult::Invalid)
2251 }
2252
2253 pub fn should_process_body(&self) -> bool {
2254 matches!(
2255 self,
2256 BlockHeaderInsertionResult::NewValid
2257 | BlockHeaderInsertionResult::AlreadyProcessedInSync
2258 )
2259 }
2260}