kaspa_consensus/processes/
block_depth.rs1use kaspa_consensus_core::blockhash::ORIGIN;
2use kaspa_hashes::Hash;
3use std::sync::Arc;
4
5use crate::model::{
6 services::reachability::{MTReachabilityService, ReachabilityService},
7 stores::{
8 depth::DepthStoreReader,
9 ghostdag::{GhostdagData, GhostdagStoreReader},
10 reachability::ReachabilityStoreReader,
11 },
12};
13
14#[derive(Clone)]
15pub struct BlockDepthManager<S: DepthStoreReader, U: ReachabilityStoreReader, V: GhostdagStoreReader> {
16 merge_depth: u64,
17 finality_depth: u64,
18 genesis_hash: Hash,
19 depth_store: Arc<S>,
20 reachability_service: MTReachabilityService<U>,
21 ghostdag_store: Arc<V>,
22}
23
24impl<S: DepthStoreReader, U: ReachabilityStoreReader, V: GhostdagStoreReader> BlockDepthManager<S, U, V> {
25 pub fn new(
26 merge_depth: u64,
27 finality_depth: u64,
28 genesis_hash: Hash,
29 depth_store: Arc<S>,
30 reachability_service: MTReachabilityService<U>,
31 ghostdag_store: Arc<V>,
32 ) -> Self {
33 Self { merge_depth, finality_depth, genesis_hash, depth_store, reachability_service, ghostdag_store }
34 }
35 pub fn calc_merge_depth_root(&self, ghostdag_data: &GhostdagData, pruning_point: Hash) -> Hash {
36 self.calculate_block_at_depth(ghostdag_data, self.merge_depth, pruning_point)
37 }
38
39 pub fn calc_finality_point(&self, ghostdag_data: &GhostdagData, pruning_point: Hash) -> Hash {
40 self.calculate_block_at_depth(ghostdag_data, self.finality_depth, pruning_point)
41 }
42
43 fn calculate_block_at_depth(&self, ghostdag_data: &GhostdagData, depth: u64, pruning_point: Hash) -> Hash {
44 assert!(depth == self.merge_depth || depth == self.finality_depth);
45
46 if ghostdag_data.blue_score < depth {
47 return self.genesis_hash;
48 }
49
50 let pp_bs = self.ghostdag_store.get_blue_score(pruning_point).unwrap();
51
52 if ghostdag_data.blue_score < pp_bs + depth {
53 return ORIGIN;
54 }
55
56 if !self.reachability_service.is_chain_ancestor_of(pruning_point, ghostdag_data.selected_parent) {
57 return ORIGIN;
58 }
59
60 let mut current = if depth == self.merge_depth {
61 self.depth_store.merge_depth_root(ghostdag_data.selected_parent).unwrap()
62 } else {
63 self.depth_store.finality_point(ghostdag_data.selected_parent).unwrap()
64 };
65
66 if current == ORIGIN {
70 current = pruning_point;
71 }
72
73 let required_blue_score = ghostdag_data.blue_score - depth;
74
75 for chain_block in self.reachability_service.forward_chain_iterator(current, ghostdag_data.selected_parent, true) {
76 if self.ghostdag_store.get_blue_score(chain_block).unwrap() >= required_blue_score {
77 break;
78 }
79
80 current = chain_block;
81 }
82
83 current
84 }
85
86 pub fn kosherizing_blues<'a>(
89 &'a self,
90 ghostdag_data: &'a GhostdagData,
91 merge_depth_root: Hash,
92 ) -> impl DoubleEndedIterator<Item = Hash> + 'a {
93 ghostdag_data
94 .mergeset_blues
95 .iter()
96 .copied()
97 .filter(move |blue| self.reachability_service.is_chain_ancestor_of(merge_depth_root, *blue))
98 }
99}