Skip to main content

dynamo_kv_hashing/
block.rs

1// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4//! [`UniversalBlock`] — the per-block result of hashing a [`crate::Request`].
5//!
6//! `UniversalBlock` carries the universal identifier ([`PositionalLineageHash`])
7//! and the per-block content hash. The `u64` sequence hash needed for chain
8//! extension is embedded in PLH itself
9//! ([`PositionalLineageHash::current_sequence_hash`]) and accessible via
10//! [`UniversalBlock::sequence_hash`], so callers no longer need a side table
11//! mapping PLH → u64.
12//!
13//! Salt is *not* a per-block field: it is a per-request constant, identical for
14//! every block in a sequence. Callers that need it should read it once from
15//! [`crate::Request::salt_hash`].
16
17use dynamo_tokens::{BlockHash, PositionalLineageHash, SequenceHash, TokenBlock};
18use serde::{Deserialize, Serialize};
19
20/// Per-block hashing result. PLH is self-contained for chain extension via
21/// [`PositionalLineageHash::extend`]; no out-of-band tracking required.
22#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
23pub struct UniversalBlock {
24    /// XXH3 over the per-slot byte buffer of this block.
25    pub block_hash: BlockHash,
26    /// Universal identifier; transport- and lookup-friendly. Carries the full u64
27    /// sequence hash inline.
28    pub plh: PositionalLineageHash,
29}
30
31impl UniversalBlock {
32    /// Block index in the sequence (zero-based).
33    #[inline]
34    pub fn position(&self) -> u64 {
35        self.plh.position()
36    }
37
38    /// Parent-chained sequence hash for this block (full u64).
39    #[inline]
40    pub fn sequence_hash(&self) -> SequenceHash {
41        self.plh.current_sequence_hash()
42    }
43
44    /// Lossy conversion: produces a [`PositionalLineageHash`] for transport / indexing.
45    pub fn into_plh(self) -> PositionalLineageHash {
46        self.plh
47    }
48}
49
50impl From<&TokenBlock> for UniversalBlock {
51    fn from(b: &TokenBlock) -> Self {
52        Self {
53            block_hash: b.block_hash(),
54            plh: b.positional_lineage_hash(),
55        }
56    }
57}