use crate::{
config::Config,
model::stores::{
acceptance_data::DbAcceptanceDataStore,
block_transactions::DbBlockTransactionsStore,
block_window_cache::BlockWindowCacheStore,
daa::DbDaaStore,
depth::DbDepthStore,
ghostdag::{CompactGhostdagData, DbGhostdagStore},
headers::{CompactHeaderData, DbHeadersStore},
headers_selected_tip::DbHeadersSelectedTipStore,
past_pruning_points::DbPastPruningPointsStore,
pruning::DbPruningStore,
pruning_utxoset::PruningUtxosetStores,
reachability::{DbReachabilityStore, ReachabilityData},
relations::DbRelationsStore,
selected_chain::DbSelectedChainStore,
statuses::DbStatusesStore,
tips::DbTipsStore,
utxo_diffs::DbUtxoDiffsStore,
utxo_multisets::DbUtxoMultisetsStore,
virtual_state::{LkgVirtualState, VirtualStores},
DB,
},
processes::{ghostdag::ordering::SortableBlock, reachability::inquirer as reachability, relations},
};
use super::cache_policy_builder::CachePolicyBuilder as PolicyBuilder;
use itertools::Itertools;
use kaspa_consensus_core::{blockstatus::BlockStatus, BlockHashSet};
use kaspa_database::registry::DatabaseStorePrefixes;
use kaspa_hashes::Hash;
use parking_lot::RwLock;
use std::{ops::DerefMut, sync::Arc};
pub struct ConsensusStorage {
db: Arc<DB>,
pub statuses_store: Arc<RwLock<DbStatusesStore>>,
pub relations_stores: Arc<RwLock<Vec<DbRelationsStore>>>,
pub reachability_store: Arc<RwLock<DbReachabilityStore>>,
pub reachability_relations_store: Arc<RwLock<DbRelationsStore>>,
pub pruning_point_store: Arc<RwLock<DbPruningStore>>,
pub headers_selected_tip_store: Arc<RwLock<DbHeadersSelectedTipStore>>,
pub body_tips_store: Arc<RwLock<DbTipsStore>>,
pub pruning_utxoset_stores: Arc<RwLock<PruningUtxosetStores>>,
pub virtual_stores: Arc<RwLock<VirtualStores>>,
pub selected_chain_store: Arc<RwLock<DbSelectedChainStore>>,
pub ghostdag_stores: Arc<Vec<Arc<DbGhostdagStore>>>,
pub ghostdag_primary_store: Arc<DbGhostdagStore>,
pub headers_store: Arc<DbHeadersStore>,
pub block_transactions_store: Arc<DbBlockTransactionsStore>,
pub past_pruning_points_store: Arc<DbPastPruningPointsStore>,
pub daa_excluded_store: Arc<DbDaaStore>,
pub depth_store: Arc<DbDepthStore>,
pub utxo_diffs_store: Arc<DbUtxoDiffsStore>,
pub utxo_multisets_store: Arc<DbUtxoMultisetsStore>,
pub acceptance_data_store: Arc<DbAcceptanceDataStore>,
pub block_window_cache_for_difficulty: Arc<BlockWindowCacheStore>,
pub block_window_cache_for_past_median_time: Arc<BlockWindowCacheStore>,
pub lkg_virtual_state: LkgVirtualState,
}
impl ConsensusStorage {
pub fn new(db: Arc<DB>, config: Arc<Config>) -> Arc<Self> {
let scale_factor = config.ram_scale;
let scaled = |s| (s as f64 * scale_factor) as usize;
let params = &config.params;
let perf_params = &config.perf;
let pruning_depth = params.pruning_depth as usize;
let pruning_size_for_caches = (params.pruning_depth + params.finality_depth) as usize; let level_lower_bound = 2 * params.pruning_proof_m as usize;
let daa_excluded_budget = scaled(30_000_000);
let statuses_budget = scaled(30_000_000);
let reachability_data_budget = scaled(20_000_000);
let reachability_sets_budget = scaled(20_000_000); let ghostdag_compact_budget = scaled(15_000_000);
let headers_compact_budget = scaled(5_000_000);
let parents_budget = scaled(40_000_000); let children_budget = scaled(5_000_000); let ghostdag_budget = scaled(80_000_000); let headers_budget = scaled(80_000_000);
let transactions_budget = scaled(40_000_000);
let utxo_diffs_budget = scaled(40_000_000);
let block_window_budget = scaled(200_000_000); let acceptance_data_budget = scaled(40_000_000);
let daa_excluded_bytes = size_of::<Hash>() + size_of::<BlockHashSet>(); let status_bytes = size_of::<Hash>() + size_of::<BlockStatus>();
let reachability_data_bytes = size_of::<Hash>() + size_of::<ReachabilityData>();
let ghostdag_compact_bytes = size_of::<Hash>() + size_of::<CompactGhostdagData>();
let headers_compact_bytes = size_of::<Hash>() + size_of::<CompactHeaderData>();
let difficulty_window_bytes = params.difficulty_window_size(0) * size_of::<SortableBlock>();
let median_window_bytes = params.past_median_time_window_size(0) * size_of::<SortableBlock>();
let daa_excluded_builder =
PolicyBuilder::new().max_items(pruning_depth).bytes_budget(daa_excluded_budget).unit_bytes(daa_excluded_bytes).untracked(); let statuses_builder =
PolicyBuilder::new().max_items(pruning_size_for_caches).bytes_budget(statuses_budget).unit_bytes(status_bytes).untracked();
let reachability_data_builder = PolicyBuilder::new()
.max_items(pruning_size_for_caches)
.bytes_budget(reachability_data_budget)
.unit_bytes(reachability_data_bytes)
.untracked();
let ghostdag_compact_builder = PolicyBuilder::new()
.max_items(pruning_size_for_caches)
.bytes_budget(ghostdag_compact_budget)
.unit_bytes(ghostdag_compact_bytes)
.min_items(level_lower_bound)
.untracked();
let headers_compact_builder = PolicyBuilder::new()
.max_items(pruning_size_for_caches)
.bytes_budget(headers_compact_budget)
.unit_bytes(headers_compact_bytes)
.untracked();
let parents_builder = PolicyBuilder::new()
.bytes_budget(parents_budget)
.unit_bytes(size_of::<Hash>())
.min_items(level_lower_bound)
.tracked_units();
let children_builder = PolicyBuilder::new()
.bytes_budget(children_budget)
.unit_bytes(size_of::<Hash>())
.min_items(level_lower_bound)
.tracked_units();
let reachability_sets_builder =
PolicyBuilder::new().bytes_budget(reachability_sets_budget).unit_bytes(size_of::<Hash>()).tracked_units();
let difficulty_window_builder = PolicyBuilder::new()
.max_items(perf_params.block_window_cache_size)
.bytes_budget(block_window_budget)
.unit_bytes(difficulty_window_bytes)
.untracked();
let median_window_builder = PolicyBuilder::new()
.max_items(perf_params.block_window_cache_size)
.bytes_budget(block_window_budget)
.unit_bytes(median_window_bytes)
.untracked();
let ghostdag_builder = PolicyBuilder::new().bytes_budget(ghostdag_budget).min_items(level_lower_bound).tracked_bytes();
let headers_builder = PolicyBuilder::new().bytes_budget(headers_budget).tracked_bytes();
let utxo_diffs_builder = PolicyBuilder::new().bytes_budget(utxo_diffs_budget).tracked_bytes();
let block_data_builder = PolicyBuilder::new().max_items(perf_params.block_data_cache_size).untracked();
let header_data_builder = PolicyBuilder::new().max_items(perf_params.header_data_cache_size).untracked();
let utxo_set_builder = PolicyBuilder::new().max_items(perf_params.utxo_set_cache_size).untracked();
let transactions_builder = PolicyBuilder::new().bytes_budget(transactions_budget).tracked_bytes();
let acceptance_data_builder = PolicyBuilder::new().bytes_budget(acceptance_data_budget).tracked_bytes();
let past_pruning_points_builder = PolicyBuilder::new().max_items(1024).untracked();
let statuses_store = Arc::new(RwLock::new(DbStatusesStore::new(db.clone(), statuses_builder.build())));
let relations_stores = Arc::new(RwLock::new(
(0..=params.max_block_level)
.map(|level| {
DbRelationsStore::new(
db.clone(),
level,
parents_builder.downscale(level).build(),
children_builder.downscale(level).build(),
)
})
.collect_vec(),
));
let reachability_store = Arc::new(RwLock::new(DbReachabilityStore::new(
db.clone(),
reachability_data_builder.build(),
reachability_sets_builder.build(),
)));
let reachability_relations_store = Arc::new(RwLock::new(DbRelationsStore::with_prefix(
db.clone(),
DatabaseStorePrefixes::ReachabilityRelations.as_ref(),
parents_builder.build(),
children_builder.build(),
)));
let ghostdag_stores = Arc::new(
(0..=params.max_block_level)
.map(|level| {
Arc::new(DbGhostdagStore::new(
db.clone(),
level,
ghostdag_builder.downscale(level).build(),
ghostdag_compact_builder.downscale(level).build(),
))
})
.collect_vec(),
);
let ghostdag_primary_store = ghostdag_stores[0].clone();
let daa_excluded_store = Arc::new(DbDaaStore::new(db.clone(), daa_excluded_builder.build()));
let headers_store = Arc::new(DbHeadersStore::new(db.clone(), headers_builder.build(), headers_compact_builder.build()));
let depth_store = Arc::new(DbDepthStore::new(db.clone(), header_data_builder.build()));
let selected_chain_store = Arc::new(RwLock::new(DbSelectedChainStore::new(db.clone(), header_data_builder.build())));
let pruning_point_store = Arc::new(RwLock::new(DbPruningStore::new(db.clone())));
let past_pruning_points_store = Arc::new(DbPastPruningPointsStore::new(db.clone(), past_pruning_points_builder.build()));
let pruning_utxoset_stores = Arc::new(RwLock::new(PruningUtxosetStores::new(db.clone(), utxo_set_builder.build())));
let block_transactions_store = Arc::new(DbBlockTransactionsStore::new(db.clone(), transactions_builder.build()));
let utxo_diffs_store = Arc::new(DbUtxoDiffsStore::new(db.clone(), utxo_diffs_builder.build()));
let utxo_multisets_store = Arc::new(DbUtxoMultisetsStore::new(db.clone(), block_data_builder.build()));
let acceptance_data_store = Arc::new(DbAcceptanceDataStore::new(db.clone(), acceptance_data_builder.build()));
let headers_selected_tip_store = Arc::new(RwLock::new(DbHeadersSelectedTipStore::new(db.clone())));
let body_tips_store = Arc::new(RwLock::new(DbTipsStore::new(db.clone())));
let block_window_cache_for_difficulty = Arc::new(BlockWindowCacheStore::new(difficulty_window_builder.build()));
let block_window_cache_for_past_median_time = Arc::new(BlockWindowCacheStore::new(median_window_builder.build()));
let lkg_virtual_state = LkgVirtualState::default();
let virtual_stores =
Arc::new(RwLock::new(VirtualStores::new(db.clone(), lkg_virtual_state.clone(), utxo_set_builder.build())));
reachability::init(reachability_store.write().deref_mut()).unwrap();
relations::init(reachability_relations_store.write().deref_mut());
Arc::new(Self {
db,
statuses_store,
relations_stores,
reachability_relations_store,
reachability_store,
ghostdag_stores,
ghostdag_primary_store,
pruning_point_store,
headers_selected_tip_store,
body_tips_store,
headers_store,
block_transactions_store,
pruning_utxoset_stores,
virtual_stores,
selected_chain_store,
acceptance_data_store,
past_pruning_points_store,
daa_excluded_store,
depth_store,
utxo_diffs_store,
utxo_multisets_store,
block_window_cache_for_difficulty,
block_window_cache_for_past_median_time,
lkg_virtual_state,
})
}
}