pub(crate) mod finalised_state;
pub(crate) mod mempool;
mod mockchain_tests;
mod non_finalised_state;
mod poll;
mod proptest_blockgen;
mod sync_loop;
pub(crate) mod types;
pub(crate) mod vectors;
pub(crate) fn init_tracing() {
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")),
)
.with_timer(tracing_subscriber::fmt::time::UtcTime::rfc_3339())
.with_target(true)
.try_init()
.unwrap();
}
use std::path::{Path, PathBuf};
use tempfile::TempDir;
use tokio::sync::OnceCell;
use tokio::time::Duration;
use zaino_common::{network::ActivationHeights, DatabaseConfig, Network, StorageConfig};
use crate::{
chain_index::{
finalised_state::ZainoDB,
finalized_height_floor,
source::mockchain_source::MockchainSource,
tests::vectors::{
build_active_mockchain_source, build_mockchain_source, copy_dir_recursive,
load_test_vectors, sync_db_with_blockdata,
},
ChainIndex, NodeBackedChainIndex, NodeBackedChainIndexSubscriber, SyncTimings,
},
BlockCacheConfig,
};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum MockchainMode {
Active,
Static,
}
async fn load_test_vectors_and_sync_chain_index(
mode: MockchainMode,
) -> (
Vec<vectors::TestVectorBlockData>,
NodeBackedChainIndex<MockchainSource>,
NodeBackedChainIndexSubscriber<MockchainSource>,
MockchainSource,
) {
load_with_settings(mode, SyncTimings::default(), Duration::from_millis(25)).await
}
async fn load_test_vectors_and_sync_chain_index_with_timings(
mode: MockchainMode,
sync_timings: SyncTimings,
) -> (
Vec<vectors::TestVectorBlockData>,
NodeBackedChainIndex<MockchainSource>,
NodeBackedChainIndexSubscriber<MockchainSource>,
MockchainSource,
) {
load_with_settings(mode, sync_timings, Duration::from_millis(25)).await
}
async fn load_with_settings(
mode: MockchainMode,
sync_timings: SyncTimings,
setup_poll_interval: Duration,
) -> (
Vec<vectors::TestVectorBlockData>,
NodeBackedChainIndex<MockchainSource>,
NodeBackedChainIndexSubscriber<MockchainSource>,
MockchainSource,
) {
init_tracing();
let blocks = load_test_vectors().unwrap().blocks;
let source = match mode {
MockchainMode::Active => build_active_mockchain_source(150, blocks.clone()),
MockchainMode::Static => build_mockchain_source(blocks.clone()),
};
let temp_dir: TempDir = tempfile::tempdir().unwrap();
let db_path: PathBuf = temp_dir.path().to_path_buf();
let seed = v1_finalised_seed_dir(mode).await;
copy_dir_recursive(seed, &db_path).unwrap();
let config = BlockCacheConfig {
storage: StorageConfig {
database: DatabaseConfig {
path: db_path,
..Default::default()
},
..Default::default()
},
db_version: 1,
network: Network::Regtest(ActivationHeights::default()),
};
let indexer = NodeBackedChainIndex::new_with_sync_timings(source.clone(), config, sync_timings)
.await
.unwrap();
let index_reader = indexer.subscriber();
let expected_nfs_tip = source.active_height();
loop {
let nfs_ready = match index_reader.snapshot_nonfinalized_state().await {
Ok(snap) => snap
.get_nfs_snapshot()
.is_some_and(|nfs| nfs.best_tip.height.0 == expected_nfs_tip),
Err(_) => false,
};
if nfs_ready {
break;
}
tokio::time::sleep(setup_poll_interval).await;
}
(blocks, indexer, index_reader, source)
}
static V1_SEED_ACTIVE: OnceCell<TempDir> = OnceCell::const_new();
static V1_SEED_STATIC: OnceCell<TempDir> = OnceCell::const_new();
async fn v1_finalised_seed_dir(mode: MockchainMode) -> &'static Path {
let cell = match mode {
MockchainMode::Active => &V1_SEED_ACTIVE,
MockchainMode::Static => &V1_SEED_STATIC,
};
cell.get_or_init(|| async move {
let blocks = load_test_vectors().unwrap().blocks;
let source = match mode {
MockchainMode::Active => build_active_mockchain_source(150, blocks.clone()),
MockchainMode::Static => build_mockchain_source(blocks.clone()),
};
let target = finalized_height_floor(source.active_height()).0;
let temp_dir: TempDir = tempfile::tempdir().unwrap();
let config = BlockCacheConfig {
storage: StorageConfig {
database: DatabaseConfig {
path: temp_dir.path().to_path_buf(),
..Default::default()
},
..Default::default()
},
db_version: 1,
network: Network::Regtest(ActivationHeights::default()),
};
let zaino_db = ZainoDB::spawn(config, source).await.unwrap();
sync_db_with_blockdata(zaino_db.router(), blocks, Some(target)).await;
zaino_db.wait_until_ready().await;
zaino_db.shutdown().await.unwrap();
temp_dir
})
.await
.path()
}