pub struct BlockStore { /* private fields */ }Expand description
Primary handle for all block persistence APIs.
§Chia blockchain analogy
This struct corresponds to BlockStore in chia-blockchain/chia/consensus/block_store.py.
Where Chia uses a single SQLite full_blocks table with Python LRU caches, DIG uses
RocksDB column families with Rust sharded LRU caches for higher throughput under
concurrent access. The API surface mirrors Chia’s: add_full_block → put_block,
get_full_block → get_block, get_block_record → get_record.
§Ownership
Thin Arc around [BlockStoreInner]: cheap Clone for tokio::task::spawn_blocking dispatch (BLK-007).
Field access on &BlockStore transparently reaches [BlockStoreInner] via std::ops::Deref.
Write pipeline (BLK-008): Self::pipeline_tx
holds the lazy mpsc::Sender outside [BlockStoreInner]. The worker task also keeps an Arc to inner
for RocksDB; if the sender lived on inner, dropping all BlockStore handles would still leave the sender
alive (circular retention), the channel would never close, and AC §8 “flush on shutdown” would not run.
§Construction
Use BlockStore::open for read-write access or BlockStore::open_readonly for read-only
access to an existing database. After construction, call BlockStore::init_genesis once
to initialize a new chain.
Implementations§
Source§impl BlockStore
impl BlockStore
Sourcepub fn get_hash_by_height(
&self,
height: u64,
) -> Result<Option<Bytes32>, BlockStoreError>
pub fn get_hash_by_height( &self, height: u64, ) -> Result<Option<Bytes32>, BlockStoreError>
Look up the canonical block hash at a given chain height.
§Algorithm (dual-layer, CAN-006)
- Hot path — mmap (
canonical.bin): O(1) pointer-offset read atheight * 32. ~10ns when the page is OS-cache-resident. Consulted first. - Cold path — RocksDB (
CF_CANONICAL): 1-10us key lookup with big-endian height key. Used when mmap is unavailable, disabled, or doesn’t cover the height.
§Returns
Ok(Some(hash))— height has a canonical block.Ok(None)— height is beyond the chain or was never canonicalized.
§Chia analogy
Corresponds to Blockchain.height_to_hash(height) in Chia, which reads from
an in-memory BlockHeightMap bytearray. DIG adds the durable RocksDB fallback.
§Derived methods
get_block_by_height,
get_header_by_height,
get_record_by_height, and
get_epoch_block_hashes all delegate through this.
Sourcepub fn set_canonical(&self, hash: &Bytes32) -> Result<(), BlockStoreError>
pub fn set_canonical(&self, hash: &Bytes32) -> Result<(), BlockStoreError>
CAN-003 — Mark an already stored block as canonical at its header height.
Algorithm (normative order — durable first):
Self::get_recordto prove the block is known (header row or cache); on miss →BlockStoreError::BlockNotInStore.DB::put_cfonCF_CANONICALwithheight_key(height) →hash_key(hash).canonical.binupdate via the same path asSelf::put_block(canonical_bin+CanonicalDenseFile::write_hash); skipped when mmap acceleration is disabled (reopen rebuilds from CF).- Set
BlockRecord::in_canonical_chain=truein [Self::record_cache] (record remains RAM-only perTYP-004) — does not changeBlockRecord::status; operators may still useSelf::update_statusfor lifecycle.
Idempotency: Re-calling with the same hash overwrites CF/mmap with identical bytes and leaves the record flag true (CAN-003 § Idempotency).
Height collisions: A second call for a different hash at the same height overwrites the height index (reorg staging); both blocks must exist in the store.
Read-only: BlockStoreError::Serialization with ERR_MUTATION_READ_ONLY — same contract as Self::put_block.
Sourcepub fn set_canonical_batch(
&self,
hashes: &[Bytes32],
) -> Result<(), BlockStoreError>
pub fn set_canonical_batch( &self, hashes: &[Bytes32], ) -> Result<(), BlockStoreError>
CAN-004 — Promote many already-stored blocks to the canonical height→hash index in one atomic RocksDB commit.
Why a separate API from Self::set_canonical: Reorgs (ROR-003) must flip many heights at once; a single WriteBatch gives all-or-nothing durability in CF_CANONICAL (NORMATIVE § CAN-004).
Algorithm (matches CAN-004 spec — validate, durable batch, then best-effort hot path):
- Fail-fast validation: For each input hash (in order),
Self::get_record. First miss →BlockStoreError::BlockNotInStorebefore anyWriteBatchmutation so callers never observe partial CF updates from this method. - Atomic CF write: One
WriteBatchwith allheight_key(record.height) → hash_key(hash)rows, thenDB::write. - Post-commit: Same as
Self::set_canonical— [Self::canonical_bin]’s mmap writer (CanonicalDenseFile::write_hashviaextend_writeinsrc/canonical/mmap.rs) per pair, then setBlockRecord::in_canonical_chainin [Self::record_cache] (re-insert on eviction, same as CAN-003).
Empty slice: Ok(())] immediately — no I/O ([CAN-004` acceptance).
Crash window: If the process dies after db.write but before mmap/cache finish, CAN-001 reopen rebuilds canonical.bin from CF_CANONICAL.
Read-only: Same BlockStoreError::Serialization + ERR_MUTATION_READ_ONLY contract as Self::put_block / Self::set_canonical.
Sourcepub fn extend_chain(&self, block: &L2Block) -> Result<bool, BlockStoreError>
pub fn extend_chain(&self, block: &L2Block) -> Result<bool, BlockStoreError>
Primary block ingestion API for normal chain-following operation.
Combines three operations into one call:
- Store —
Self::putwrites body toCF_BLOCKS, header toCF_HEADERS, and height→hash toCF_CANONICAL(canonical=true). - Tip advance —
Self::set_tippersists the new chain peak toCF_METADATAand updates the in-memoryRwLock<Option<ChainTip>>.
§Returns
Ok(true)— block was novel; stored, canonicalized, and tip advanced.Ok(false)— block hash was already in the store (duplicate); no changes made.
§Atomicity (CAN-005)
The individual operations are not wrapped in a single RocksDB transaction, but the ordering ensures safe crash recovery:
- Crash after
putbut beforeset_tip: block is stored and canonical, but tip is stale. On restart, tip can be corrected by scanning CF_CANONICAL. - The duplicate check via
has_blockmakes re-ingestion safe.
§Chia analogy
Corresponds to the storage portion of Blockchain.receive_block →
BlockStore.add_full_block in Chia, where the block is stored, the peak is
updated, and the height map is advanced.
§Errors
BlockStoreError::SerializationwithERR_MUTATION_READ_ONLYon read-only handles.- RocksDB or compression errors from the underlying
put/set_tipcalls.
Source§impl BlockStore
Compression and serialization methods on BlockStore.
impl BlockStore
Compression and serialization methods on BlockStore.
These are impl BlockStore (not BlockStoreInner) because they were originally
defined in the impl BlockStore block and callers use Self::serialize_header()
which resolves through BlockStore. Field access goes through Deref<Target=BlockStoreInner>.
pub fn serialize_header( header: &L2BlockHeader, ) -> Result<Vec<u8>, BlockStoreError>
Sourcepub fn deserialize_header(
bytes: &[u8],
) -> Result<L2BlockHeader, BlockStoreError>
pub fn deserialize_header( bytes: &[u8], ) -> Result<L2BlockHeader, BlockStoreError>
Deserialize a header from [CF_HEADERS] bytes (SER-002).
Read path: raw bincode only — callers MUST NOT pass zstd-compressed payloads (those belong in CF_BLOCKS
via Self::deserialize_block).
Sourcepub fn serialize_block(
&self,
block: &L2Block,
) -> Result<Vec<u8>, BlockStoreError>
pub fn serialize_block( &self, block: &L2Block, ) -> Result<Vec<u8>, BlockStoreError>
Serialize then zstd-compress a block for CF_BLOCKS (SER-001).
Pipeline: bincode::serialize → zstd::bulk::Compressor::with_dictionary when
[Self::use_compression_dict] and a dictionary are present; otherwise zstd::encode_all (plain zstd).
Errors: BlockStoreError::Serialization from bincode; BlockStoreError::Compression from zstd.
Sourcepub fn deserialize_block(
&self,
compressed: &[u8],
) -> Result<L2Block, BlockStoreError>
pub fn deserialize_block( &self, compressed: &[u8], ) -> Result<L2Block, BlockStoreError>
Reverse Self::serialize_block (SER-001).
Fallback: Dictionary decompress is attempted first when configured; on failure, plain
zstd::decode_all handles pre-dictionary payloads written before training (SER-005).
Hash invariance: Correct payloads MUST yield an L2Block whose L2Block::hash matches the original
pre-serialize block (SER-004; verified in tests/ser_004_tests.rs).
Errors: Decompression failures map to BlockStoreError::Serialization so callers see a single
“payload unusable” surface for malformed CF_BYTES; bincode structural errors also use Serialization.
Sourcepub fn block_count(&self) -> Result<u64, BlockStoreError>
pub fn block_count(&self) -> Result<u64, BlockStoreError>
Full scan of CF_BLOCKS to count stored block rows.
Iterates every key in the column family; used by crate::BlockStore::stats and by
Self::maybe_train_dictionary to detect when the training threshold is crossed
(SER-005).
Sourcepub fn init_dictionary(&self) -> Result<(), BlockStoreError>
pub fn init_dictionary(&self) -> Result<(), BlockStoreError>
SER-005 — Reload dictionary bytes from
META_ZSTD_DICT into memory after external maintenance (or to align with Self::train_dictionary
persistence).
Startup: Self::open already embeds this via [load_zstd_dict_from_db]; public callers use
init_dictionary when a second process trains the dictionary or metadata is repaired online.
Source§impl BlockStore
impl BlockStore
Sourcepub fn stream_blocks_in_range(
&self,
start: u64,
end: u64,
) -> Result<StreamBlocksInRange<'_>, BlockStoreError>
pub fn stream_blocks_in_range( &self, start: u64, end: u64, ) -> Result<StreamBlocksInRange<'_>, BlockStoreError>
Stream canonical blocks from height start through end inclusive (BLK-006).
Phase 1 — canonical walk: rocksdb::DB::iterator_cf_opt over CF_CANONICAL with
ReadOptions::set_readahead_size and iterate bounds
(KEY-002 big-endian order).
Phase 2 — lazy bodies: The returned StreamBlocksInRange walks the captured (height, hash) slice and,
for each entry, serves ShardedBlockCache hits without RocksDB, or
rocksdb::DB::get_cf_opt on CF_BLOCKS with the same readahead hint (separate ReadOptions
instance so canonical and block reads each carry the configured hint).
Why two phases: A live RocksDB iterator over CF_CANONICAL cannot coexist with mutable/immutable borrows
of block_cache / decompressors on every Iterator::next without self-referential structs; materializing
the height→hash list preserves readahead on the canonical scan while keeping the public API safe and 'static-free.
Errors: Missing CF_BLOCKS row for a canonical hash yields BlockStoreError::BlockNotFound from the stream
(BLK-006 AC §6). Malformed canonical keys/values map to BlockStoreError::Serialization.
Empty / inverted range: If start > end, returns an iterator that yields immediately without I/O.
Sourcepub async fn put_pipelined(
&self,
block: L2Block,
canonical: bool,
) -> Result<Receiver<Result<bool, BlockStoreError>>, BlockStoreError>
pub async fn put_pipelined( &self, block: L2Block, canonical: bool, ) -> Result<Receiver<Result<bool, BlockStoreError>>, BlockStoreError>
Async batched ingest (BLK-008, IMPLEMENTATION_ORDER.md Phase 5).
Channel + batching (NORMATIVE §1–3): Enqueues into a bounded mpsc queue; a background task accumulates
up to pipeline_batch_size jobs or until pipeline_flush_ms elapses,
then applies one WriteBatch mirroring BlockStore::put_block semantics.
Per-block ack (IMPLEMENTATION_ORDER.md): The returned
oneshot::Receiver resolves to the same Result<bool, BlockStoreError> shape as BlockStore::put_block
(Ok(true) inserted, Ok(false) duplicate).
Runtime contract: The first call lazily spawns [run_write_pipeline] via tokio::spawn; therefore an
active tokio::runtime::Handle must exist (integration tests should use #[tokio::test]).
Sourcepub fn pipeline_write_batch_count(&self) -> u64
pub fn pipeline_write_batch_count(&self) -> u64
Count of successful RocksDB WriteBatch commits executed by the BLK-008 worker.
Instrumentation: Used by tests/blk_008_tests.rs to prove AC §4 “single WriteBatch per flush interval”.
Source§impl BlockStore
impl BlockStore
Sourcepub fn export_snapshot(
&self,
start_height: u64,
end_height: u64,
writer: &mut impl Write,
) -> Result<SnapshotManifest, BlockStoreError>
pub fn export_snapshot( &self, start_height: u64, end_height: u64, writer: &mut impl Write, ) -> Result<SnapshotManifest, BlockStoreError>
Export canonical blocks in [start_height, end_height] as a snapshot stream.
§Stream format (SNP-001)
SnapshotManifest(bincode-serialized)- For each height:
block_len: u32 LE+compressed_block_bytes - SHA-256 checksum (32 bytes) of all preceding bytes
Block bytes are read directly from CF_BLOCKS (pre-compressed) to avoid decompression/recompression overhead.
§Returns
The finalized SnapshotManifest with the computed checksum.
Sourcepub fn import_snapshot(
&self,
reader: &mut impl Read,
) -> Result<SnapshotManifest, BlockStoreError>
pub fn import_snapshot( &self, reader: &mut impl Read, ) -> Result<SnapshotManifest, BlockStoreError>
Import a snapshot stream, validating manifest, contiguity, parent links, and checksum.
§Algorithm (SNP-002)
- Read and validate
SnapshotManifest(schema version check). - For each block: read length-prefixed compressed bytes, decompress + deserialize
for validation, verify height contiguity and parent-child links, store via
put_block. - Verify trailing SHA-256 checksum.
§Returns
The SnapshotManifest read from the stream.
Source§impl BlockStore
impl BlockStore
Sourcepub fn open(config: BlockStoreConfig) -> Result<Self, BlockStoreError>
pub fn open(config: BlockStoreConfig) -> Result<Self, BlockStoreError>
Sourcepub fn open_readonly(path: impl AsRef<Path>) -> Result<Self, BlockStoreError>
pub fn open_readonly(path: impl AsRef<Path>) -> Result<Self, BlockStoreError>
Open an existing database read-only; fails if path does not exist (STR-004).
Sourcepub fn init_genesis(&self, block: &L2Block) -> Result<(), BlockStoreError>
pub fn init_genesis(&self, block: &L2Block) -> Result<(), BlockStoreError>
Initialize genesis: empty store only; atomic WriteBatch (STR-004).
Sourcepub fn disable_canonical_bin_acceleration(&self)
pub fn disable_canonical_bin_acceleration(&self)
Diagnostics / tests: Disable the mmap acceleration layer so height→hash resolution uses CF_CANONICAL
only until the next BlockStore::open (CAN-001 test plan: mmap fallback).
Production: Do not call — the next process restart re-syncs canonical.bin from RocksDB anyway.
Sourcepub fn tip(&self) -> Option<ChainTip>
pub fn tip(&self) -> Option<ChainTip>
Current chain tip — hash and height of the highest canonical block.
Returns the in-memory cached copy loaded from META_TIP at startup
and updated by BlockStore::set_tip, BlockStore::init_genesis, and future
extend_chain / rollback_to_height APIs.
§Performance
This is a hot-path accessor queried on every block ingestion for parent-hash validation.
The parking_lot::RwLock::read is lock-free on the uncontended fast path (~2-5ns).
No RocksDB I/O occurs.
§Chia analogy
Corresponds to BlockStore.get_peak() in Chia’s block_store.py.
Requirement: CAN-007.
Sourcepub fn height(&self) -> Option<u64>
pub fn height(&self) -> Option<u64>
Convenience accessor for the current canonical chain height.
Returns tip().map(|t| t.height) — None when the store has no tip (before genesis),
Some(0) after genesis, Some(n) after extending to height n.
Requirement: CAN-007 § Accessors.
Sourcepub fn set_tip(&self, tip: ChainTip) -> Result<(), BlockStoreError>
pub fn set_tip(&self, tip: ChainTip) -> Result<(), BlockStoreError>
Persist a new chain tip to CF_METADATA / META_TIP
and update the in-memory cache.
§Encoding
The value written is exactly 40 bytes: hash (32 bytes, raw Bytes32) || height (8 bytes, little-endian u64).
This matches ChainTip::to_bytes() and the
TYP-006 wire format.
§Ordering
RocksDB write is performed before updating the in-memory RwLock. If the write
fails, the in-memory tip remains unchanged (no stale state visible to concurrent readers).
§Errors
BlockStoreError::SerializationwithERR_MUTATION_READ_ONLYwhen called on a read-only handle.BlockStoreError::RocksDbon write failure.
§Update points (CAN-007)
| Operation | New Tip |
|---|---|
extend_chain (CAN-005) | Newly added block |
rollback_to_height (ROR-001) | Block at target height |
apply_reorg (ROR-003) | Last block in new chain |
init_genesis (STR-004) | Genesis block (height 0) |
Sourcepub fn warm_blocks_loaded_count(&self) -> usize
pub fn warm_blocks_loaded_count(&self) -> usize
Blocks successfully verified present while warming on last Self::open (STR-004 / CAC-006).
Sourcepub fn get_block(
&self,
hash: &Bytes32,
) -> Result<Option<L2Block>, BlockStoreError>
pub fn get_block( &self, hash: &Bytes32, ) -> Result<Option<L2Block>, BlockStoreError>
Serialize a block header for CF_HEADERS (SER-002).
Write path (normative): L2BlockHeader → bincode::serialize → raw bytes (no zstd). Headers are
small and read on every chain walk; skipping compression avoids framing overhead and decode latency
on the hot path (NORMATIVE.md § SER-002).
Errors: BlockStoreError::Serialization — same variant as corrupt block payloads so upper
layers can treat “bytes unusable” uniformly until ERR-* adds finer codes.
Write path: Self::put_block / Self::init_genesis insert fresh values so steady-state reads hit RAM.
Sourcepub fn has_block(&self, hash: &Bytes32) -> Result<bool, BlockStoreError>
pub fn has_block(&self, hash: &Bytes32) -> Result<bool, BlockStoreError>
BLK-011 — Whether any persisted row exists for hash without decoding zstd or bincode (NORMATIVE.md § BLK-011).
Cache first (AC §2): [Self::block_cache] and [Self::header_cache] are consulted via ShardedLruCache::contains (LruCache::peek — no LRU promotion).
RocksDB (AC §1): If both caches miss, probe CF_HEADERS then CF_BLOCKS using hash_key (same key layout as Self::put_block). The second probe covers edge cases where only a body row exists; normal Self::put_block writes both families together (BLK-001).
No deserialize / decompress (AC §3): Uses only DB::get_cf presence checks — returned bytes are discarded without calling Self::deserialize_block or Self::deserialize_header.
Instrumentation: This path does not increment Self::cf_blocks_physical_get_count (that counter remains exclusive to Self::get_block) so tests can prove cache-fast paths avoid the heavy read API (BLK-002 counter semantics).
Sourcepub fn stats(&self) -> Result<StorageStats, BlockStoreError>
pub fn stats(&self) -> Result<StorageStats, BlockStoreError>
BLK-012 — Aggregate StorageStats for monitoring / diagnostics (TYP-007, NORMATIVE BLK-012).
Row counts: Each *_count field is the number of keys in the corresponding column family from a linear
DB::iterator_cf scan (CF_BLOCKS, CF_HEADERS, CF_CANONICAL,
CF_CHECKPOINTS, CF_ATTESTED). This is exact for current store sizes (typical node counts) and
matches NORMATIVE wording (“reflects the total number of entries”). If full scans become too costly at scale,
a future revision may offer rocksdb.estimate-num-keys behind configuration with documented error bounds.
Tip / pruning: StorageStats::tip_height mirrors Self::tip (RAM snapshot loaded from META_TIP on open, updated by Self::init_genesis today). Self::put_block does not yet advance the tip (CAN-007); operators should not assume tip_height == max(block heights) until chain-tip APIs land. StorageStats::min_height reads
META_MIN_HEIGHT in CF_METADATA as 8 bytes little-endian u64 (storage_types/NORMATIVE); missing key means no prune watermark yet (PRN-004).
Disk estimate: StorageStats::total_size_bytes sums per-CF RocksDB property rocksdb.estimate-live-data-size
(live SST + memtable footprint estimate). It is not a byte-exact du of the directory; callers should treat
it as an order-of-magnitude health signal; use Self::flush / Self::compact before relying on
filesystem-level durability or space reclamation (BLK-013).
Sourcepub fn flush(&self) -> Result<(), BlockStoreError>
pub fn flush(&self) -> Result<(), BlockStoreError>
BLK-013 — Persist buffered engine state
(NORMATIVE BLK-013).
Semantics: First rocksdb::DB::flush_wal(true) so the write-ahead log is synced through the OS to
stable storage, then rocksdb::DB::flush to flush all column-family
memtables to SST files. Together this matches operators’ “make my recent writes durable” intent while staying
close to the BLK-013 spec snippet (which only showed flush() — WAL sync is required by NORMATIVE item 1’s
“WAL flush” wording).
Logical state: Does not mutate dig-blockstore caches, tip, or row keys — only RocksDB I/O.
Errors: Any rocksdb::Error maps to BlockStoreError::RocksDb (ERR-002).
Sourcepub fn compact(&self) -> Result<(), BlockStoreError>
pub fn compact(&self) -> Result<(), BlockStoreError>
BLK-013 — Request manual compaction on
every column family in crate::constants::ALL_COLUMN_FAMILIES (TYP-001).
Implementation: For each family, DB::compact_range_cf with a None
key range compacts the entire keyspace (RocksDB schedules background work). The rust-rocksdb binding
returns () from compact_range_cf (errors surface asynchronously); callers use this for space reclamation
and read amplification tuning, not as a transactional barrier.
Logical state: Compaction does not delete live keys written by Self::put_block / Self::init_genesis;
it merges SSTables. Same error mapping as Self::flush if future APIs gain fallible compaction entry points.
Sourcepub fn get_blocks_by_hash(
&self,
hashes: &[Bytes32],
) -> Result<Vec<Option<L2Block>>, BlockStoreError>
pub fn get_blocks_by_hash( &self, hashes: &[Bytes32], ) -> Result<Vec<Option<L2Block>>, BlockStoreError>
Batch-fetch blocks by hash (BLK-005).
Algorithm
- For each input hash in order, clone from [
Self::block_cache] when present (CAC-001). - Collect all cache misses; if non-empty, issue one
rocksdb::DB::multi_get_cfoverCF_BLOCKS(same(cf, key)pattern asSelf::get_block,SER-001payloads). - For each returned blob:
Self::deserialize_block, then insert into [Self::block_cache] and [Self::header_cache] (mirrors single-key read-through inSelf::get_block).
Ordering: Output Vec index i always corresponds to hashes[i] (per NORMATIVE BLK-005 §5).
Missing keys: Ok(None) at that index; RocksDB row absent still consumes one slot in the multi_get result vector.
Empty input: Returns Ok(vec![]) without touching RocksDB.
Chunking: Very large batches stay single-call for now (BLK-005.md implementation notes); future work may split to bound peak memory.
Sourcepub fn invalidate_block_cache_entry(&self, hash: &Bytes32)
pub fn invalidate_block_cache_entry(&self, hash: &Bytes32)
Drop a single entry from the in-memory block LRU — no RocksDB writes (BLK-002 test plan: simulate eviction).
Sourcepub fn get_block_by_height(
&self,
height: u64,
) -> Result<Option<L2Block>, BlockStoreError>
pub fn get_block_by_height( &self, height: u64, ) -> Result<Option<L2Block>, BlockStoreError>
Look up the canonical block at height (CAN-006 precursor, BLK-014 building block).
Algorithm: Self::get_hash_by_height (mmap then CF_CANONICAL) → Self::get_block
(BLK-002 decompress + cache).
Returns: Ok(None) when the height index is absent or when the hash is indexed but the body row is
missing (same as Self::get_block returning None).
Threading: Safe on any thread; performs synchronous RocksDB + zstd work — use Self::get_block_by_height_async
from async contexts that must not block the runtime (BLK-007).
Sourcepub fn get_blocks_in_range(
&self,
start_height: u64,
end_height: u64,
) -> Result<Vec<L2Block>, BlockStoreError>
pub fn get_blocks_in_range( &self, start_height: u64, end_height: u64, ) -> Result<Vec<L2Block>, BlockStoreError>
BLK-014 — Collect canonical L2Blocks for
heights in [start_height, end_height] inclusive (NORMATIVE BLK-014).
Semantics: Ascending height order; start_height > end_height ⇒ empty Vec (not an error); any height with
no canonical row or no retrievable body is omitted (gaps and “beyond tip” behave the same — fewer results).
vs Self::stream_blocks_in_range ([BLK-006]): This API eagerly builds a Vec with simple point lookups per height.
StreamBlocksInRange is better for large scans (single readahead iterator over CF_CANONICAL).
Sourcepub fn get_record_by_height(
&self,
height: u64,
) -> Result<Option<BlockRecord>, BlockStoreError>
pub fn get_record_by_height( &self, height: u64, ) -> Result<Option<BlockRecord>, BlockStoreError>
Look up the canonical BlockRecord at height (BLK-015, BLK-004).
Resolution: Same CF_CANONICAL → Bytes32 step as Self::get_block_by_height, then Self::get_record
so misses load bincode headers only from CF_HEADERS (SER-002) — no zstd frame read from CF_BLOCKS.
Returns: Ok(None) when the height index is missing or when neither CF_HEADERS nor caches can supply a header.
Canonical resolution: Same Self::get_hash_by_height dual layer as Self::get_block_by_height (CAN-001).
Sourcepub fn get_header_by_height(
&self,
height: u64,
) -> Result<Option<L2BlockHeader>, BlockStoreError>
pub fn get_header_by_height( &self, height: u64, ) -> Result<Option<L2BlockHeader>, BlockStoreError>
Look up the canonical header at height (CAN-006).
Algorithm: Self::get_hash_by_height → Self::get_header
(BLK-003 cache + bincode).
Returns: Ok(None) when the height is not canonical or the header row is absent.
Lighter than get_block_by_height: Headers are uncompressed bincode (~700 bytes)
versus full block bodies (zstd decompression + larger payload). Use this when only
header fields are needed (e.g., parent-hash walks, timestamp checks).
Sourcepub fn get_epoch_block_hashes(
&self,
epoch: u64,
) -> Result<Vec<Bytes32>, BlockStoreError>
pub fn get_epoch_block_hashes( &self, epoch: u64, ) -> Result<Vec<Bytes32>, BlockStoreError>
Collect canonical block hashes for all heights in the given epoch.
Algorithm: Uses dig_epoch::first_height_in_epoch and
dig_epoch::epoch_checkpoint_height to derive the inclusive [start, end]
height range, then calls Self::get_hash_by_height for each height. Stops
early when a height returns None (chain hasn’t reached that height yet).
Returns: A Vec<Bytes32> containing one hash per canonical height in the epoch,
in ascending height order. May be shorter than BLOCKS_PER_EPOCH if the chain is
still growing into the epoch, or empty if the epoch is entirely beyond the chain tip.
Requirement: CAN-006 § Epoch Block Hashes.
Sourcepub fn get_records_in_range(
&self,
start_height: u64,
end_height: u64,
) -> Result<Vec<BlockRecord>, BlockStoreError>
pub fn get_records_in_range( &self, start_height: u64, end_height: u64, ) -> Result<Vec<BlockRecord>, BlockStoreError>
BLK-015 — Materialize canonical BlockRecords for [start_height, end_height] inclusive (NORMATIVE BLK-015).
Semantics: Matches Self::get_blocks_in_range ordering and gap rules (BLK-014), but each row comes from Self::get_record_by_height so operators avoid zstd decompression on the hot path (BLK-015 § Specification).
Cache interaction: Self::get_record may insert derived rows into [Self::record_cache] / [Self::header_cache];
repeated scans therefore become cheaper, mirroring single-hash lookups (CAC-003 precursor).
Sourcepub fn cf_blocks_physical_get_count(&self) -> u64
pub fn cf_blocks_physical_get_count(&self) -> u64
How many times Self::get_block reached RocksDB CF_BLOCKS after a cache miss (includes Ok(None) probes).
Tests / ops: [tests/blk_002_tests.rs] asserts hits add zero; misses increment exactly once per call.
Sourcepub fn cf_blocks_multi_get_batch_count(&self) -> u64
pub fn cf_blocks_multi_get_batch_count(&self) -> u64
How many times Self::get_blocks_by_hash invoked rocksdb::DB::multi_get_cf because at least one hash missed
[Self::block_cache] (BLK-005; see [tests/blk_005_tests.rs]).
Sourcepub fn readahead_size(&self) -> usize
pub fn readahead_size(&self) -> usize
RocksDB readahead hint (bytes) copied from BlockStoreConfig::readahead_size at open (BLK-006 AC §4).
Sourcepub fn cf_blocks_stream_physical_get_count(&self) -> u64
pub fn cf_blocks_stream_physical_get_count(&self) -> u64
How many times StreamBlocksInRange issued DB::get_cf_opt against CF_BLOCKS
after a block-cache miss while streaming (BLK-006; [tests/blk_006_tests.rs]).
Sourcepub fn get_header(
&self,
hash: &Bytes32,
) -> Result<Option<L2BlockHeader>, BlockStoreError>
pub fn get_header( &self, hash: &Bytes32, ) -> Result<Option<L2BlockHeader>, BlockStoreError>
Retrieve a block header by hash (BLK-003).
Order: [Self::header_cache] → on miss, get_cf CF_HEADERS → Self::deserialize_header (no zstd;
SER-002).
Write path: Self::put_block / Self::init_genesis insert headers in parallel with block bodies.
Sourcepub fn invalidate_header_cache_entry(&self, hash: &Bytes32)
pub fn invalidate_header_cache_entry(&self, hash: &Bytes32)
Drop one header from the in-memory LRU (BLK-003 tests / future invalidation).
Sourcepub fn cf_headers_physical_get_count(&self) -> u64
pub fn cf_headers_physical_get_count(&self) -> u64
Count of RocksDB CF_HEADERS get_cf calls from Self::get_header or Self::get_record
when the in-memory header and record caches do not already supply the header/record (BLK-003, BLK-004).
Note: Self::get_record consults [Self::header_cache] before touching RocksDB, so a record-cache
miss with a warm header cache does not increment this counter (still satisfies “derive from header”).
Sourcepub fn put_block(
&self,
block: &L2Block,
canonical: bool,
) -> Result<bool, BlockStoreError>
pub fn put_block( &self, block: &L2Block, canonical: bool, ) -> Result<bool, BlockStoreError>
BLK-001 — Primary name in
IMPLEMENTATION_ORDER.md Phase 5.
Pipeline: zstd payload → CF_BLOCKS, bincode header → CF_HEADERS, optional height index →
CF_CANONICAL; BlockRecord is derived with BlockStatus::Validated and stored only in
[Self::record_cache] (TYP-004 persistence rule).
Idempotency: If the block hash already exists in CF_BLOCKS, returns Ok(false) and performs no writes
(start.md hard requirement §9).
SER-005: A successful insert that makes
Self::block_count reach [DICT_TRAINING_THRESHOLD] triggers one-time dictionary training when
BlockStoreConfig::use_compression_dict is true.
Sourcepub fn put(
&self,
block: &L2Block,
canonical: bool,
) -> Result<bool, BlockStoreError>
pub fn put( &self, block: &L2Block, canonical: bool, ) -> Result<bool, BlockStoreError>
Alias for Self::put_block — matches the BLK-001 normative snippet name put (NORMATIVE.md § BLK-001).
Sourcepub fn min_retained_height(&self) -> Result<u64, BlockStoreError>
pub fn min_retained_height(&self) -> Result<u64, BlockStoreError>
Public accessor for the pruning floor: minimum retained block height.
Returns 0 when no pruning has occurred (all heights retained).
After [PRN-001] runs, this reflects the META_MIN_HEIGHT value in CF_METADATA.
Requirement: ROR-005.
Public accessor for the pruning floor: minimum retained block height.
Returns 0 when no pruning has occurred (all heights retained).
Uses the cached AtomicU64 for fast lock-free access ([PRN-004]).
Sourcepub fn blocks_to_revert(
&self,
target_height: u64,
) -> Result<Vec<Bytes32>, BlockStoreError>
pub fn blocks_to_revert( &self, target_height: u64, ) -> Result<Vec<Bytes32>, BlockStoreError>
Read-only preview: which canonical blocks would be reverted by a rollback to target_height.
Returns hashes in descending height order (tip first). Returns empty Vec when
no tip is set or target_height >= tip.height. Does NOT modify any state.
Requirement: ROR-006.
Sourcepub fn rollback_to_height(
&self,
target_height: u64,
) -> Result<Vec<Bytes32>, BlockStoreError>
pub fn rollback_to_height( &self, target_height: u64, ) -> Result<Vec<Bytes32>, BlockStoreError>
Revert the canonical chain to target_height, removing higher heights from
the canonical index and updating the tip.
§Validation (ROR-005)
Checked in order before any mutation:
- NoTip — no chain tip set.
- RollbackAboveTip —
target_height > tip.height. - RollbackBelowMin —
target_height < min_retained_height().
§Mutation (ROR-001)
- Collect reverted hashes from tip down to
target_height + 1. WriteBatchdeletes on CF_CANONICAL for each reverted height.- Truncate
canonical.binto(target_height + 1) * 32. - Update tip to the block at
target_height. - Mark reverted blocks as non-canonical in record_cache.
- Evict reverted heights from canonical_height_cache.
§Returns
Hashes of reverted blocks in descending height order (tip first). Returns empty Vec for a no-op rollback at the current tip. Block data in CF_BLOCKS is NOT deleted (fork preservation per ROR-004).
Sourcepub fn apply_reorg(
&self,
ancestor_height: u64,
new_chain_hashes: &[Bytes32],
) -> Result<ReorgResult, BlockStoreError>
pub fn apply_reorg( &self, ancestor_height: u64, new_chain_hashes: &[Bytes32], ) -> Result<ReorgResult, BlockStoreError>
Atomically rollback the canonical chain to ancestor_height and re-canonicalize
the blocks in new_chain_hashes.
§Algorithm (ROR-003)
- Validate: NoTip → error. EmptyReorgChain → error. Each hash in
new_chain_hashesmust be in the store (BlockNotInStore if not). - WriteBatch (atomic):
- Delete CF_CANONICAL entries for heights
ancestor_height + 1..current_tip.height. - Put new canonical entries for each hash in
new_chain_hashes(height from record). - Write new tip (last hash in
new_chain_hashes) to META_TIP.
- Delete CF_CANONICAL entries for heights
- Post-commit:
- Truncate
canonical.bintoancestor_height, then write new hashes. - Update record_cache: reverted →
in_canonical_chain=false, applied →true. - Update in-memory tip.
- Evict/update canonical_height_cache.
- Truncate
§Returns
ReorgResult with reverted (descending), applied (ascending), and new_tip.
Sourcepub fn find_common_ancestor(
&self,
hash: &Bytes32,
max_depth: u64,
) -> Result<Option<(Bytes32, u64)>, BlockStoreError>
pub fn find_common_ancestor( &self, hash: &Bytes32, max_depth: u64, ) -> Result<Option<(Bytes32, u64)>, BlockStoreError>
Walk the parent_hash chain from hash backward, returning the first block
that is the canonical block at its height.
§Algorithm (ROR-002)
For up to max_depth steps:
- Load the
BlockRecordforcurrent_hash(cache or CF_HEADERS derive). - Check if
get_hash_by_height(record.height) == current_hash— if so, this block is canonical and is the common ancestor. - Otherwise, follow
record.parent_hashand repeat.
§Returns
Ok(Some((hash, height)))— the first canonical ancestor found.Ok(None)— hash not in store, parent chain broken, ormax_depthexceeded.
§Use case
When a new block arrives whose parent is not the current tip, call this with the
new block’s parent hash to find where the fork diverged from the canonical chain.
The result feeds into apply_reorg (ROR-003) as the ancestor_height.
§Read-only
This method does not modify any state. Safe to call concurrently.
Sourcepub fn put_attestation(
&self,
hash: &Bytes32,
attested: &AttestedBlock,
) -> Result<(), BlockStoreError>
pub fn put_attestation( &self, hash: &Bytes32, attested: &AttestedBlock, ) -> Result<(), BlockStoreError>
BLK-009 — Persist an AttestedBlock under the block’s hash key.
Key: hash_key(hash) — raw 32 bytes in CF_ATTESTED (KEY-001), identical key shape to CF_BLOCKS / CF_HEADERS.
Value: bincode::serialize of attested (uncompressed; attestations are small per BLK-009 implementation notes).
Hash vs payload: Callers normally pass hash == attested.hash(); this method does not verify that invariant so
tests and migration tooling can stage rows independently of body presence in CF_BLOCKS.
Overwrite (AC §4): A second call with the same hash replaces the previous value (DB::put_cf).
Read-only: Returns BlockStoreError::Serialization with ERR_MUTATION_READ_ONLY — same contract as Self::put_block.
Sourcepub fn get_attestation(
&self,
hash: &Bytes32,
) -> Result<Option<AttestedBlock>, BlockStoreError>
pub fn get_attestation( &self, hash: &Bytes32, ) -> Result<Option<AttestedBlock>, BlockStoreError>
BLK-009 — Read AttestedBlock bytes from CF_ATTESTED.
Miss: [Ok(None)] when no row exists (AC §3).
No attestation cache (yet): Each call performs a RocksDB get_cf + bincode decode (BLK-009 notes; hot paths may add [CAC-*] later).
Corrupt rows: Malformed bincode surfaces as BlockStoreError::Serialization so operators can distinguish “missing” vs “bad bytes”.
Sourcepub fn put_checkpoint(
&self,
checkpoint: &StoredCheckpoint,
) -> Result<(), BlockStoreError>
pub fn put_checkpoint( &self, checkpoint: &StoredCheckpoint, ) -> Result<(), BlockStoreError>
Persist a [StoredCheckpoint] to CF_CHECKPOINTS keyed by epoch.
Key: epoch_key(checkpoint.checkpoint.epoch) — 8-byte big-endian.
Value: bincode::serialize of the full [StoredCheckpoint].
Idempotent: overwrites any existing checkpoint at the same epoch.
Requirement: CKP-001.
Sourcepub fn get_checkpoint(
&self,
epoch: u64,
) -> Result<Option<StoredCheckpoint>, BlockStoreError>
pub fn get_checkpoint( &self, epoch: u64, ) -> Result<Option<StoredCheckpoint>, BlockStoreError>
Retrieve a [StoredCheckpoint] by epoch from CF_CHECKPOINTS.
Returns Ok(None) if no checkpoint exists for the given epoch.
Requirement: CKP-002.
Sourcepub fn get_latest_checkpoint(
&self,
) -> Result<Option<StoredCheckpoint>, BlockStoreError>
pub fn get_latest_checkpoint( &self, ) -> Result<Option<StoredCheckpoint>, BlockStoreError>
Retrieve the most recent checkpoint (highest epoch) via reverse iterator.
Returns Ok(None) if no checkpoints are stored.
Requirement: CKP-003.
Sourcepub fn get_checkpoints_in_range(
&self,
start_epoch: u64,
end_epoch: u64,
) -> Result<Vec<StoredCheckpoint>, BlockStoreError>
pub fn get_checkpoints_in_range( &self, start_epoch: u64, end_epoch: u64, ) -> Result<Vec<StoredCheckpoint>, BlockStoreError>
Retrieve all checkpoints within an epoch range [start_epoch, end_epoch] inclusive.
Returns empty Vec if no checkpoints exist in the range. If start_epoch > end_epoch,
returns empty (no error).
Requirement: CKP-004.
Sourcepub fn prune_before_height(&self, height: u64) -> Result<usize, BlockStoreError>
pub fn prune_before_height(&self, height: u64) -> Result<usize, BlockStoreError>
Remove all blocks, headers, attestations, and canonical entries below height.
§Algorithm (PRN-001)
- Iterate
CF_CANONICALfrommin_retained_heighttoheight - 1, collecting hashes. - Also scan
CF_HEADERSfor non-canonical blocks belowheight([PRN-005]). - Single
WriteBatchdeletes from CF_BLOCKS, CF_HEADERS, CF_ATTESTED, CF_CANONICAL. - Update
META_MIN_HEIGHTin the same batch. - Post-commit: evict from all caches, update
AtomicU64.
§Returns
Count of blocks pruned (canonical + non-canonical).
Sourcepub fn prune_checkpoints_before_epoch(
&self,
epoch: u64,
) -> Result<usize, BlockStoreError>
pub fn prune_checkpoints_before_epoch( &self, epoch: u64, ) -> Result<usize, BlockStoreError>
Remove all checkpoints with epoch < epoch from CF_CHECKPOINTS.
Returns the count of pruned checkpoints.
Requirement: PRN-002.
Sourcepub fn get_record(
&self,
hash: &Bytes32,
) -> Result<Option<BlockRecord>, BlockStoreError>
pub fn get_record( &self, hash: &Bytes32, ) -> Result<Option<BlockRecord>, BlockStoreError>
Look up BlockRecord by hash (BLK-004).
Order
- [
Self::record_cache] (Mutex map) — clone on hit; no RocksDB I/O. - [
Self::header_cache] — if the header is already deserialized (e.g. afterSelf::put_blockorSelf::get_header), deriveBlockRecord::from_headerwithBlockStatus::Validatedand insert into the record cache; no RocksDBget_cfonCF_HEADERS. - Else load raw bytes from
CF_HEADERS, increment [Self::cf_headers_physical_gets], deserialize viaSelf::deserialize_header, warm [Self::header_cache] + record cache.
Persistence: BlockRecord is never written to any column family (TYP-004); only headers live under CF_HEADERS.
Read-only stores: Record/header RAM caches start empty; the first lookup may read CF_HEADERS and populate both caches without mutating on-disk layout beyond normal reads.
Sourcepub fn invalidate_record_cache_entry(&self, hash: &Bytes32)
pub fn invalidate_record_cache_entry(&self, hash: &Bytes32)
Remove one hash from the in-memory BlockRecord map — no RocksDB writes (BLK-004 test plan: simulate record-cache eviction).
Sourcepub fn update_status(
&self,
hash: &Bytes32,
status: BlockStatus,
) -> Result<(), BlockStoreError>
pub fn update_status( &self, hash: &Bytes32, status: BlockStatus, ) -> Result<(), BlockStoreError>
BLK-010 — Set BlockRecord::status for a hash already present in [Self::record_cache].
No disk I/O: BlockRecord is cache-only (TYP-004); this method never touches rocksdb::WriteBatch or DB::put_cf.
in_canonical_chain: Recomputed from BlockStatus::is_canonical so the row stays aligned with BlockRecord::from_header (TYP-004 module docs).
Precondition: The hash must already exist in the record cache (typically after Self::put_block or a cache-warming Self::get_record). Otherwise returns BlockStoreError::Serialization whose message starts with
ERR_UPDATE_STATUS_RECORD_NOT_CACHED_PREFIX
(ERR-001 caps the public enum at thirteen variants, so this uses the same stable-prefix pattern as read-only mutation guards).
Sourcepub async fn get_block_async(
&self,
hash: &Bytes32,
) -> Result<Option<L2Block>, BlockStoreError>
pub async fn get_block_async( &self, hash: &Bytes32, ) -> Result<Option<L2Block>, BlockStoreError>
Async retrieval by hash (BLK-007 AC §1, §4, §5).
Hot path: [Self::block_cache] hits return cloned blocks before any .await, so the generated
future can complete as [Poll::Ready] on the first poll without scheduling
tokio::task::spawn_blocking (NORMATIVE BLK-007 §1–2).
Cold path: Delegates to Self::get_block on the blocking pool so RocksDB + zstd never run on a
cooperative tokio worker thread.
Sourcepub async fn get_header_async(
&self,
hash: &Bytes32,
) -> Result<Option<L2BlockHeader>, BlockStoreError>
pub async fn get_header_async( &self, hash: &Bytes32, ) -> Result<Option<L2BlockHeader>, BlockStoreError>
Async header retrieval (BLK-007 AC §2, §4–5).
Sourcepub async fn get_block_by_height_async(
&self,
height: u64,
) -> Result<Option<L2Block>, BlockStoreError>
pub async fn get_block_by_height_async( &self, height: u64, ) -> Result<Option<L2Block>, BlockStoreError>
Async canonical-height lookup followed by block load (BLK-007 AC §3).
Always spawn_blocking: height→hash uses CF_CANONICAL I/O; per BLK-007 implementation notes this
stays on the blocking pool even when the block body would hit [Self::block_cache], avoiding partial
“async hits” that still touch RocksDB in the sync prelude.
Trait Implementations§
Source§impl Clone for BlockStore
impl Clone for BlockStore
Auto Trait Implementations§
impl !RefUnwindSafe for BlockStore
impl !UnwindSafe for BlockStore
impl Freeze for BlockStore
impl Send for BlockStore
impl Sync for BlockStore
impl Unpin for BlockStore
impl UnsafeUnpin for BlockStore
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.