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}