Skip to main content

dig_blockstore/
lib.rs

1//! # dig-blockstore
2//!
3//! Persistent storage for validated DIG L2 blocks: RocksDB layout, canonical
4//! height→hash indexing, caching, rollback, pruning, and checkpoints — see
5//! `docs/resources/SPEC.md` for the authoritative architecture.
6//!
7//! ## Module layout (STR-002)
8//!
9//! The subtree under `src/` mirrors [`STR-002`](../docs/requirements/domains/crate_structure/specs/STR-002.md)
10//! and **§16 — Crate boundary** in `docs/resources/SPEC.md`: store, config, types,
11//! constants, [`cf_options`](crate::cf_options) ([`TYP-003`](../docs/requirements/domains/storage_types/specs/TYP-003.md)),
12//! errors, encoding, cache, canonical index, compression, async pipeline,
13//! and snapshot I/O.
14//!
15//! ## Public API surface (STR-003)
16//!
17//! Primary types, constants, and key helpers are re-exported at the crate root per
18//! [`STR-003`](../docs/requirements/domains/crate_structure/specs/STR-003.md) and **§15** in
19//! `docs/resources/SPEC.md`. Submodules remain `pub` so integration tests and advanced callers
20//! can use qualified paths (e.g. [`store::BlockStore`](crate::store::BlockStore)).
21//!
22//! ## STR-001 dependency smoke
23//!
24//! [`str001_dependency_smoke`] forces every direct `Cargo.toml` dependency to link,
25//! catching resolution failures early ([`STR-001`](../docs/requirements/domains/crate_structure/specs/STR-001.md)).
26// `memmap2` mapping constructors are `unsafe` ([`CAN-001`](docs/requirements/domains/canonical_chain/specs/CAN-001.md));
27// isolated, documented `unsafe` lives in [`crate::canonical::mmap`]. Use `deny` (not `forbid`) so that module can opt in.
28#![deny(unsafe_code)]
29
30pub mod cache;
31pub mod canonical;
32pub mod cf_options;
33pub mod compression;
34pub mod config;
35pub mod constants;
36pub mod encoding;
37pub mod error;
38pub mod pipeline;
39pub mod snapshot;
40pub mod store;
41pub mod types;
42/// Chia [`Streamable`] wire serialization for [`dig_block::L2Block`] ([`SER-003`](../docs/requirements/domains/serialization/specs/SER-003.md)).
43pub mod wire;
44
45// --- STR-003 + API-001: flat public API (`use dig_blockstore::{…}`) ---
46//
47// Re-export upstream types that appear in public method signatures so consumers
48// can write `use dig_blockstore::{BlockStore, L2Block, Bytes32}` without adding
49// dig-block or chia-protocol to their own Cargo.toml.
50pub use chia_protocol::Bytes32;
51pub use config::BlockStoreConfig;
52pub use constants::{
53    CF_ATTESTED, CF_BLOCKS, CF_CANONICAL, CF_CHECKPOINTS, CF_HEADERS, CF_METADATA,
54    DEFAULT_BLOCK_CACHE_CAPACITY, DEFAULT_BLOCK_CACHE_SIZE, DEFAULT_BLOOM_BITS_PER_KEY,
55    DEFAULT_HEADER_CACHE_CAPACITY, DEFAULT_MAX_DECOMPRESSED_BLOCK_BYTES, DEFAULT_MAX_OPEN_FILES,
56    DEFAULT_WRITE_BUFFER_SIZE, DICT_TARGET_SIZE, DICT_TRAINING_THRESHOLD, META_GENESIS_HASH,
57    META_MIN_HEIGHT, META_SCHEMA_VERSION, META_TIP, META_ZSTD_DICT, SCHEMA_VERSION,
58    ZSTD_COMPRESSION_LEVEL,
59};
60pub use dig_block::{AttestedBlock, BlockStatus, L2Block, L2BlockHeader};
61pub use encoding::{
62    decode_epoch_key, decode_height_key, epoch_key, hash_key, height_key, metadata_key,
63};
64pub use error::{
65    BlockStoreError, ERR_ASYNC_JOIN_PREFIX, ERR_INIT_GENESIS_ALREADY_INITIALIZED,
66    ERR_INIT_GENESIS_READ_ONLY, ERR_MUTATION_READ_ONLY, ERR_OPEN_READONLY_PATH_MISSING_PREFIX,
67    ERR_UPDATE_STATUS_RECORD_NOT_CACHED_PREFIX,
68};
69pub use snapshot::{SnapshotManifest, SNAPSHOT_VERSION};
70pub use store::{BlockStore, StreamBlocksInRange};
71pub use types::{BlockRecord, ChainTip, ReorgResult, StorageStats, StoredCheckpoint};
72pub use wire::{block_from_wire_bytes, block_to_wire_bytes};
73
74// --- API-003: Compile-time thread-safety assertions ---
75// BlockStore is designed for concurrent use across tokio tasks and thread pools.
76// All public methods take &self. Clone is cheap (Arc<Inner>).
77const _: () = {
78    fn _assert_send<T: Send>() {}
79    fn _assert_sync<T: Sync>() {}
80    fn _assert_clone<T: Clone>() {}
81    fn _assertions() {
82        _assert_send::<BlockStore>();
83        _assert_sync::<BlockStore>();
84        _assert_clone::<BlockStore>();
85        _assert_send::<BlockStoreError>();
86        _assert_sync::<BlockStoreError>();
87    }
88};
89
90// L2BlockHeader re-exported above via `pub use dig_block::...`
91use dig_constants::NetworkConstants;
92use dig_epoch::BLOCKS_PER_EPOCH;
93
94/// Exercises every **direct** `[dependencies]` entry from STR-001 so `cargo check`
95/// cannot succeed if any crate fails to resolve.
96///
97/// **Semantic links:**
98/// - Requirement & test plan: `docs/requirements/domains/crate_structure/specs/STR-001.md`
99/// - Normative summary: `docs/requirements/domains/crate_structure/NORMATIVE.md`
100/// - Spec §1.2: `docs/resources/SPEC.md`
101#[doc(hidden)]
102pub fn str001_dependency_smoke() -> usize {
103    use chia_bls::Signature;
104    use chia_protocol::Bytes32;
105    use chia_sha2::Sha256;
106    use chia_traits::Streamable;
107
108    fn touch_streamable<T: Streamable>(v: &T) {
109        let _ = core::mem::size_of_val(v);
110    }
111
112    #[derive(serde::Serialize)]
113    struct SerdeSmoke {
114        tag: u8,
115    }
116
117    #[derive(thiserror::Error, Debug)]
118    enum SmokeErr {
119        #[error("str-001 dependency smoke")]
120        Smoke,
121    }
122
123    let _: Bytes32 = Bytes32::default();
124    let _epoch: u64 = BLOCKS_PER_EPOCH;
125    let _net = core::mem::size_of::<NetworkConstants>();
126    let _hdr = core::mem::size_of::<L2BlockHeader>();
127    let _rocksdb = core::mem::size_of::<rocksdb::DB>();
128    let _zstd = zstd::DEFAULT_COMPRESSION_LEVEL;
129    let _codec = bincode::serialized_size(&0u8).unwrap_or(0);
130    let _serde = bincode::serialize(&SerdeSmoke { tag: 0 })
131        .map(|b| b.len())
132        .unwrap_or(0);
133    let _err = SmokeErr::Smoke.to_string().len();
134    let _sig = core::mem::size_of::<Signature>();
135    touch_streamable(&Bytes32::default());
136    let mut sha = Sha256::new();
137    sha.update(b"str001");
138    let _sha_len = sha.finalize().len();
139    let _lock = core::mem::size_of::<parking_lot::RawRwLock>();
140    let _lru = core::mem::size_of::<lru::LruCache<u8, u8>>();
141    let _rt = core::mem::size_of::<tokio::runtime::Runtime>();
142    let _map = core::mem::size_of::<memmap2::MmapOptions>();
143
144    _hdr + _net
145        + _rocksdb
146        + _zstd as usize
147        + _codec as usize
148        + _serde
149        + _err
150        + _sig
151        + _sha_len
152        + _lock
153        + _lru
154        + _rt
155        + _map
156        + _epoch as usize
157}