Skip to content

vllm.distributed.kv_transfer.kv_connector.v1.mooncake.store.data

Data classes for MooncakeStoreConnector.

Classes:

  • BlobBlockHashes

    Lazy view over a flat buffer of fixed-size block hashes to avoid the overhead

  • ChunkedTokenDatabase

    Maps token positions to store keys and GPU memory addresses.

  • KeyMetadata

    Metadata for constructing pool keys.

  • LoadSpec

    Specification for loading KV cache from external store.

  • MooncakeStoreConnectorMetadata

    Metadata passed from scheduler to worker.

  • PoolKey

    Key for addressing KV cache blocks in the distributed store.

  • ReqMeta

    Per-request metadata for store put/get operations.

  • RequestTracker

    Tracks per-request state across scheduler ticks.

Functions:

BlobBlockHashes

Bases: Sequence[BlockHash]

Lazy view over a flat buffer of fixed-size block hashes to avoid the overhead of materializing all hashes upfront.

Source code in vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/data.py
class BlobBlockHashes(Sequence[BlockHash]):
    """Lazy view over a flat buffer of fixed-size block hashes to avoid the overhead
    of materializing all hashes upfront.
    """

    def __init__(self, blob: memoryview, hash_len: int):
        self._blob = blob
        self._hash_len = hash_len
        self._n = len(blob) // hash_len if hash_len else 0

    def __len__(self) -> int:
        return self._n

    def __getitem__(self, idx):
        if isinstance(idx, slice):
            return [self[i] for i in range(*idx.indices(self._n))]
        if idx < 0:
            idx += self._n
        if not 0 <= idx < self._n:
            raise IndexError(idx)
        off = idx * self._hash_len
        return BlockHash(self._blob[off : off + self._hash_len])

ChunkedTokenDatabase

Maps token positions to store keys and GPU memory addresses.

Methods:

  • prepare_value

    Compute memory addresses and sizes for a single token range.

  • prepare_value_for_block

    Return addresses and sizes for one physical block slot.

  • prepare_values

    Compute memory addresses and sizes for multiple token ranges.

  • process_tokens

    Process tokens and yield (start_idx, end_idx, block_hash) tuples.

Source code in vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/data.py
class ChunkedTokenDatabase:
    """Maps token positions to store keys and GPU memory addresses."""

    def __init__(
        self,
        metadata: KeyMetadata,
        block_size: int,
        hash_block_size: int | None = None,
    ):
        self.metadata = metadata
        self.block_size = block_size
        self.hash_block_size = hash_block_size or block_size
        if self.block_size % self.hash_block_size != 0:
            raise ValueError(
                f"block_size ({self.block_size}) must be a multiple of "
                f"hash_block_size ({self.hash_block_size})"
            )
        self.kv_caches_base_addr: list[int] = []
        self.block_len: list[int] = []
        self._key_prefix = PoolKey.build_prefix(metadata)

    def key_for(self, chunk_hash: BlockHash) -> str:
        return PoolKey.build_key_string(self._key_prefix, chunk_hash.hex())

    def set_kv_caches_base_addr(self, kv_caches_base_addr: list[int]):
        self.kv_caches_base_addr = kv_caches_base_addr

    def set_block_len(self, block_len: list[int]):
        self.block_len = block_len

    def prepare_value(
        self, start: int, end: int, block_ids: list[int]
    ) -> tuple[list[int], list[int], int]:
        """Compute memory addresses and sizes for a single token range.

        Returns:
            (addr_list, size_list, block_id)
        """
        addr_lists, size_lists, chunk_block_ids = self.prepare_values(
            ((start, end),), block_ids
        )
        return addr_lists[0], size_lists[0], chunk_block_ids[0]

    def prepare_values(
        self,
        chunks: Sequence[tuple[int, int]],
        block_ids: list[int],
    ) -> tuple[list[list[int]], list[list[int]], list[int]]:
        """Compute memory addresses and sizes for multiple token ranges.

        Returns:
            (addr_lists, size_lists, chunk_block_ids), one entry per chunk.
        """
        if not chunks:
            return [], [], []
        base = np.asarray(self.kv_caches_base_addr, dtype=np.int64)
        length = len(self.block_len)
        blen = np.asarray(
            [self.block_len[i % length] for i in range(base.shape[0])],
            dtype=np.int64,
        )
        n = len(chunks)
        starts = np.fromiter((c[0] for c in chunks), dtype=np.int64, count=n)
        spans = np.fromiter((c[1] for c in chunks), dtype=np.int64, count=n) - starts
        assert not (spans % self.hash_block_size).any()
        bids = np.fromiter(
            (block_ids[i] for i in (starts // self.block_size).tolist()),
            dtype=np.int64,
            count=n,
        )
        addrs = base[None, :] + bids[:, None] * blen[None, :]
        block_counts = (spans + self.block_size - 1) // self.block_size
        sizes = blen[None, :] * block_counts[:, None]
        return addrs.tolist(), sizes.tolist(), bids.tolist()

    def prepare_value_for_block(self, block_id: int) -> tuple[list[int], list[int]]:
        """Return addresses and sizes for one physical block slot."""
        addr_list = []
        size_list = []
        length = len(self.block_len)
        for index, base_addr in enumerate(self.kv_caches_base_addr):
            addr = base_addr + block_id * self.block_len[index % length]
            addr_list.append(addr)
            size_list.append(self.block_len[index % length])
        return addr_list, size_list

    def process_tokens(
        self,
        token_len: int,
        block_hashes: list[BlockHash],
        mask_num: int = 0,
        *,
        chunk_mask: list[bool] | None = None,
        put_step: int = 1,
        put_step_rank: int = 0,
    ) -> Iterable[tuple[int, int, BlockHash]]:
        """Process tokens and yield (start_idx, end_idx, block_hash) tuples.

        When there are fewer KV heads than TP ranks, chunks are distributed
        across TP ranks to avoid duplicate load/store. The assignment keys off
        the absolute ``chunk_id`` so a given chunk always lands on the same
        rank regardless of where the processed suffix begins.

        Args:
            token_len: Total number of tokens. Must be hash-block aligned and
                covered by ``block_hashes`` when hashes are present.
            block_hashes: Block hashes computed at ``hash_block_size`` granularity.
                When ``block_size > hash_block_size`` each group's ``block_size`` chunk
                is keyed by its last sub-hash via ``chunk_hashes_for_block_size``.
            mask_num: Number of tokens to skip from the beginning.
            chunk_mask: Optional mask relative to the first chunk after
                ``mask_num``. False entries are skipped before hash access.
            put_step: Stride for distributing chunks across ranks.
            put_step_rank: ``chunk_id % put_step`` value this rank stores.
        """
        assert put_step > 0
        if not block_hashes:
            return
        assert token_len % self.hash_block_size == 0
        assert token_len // self.hash_block_size <= len(block_hashes)
        start_chunk = max(0, cdiv(mask_num, self.block_size))
        max_chunks = cdiv(token_len, self.block_size)
        if chunk_mask is not None:
            max_chunks = min(max_chunks, start_chunk + len(chunk_mask))
        for chunk_id in range(start_chunk, max_chunks):
            if chunk_mask is not None and not chunk_mask[chunk_id - start_chunk]:
                continue
            if chunk_id % put_step != put_step_rank:
                continue
            start_idx = chunk_id * self.block_size
            end_idx = min(start_idx + self.block_size, token_len)
            h = block_hashes[end_idx // self.hash_block_size - 1]
            yield start_idx, end_idx, h

prepare_value(start, end, block_ids)

Compute memory addresses and sizes for a single token range.

Returns:

Source code in vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/data.py
def prepare_value(
    self, start: int, end: int, block_ids: list[int]
) -> tuple[list[int], list[int], int]:
    """Compute memory addresses and sizes for a single token range.

    Returns:
        (addr_list, size_list, block_id)
    """
    addr_lists, size_lists, chunk_block_ids = self.prepare_values(
        ((start, end),), block_ids
    )
    return addr_lists[0], size_lists[0], chunk_block_ids[0]

prepare_value_for_block(block_id)

Return addresses and sizes for one physical block slot.

Source code in vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/data.py
def prepare_value_for_block(self, block_id: int) -> tuple[list[int], list[int]]:
    """Return addresses and sizes for one physical block slot."""
    addr_list = []
    size_list = []
    length = len(self.block_len)
    for index, base_addr in enumerate(self.kv_caches_base_addr):
        addr = base_addr + block_id * self.block_len[index % length]
        addr_list.append(addr)
        size_list.append(self.block_len[index % length])
    return addr_list, size_list

prepare_values(chunks, block_ids)

Compute memory addresses and sizes for multiple token ranges.

Returns:

Source code in vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/data.py
def prepare_values(
    self,
    chunks: Sequence[tuple[int, int]],
    block_ids: list[int],
) -> tuple[list[list[int]], list[list[int]], list[int]]:
    """Compute memory addresses and sizes for multiple token ranges.

    Returns:
        (addr_lists, size_lists, chunk_block_ids), one entry per chunk.
    """
    if not chunks:
        return [], [], []
    base = np.asarray(self.kv_caches_base_addr, dtype=np.int64)
    length = len(self.block_len)
    blen = np.asarray(
        [self.block_len[i % length] for i in range(base.shape[0])],
        dtype=np.int64,
    )
    n = len(chunks)
    starts = np.fromiter((c[0] for c in chunks), dtype=np.int64, count=n)
    spans = np.fromiter((c[1] for c in chunks), dtype=np.int64, count=n) - starts
    assert not (spans % self.hash_block_size).any()
    bids = np.fromiter(
        (block_ids[i] for i in (starts // self.block_size).tolist()),
        dtype=np.int64,
        count=n,
    )
    addrs = base[None, :] + bids[:, None] * blen[None, :]
    block_counts = (spans + self.block_size - 1) // self.block_size
    sizes = blen[None, :] * block_counts[:, None]
    return addrs.tolist(), sizes.tolist(), bids.tolist()

process_tokens(token_len, block_hashes, mask_num=0, *, chunk_mask=None, put_step=1, put_step_rank=0)

Process tokens and yield (start_idx, end_idx, block_hash) tuples.

When there are fewer KV heads than TP ranks, chunks are distributed across TP ranks to avoid duplicate load/store. The assignment keys off the absolute chunk_id so a given chunk always lands on the same rank regardless of where the processed suffix begins.

Parameters:

  • token_len

    (int) –

    Total number of tokens. Must be hash-block aligned and covered by block_hashes when hashes are present.

  • block_hashes

    (list[BlockHash]) –

    Block hashes computed at hash_block_size granularity. When block_size > hash_block_size each group's block_size chunk is keyed by its last sub-hash via chunk_hashes_for_block_size.

  • mask_num

    (int, default: 0 ) –

    Number of tokens to skip from the beginning.

  • chunk_mask

    (list[bool] | None, default: None ) –

    Optional mask relative to the first chunk after mask_num. False entries are skipped before hash access.

  • put_step

    (int, default: 1 ) –

    Stride for distributing chunks across ranks.

  • put_step_rank

    (int, default: 0 ) –

    chunk_id % put_step value this rank stores.

Source code in vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/data.py
def process_tokens(
    self,
    token_len: int,
    block_hashes: list[BlockHash],
    mask_num: int = 0,
    *,
    chunk_mask: list[bool] | None = None,
    put_step: int = 1,
    put_step_rank: int = 0,
) -> Iterable[tuple[int, int, BlockHash]]:
    """Process tokens and yield (start_idx, end_idx, block_hash) tuples.

    When there are fewer KV heads than TP ranks, chunks are distributed
    across TP ranks to avoid duplicate load/store. The assignment keys off
    the absolute ``chunk_id`` so a given chunk always lands on the same
    rank regardless of where the processed suffix begins.

    Args:
        token_len: Total number of tokens. Must be hash-block aligned and
            covered by ``block_hashes`` when hashes are present.
        block_hashes: Block hashes computed at ``hash_block_size`` granularity.
            When ``block_size > hash_block_size`` each group's ``block_size`` chunk
            is keyed by its last sub-hash via ``chunk_hashes_for_block_size``.
        mask_num: Number of tokens to skip from the beginning.
        chunk_mask: Optional mask relative to the first chunk after
            ``mask_num``. False entries are skipped before hash access.
        put_step: Stride for distributing chunks across ranks.
        put_step_rank: ``chunk_id % put_step`` value this rank stores.
    """
    assert put_step > 0
    if not block_hashes:
        return
    assert token_len % self.hash_block_size == 0
    assert token_len // self.hash_block_size <= len(block_hashes)
    start_chunk = max(0, cdiv(mask_num, self.block_size))
    max_chunks = cdiv(token_len, self.block_size)
    if chunk_mask is not None:
        max_chunks = min(max_chunks, start_chunk + len(chunk_mask))
    for chunk_id in range(start_chunk, max_chunks):
        if chunk_mask is not None and not chunk_mask[chunk_id - start_chunk]:
            continue
        if chunk_id % put_step != put_step_rank:
            continue
        start_idx = chunk_id * self.block_size
        end_idx = min(start_idx + self.block_size, token_len)
        h = block_hashes[end_idx // self.hash_block_size - 1]
        yield start_idx, end_idx, h

KeyMetadata dataclass

Metadata for constructing pool keys.

Source code in vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/data.py
@dataclass
class KeyMetadata:
    """Metadata for constructing pool keys."""

    model_name: str
    tp_rank: int
    pcp_rank: int
    dcp_rank: int
    pp_rank: int
    group_id: int = 0
    # Optional namespace prepended to every key. Lets separate deployments
    # share one Mooncake master without colliding on identical block hashes.
    # Empty (the default) keeps keys byte-identical to the unprefixed format.
    cache_prefix: str = ""

LoadSpec dataclass

Specification for loading KV cache from external store.

Source code in vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/data.py
@dataclass
class LoadSpec:
    """Specification for loading KV cache from external store."""

    vllm_cached_tokens: int
    kvpool_cached_tokens: int
    can_load: bool
    token_len: int = 0

MooncakeStoreConnectorMetadata

Bases: KVConnectorMetadata

Metadata passed from scheduler to worker.

Source code in vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/data.py
class MooncakeStoreConnectorMetadata(KVConnectorMetadata):
    """Metadata passed from scheduler to worker."""

    def __init__(
        self,
        unfinished_request_ids: set[str],
        preempted_req_ids: set[str],
    ):
        self.requests: list[ReqMeta] = []
        self.unfinished_request_ids = unfinished_request_ids
        self.preempted_req_ids = preempted_req_ids

    def add_request(self, req_meta: ReqMeta) -> None:
        self.requests.append(req_meta)

PoolKey dataclass

Key for addressing KV cache blocks in the distributed store.

Methods:

  • build_prefix

    Return the stable prefix for a Mooncake pool key.

Source code in vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/data.py
@dataclass(order=True)
class PoolKey:
    """Key for addressing KV cache blocks in the distributed store."""

    key_metadata: KeyMetadata
    chunk_hash: str

    def __hash__(self):
        return hash(
            (
                self.key_metadata.cache_prefix,
                self.key_metadata.model_name,
                self.key_metadata.tp_rank,
                self.key_metadata.pcp_rank,
                self.key_metadata.dcp_rank,
                self.key_metadata.pp_rank,
                self.key_metadata.group_id,
                self.chunk_hash,
            )
        )

    @staticmethod
    def build_prefix(
        key_metadata: KeyMetadata,
        *,
        tp_rank: int | None = None,
        pcp_rank: int | None = None,
        dcp_rank: int | None = None,
        pp_rank: int | None = None,
    ) -> str:
        """Return the stable prefix for a Mooncake pool key."""
        prefix = f"{key_metadata.cache_prefix}@" if key_metadata.cache_prefix else ""
        return (
            f"{prefix}"
            f"{key_metadata.model_name}"
            f"@tp_rank:{key_metadata.tp_rank if tp_rank is None else tp_rank}"
            f"@pcp{key_metadata.pcp_rank if pcp_rank is None else pcp_rank}"
            f"@dcp{key_metadata.dcp_rank if dcp_rank is None else dcp_rank}"
            f"@pp_rank:{key_metadata.pp_rank if pp_rank is None else pp_rank}"
            f"@group:{key_metadata.group_id}"
        )

    @staticmethod
    def build_key_string(key_prefix: str, chunk_hash: str) -> str:
        return f"{key_prefix}@{chunk_hash}"

    def to_string(self) -> str:
        return self.build_key_string(
            self.build_prefix(self.key_metadata), self.chunk_hash
        )

build_prefix(key_metadata, *, tp_rank=None, pcp_rank=None, dcp_rank=None, pp_rank=None) staticmethod

Return the stable prefix for a Mooncake pool key.

Source code in vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/data.py
@staticmethod
def build_prefix(
    key_metadata: KeyMetadata,
    *,
    tp_rank: int | None = None,
    pcp_rank: int | None = None,
    dcp_rank: int | None = None,
    pp_rank: int | None = None,
) -> str:
    """Return the stable prefix for a Mooncake pool key."""
    prefix = f"{key_metadata.cache_prefix}@" if key_metadata.cache_prefix else ""
    return (
        f"{prefix}"
        f"{key_metadata.model_name}"
        f"@tp_rank:{key_metadata.tp_rank if tp_rank is None else tp_rank}"
        f"@pcp{key_metadata.pcp_rank if pcp_rank is None else pcp_rank}"
        f"@dcp{key_metadata.dcp_rank if dcp_rank is None else dcp_rank}"
        f"@pp_rank:{key_metadata.pp_rank if pp_rank is None else pp_rank}"
        f"@group:{key_metadata.group_id}"
    )

ReqMeta dataclass

Per-request metadata for store put/get operations.

Methods:

Source code in vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/data.py
@dataclass
class ReqMeta:
    """Per-request metadata for store put/get operations."""

    req_id: str
    token_len_chunk: int
    block_ids: tuple[list[int], ...]
    block_hashes: list[BlockHash]

    can_save: bool | None = None
    load_spec: LoadSpec | None = None
    is_last_chunk: bool | None = None
    current_event: torch.cuda.Event | None = None

    token_ids: list[int] | None = None
    num_prompt_tokens: int | None = None
    # Core-provided per-mamba-group
    # (group_id, cow_block_id, boundary_tokens) for this request's partial tail.
    # Present only on the producer's CoW step; drives the connector's offload
    # (the FA group's block is derived from block_ids and boundary_tokens).
    partial_tail_offloads: list[tuple[int, int, int]] | None = None

    @staticmethod
    def from_request_tracker(
        tracker: RequestTracker,
        block_size: int,
        load_spec: LoadSpec | None = None,
        skip_save: bool | None = False,
        block_hashes: list[BlockHash] | None = None,
        is_last_chunk: bool | None = None,
    ) -> "ReqMeta | None":
        """Create ReqMeta from a RequestTracker."""
        if block_hashes is None:
            block_hashes = []
        input_token_len = tracker.token_len

        chunk_boundary = cdiv(tracker.num_saved_tokens + 1, block_size) * block_size
        num_tokens_to_save = input_token_len // block_size * block_size

        skip_save = skip_save or num_tokens_to_save < chunk_boundary
        # A ReqMeta must never carry both a save AND a load.
        # The save would also be wasted work — the bytes are being looked up
        # in the store right now. Later cached_reqs steps save new tokens
        # normally.
        if load_spec is not None and load_spec.can_load:
            skip_save = True
        if skip_save and load_spec is None:
            return None

        if not skip_save:
            tracker.num_saved_tokens = num_tokens_to_save

        token_ids = None
        if tracker.token_ids:
            token_ids = tracker.token_ids

        if load_spec is not None and load_spec.can_load:
            logger.debug(
                "Scheduled to load %d tokens for request %s",
                load_spec.kvpool_cached_tokens,
                tracker.req_id,
            )
        else:
            load_spec = None

        logger.debug(
            "request:%s, meta save spec:%s, meta load spec:%s",
            tracker.req_id,
            not skip_save,
            load_spec,
        )
        return ReqMeta(
            req_id=tracker.req_id,
            token_len_chunk=num_tokens_to_save,
            block_ids=tracker.allocated_block_ids,
            can_save=not skip_save,
            load_spec=load_spec,
            block_hashes=block_hashes,
            is_last_chunk=is_last_chunk,
            token_ids=token_ids,
            num_prompt_tokens=tracker.prefill_end_tokens,
        )

from_request_tracker(tracker, block_size, load_spec=None, skip_save=False, block_hashes=None, is_last_chunk=None) staticmethod

Create ReqMeta from a RequestTracker.

Source code in vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/data.py
@staticmethod
def from_request_tracker(
    tracker: RequestTracker,
    block_size: int,
    load_spec: LoadSpec | None = None,
    skip_save: bool | None = False,
    block_hashes: list[BlockHash] | None = None,
    is_last_chunk: bool | None = None,
) -> "ReqMeta | None":
    """Create ReqMeta from a RequestTracker."""
    if block_hashes is None:
        block_hashes = []
    input_token_len = tracker.token_len

    chunk_boundary = cdiv(tracker.num_saved_tokens + 1, block_size) * block_size
    num_tokens_to_save = input_token_len // block_size * block_size

    skip_save = skip_save or num_tokens_to_save < chunk_boundary
    # A ReqMeta must never carry both a save AND a load.
    # The save would also be wasted work — the bytes are being looked up
    # in the store right now. Later cached_reqs steps save new tokens
    # normally.
    if load_spec is not None and load_spec.can_load:
        skip_save = True
    if skip_save and load_spec is None:
        return None

    if not skip_save:
        tracker.num_saved_tokens = num_tokens_to_save

    token_ids = None
    if tracker.token_ids:
        token_ids = tracker.token_ids

    if load_spec is not None and load_spec.can_load:
        logger.debug(
            "Scheduled to load %d tokens for request %s",
            load_spec.kvpool_cached_tokens,
            tracker.req_id,
        )
    else:
        load_spec = None

    logger.debug(
        "request:%s, meta save spec:%s, meta load spec:%s",
        tracker.req_id,
        not skip_save,
        load_spec,
    )
    return ReqMeta(
        req_id=tracker.req_id,
        token_len_chunk=num_tokens_to_save,
        block_ids=tracker.allocated_block_ids,
        can_save=not skip_save,
        load_spec=load_spec,
        block_hashes=block_hashes,
        is_last_chunk=is_last_chunk,
        token_ids=token_ids,
        num_prompt_tokens=tracker.prefill_end_tokens,
    )

RequestTracker dataclass

Tracks per-request state across scheduler ticks.

Source code in vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/data.py
@dataclass
class RequestTracker:
    """Tracks per-request state across scheduler ticks."""

    req_id: str
    token_len: int
    allocated_block_ids: tuple[list[int], ...]
    num_saved_tokens: int = 0
    token_ids: list[int] | None = None
    has_pending_offload: bool = False
    # Snapshot of the prefill range length at tracker creation time.
    # For a fresh request this is len(prompt). For a resumed-from-preemption
    # request it includes previously-generated tokens, which are re-prefilled.
    prefill_end_tokens: int = 0

    def reset(self) -> None:
        self.token_len = 0
        self.allocated_block_ids = ()
        self.num_saved_tokens = 0
        self.token_ids = None
        self.has_pending_offload = False
        self.prefill_end_tokens = 0

    def update(
        self,
        new_block_ids: tuple[list[int], ...] | list[int],
    ) -> None:
        # Backward-compat: accept a single list (broadcast to single group).
        if isinstance(new_block_ids, list):
            new_block_ids = (new_block_ids,)
        if len(new_block_ids) != len(self.allocated_block_ids):
            raise ValueError(
                f"Group count mismatch: tracker has "
                f"{len(self.allocated_block_ids)} groups, update has "
                f"{len(new_block_ids)}"
            )
        for existing, new in zip(self.allocated_block_ids, new_block_ids, strict=True):
            if new:
                existing.extend(new)

_CompactChunkHashList

Bases: BlockHashListWithBlockSize

View that keys each block_size chunk by the last constituent hash_block_size hash instead of concatenating all of them.

The engine chains block hashes (each hash folds in the previous one), so the final sub-block hash of a chunk already uniquely identifies the whole chunk and its prefix. Using it keeps a Mooncake key at a single hash digest regardless of the block_size / hash_block_size ratio, instead of growing the key linearly with it (e.g. 64x for block_size=256, hash_block_size=4).

Source code in vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/data.py
class _CompactChunkHashList(BlockHashListWithBlockSize):
    """View that keys each ``block_size`` chunk by the last constituent
    ``hash_block_size`` hash instead of concatenating all of them.

    The engine chains block hashes (each hash folds in the previous one), so the
    final sub-block hash of a chunk already uniquely identifies the whole chunk
    and its prefix. Using it keeps a Mooncake key at a single hash digest
    regardless of the ``block_size`` / ``hash_block_size`` ratio, instead of
    growing the key linearly with it (e.g. 64x for ``block_size=256``,
    ``hash_block_size=4``).
    """

    def __init__(
        self,
        block_hashes: Sequence[BlockHash],
        hash_block_size: int,
        target_block_size: int,
    ):
        # Accept any indexable sequence (e.g. the lazy ``BlobBlockHashes``), not
        # just ``list``; the base only indexes/sizes it.
        assert target_block_size % hash_block_size == 0
        self.block_hashes = block_hashes  # type: ignore[assignment]
        self.scale_factor = target_block_size // hash_block_size

    def _get_value_at(self, idx: int) -> BlockHash:
        return self.block_hashes[idx * self.scale_factor + self.scale_factor - 1]

chunk_hashes_for_block_size(block_hashes, hash_block_size, block_size)

Map hash_block_size-granular block hashes to one compact hash per block_size chunk (the chunk's last sub-hash). Returns block_hashes unchanged when the two sizes are equal.

Source code in vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/data.py
def chunk_hashes_for_block_size(
    block_hashes: Sequence[BlockHash],
    hash_block_size: int,
    block_size: int,
) -> Sequence[BlockHash]:
    """Map ``hash_block_size``-granular block hashes to one compact hash per
    ``block_size`` chunk (the chunk's last sub-hash). Returns ``block_hashes``
    unchanged when the two sizes are equal.
    """
    if block_size == hash_block_size:
        return block_hashes
    # Structurally a Sequence[BlockHash] (indexable + sized); the base class
    # just isn't declared as one.
    return cast(
        "Sequence[BlockHash]",
        _CompactChunkHashList(block_hashes, hash_block_size, block_size),
    )