Expand description
Chain-backed OriginDirectory implementation.
Resolves a request’s namespace to the set of currently-active operator
NodeIds authorised as origins for it. The resolution chain (ADR 022 §
FIND_VALUE Flow “Origin discovery”, ADR 011 § Origin Assignment
Authority) is:
OriginAssignment.getOrigins(namespaceId) → [operator...]
→ drop operators the local ContentDenylist denies (the origin ∪
operator blacklist union the watcher syncs from ContentBlacklist,
plus the operator’s own [content] denied_origins)
→ capacity-bond reverse projection (operator → NodeId, binding only)
→ keep operators the shared StakerSet reports active
The blacklist drop is this node protecting itself: getOrigins is a routing
hint the contract does not filter (ADR 011 § Interaction with
ContentBlacklist), so the consumer applies the same deny-set its delivery
gate already holds rather than trusting the seat set to be blacklist-clean.
The bare hash carries no origin information (ADR 002 § Retrieval by
namespace): the request supplies the namespace its content is published
under. namespaceId == 0 has no authorized origins, so it resolves to no
origins here and is never fetched or cached.
Namespace creation is permissionless and free, so this directory does not
mirror the whole chain-side namespace set up front: it resolves each
namespace lazily, on first request, and caches the result (positive or
negative) behind a split TTL (crate::dht::lazy_origin_cache). A live
cache hit — including a cached “no origins” — resolves with no RPC; a
cold miss issues one getOrigins(namespace) call. Chain reads therefore
scale with the namespaces this node is actually asked to serve, not the
permissionless global namespace count.
The cache stores only the raw operator address set; it never stores
resolved NodeIds or liveness. Both the operator → NodeId binding (the
shared capacity-bond reverse projection) and staker liveness (the shared
StakerSet) are read live at resolution time, so a TTL-anchored cache
entry never goes stale on the parts of the answer that can change without
a new getOrigins call.
A getOrigins RPC failure fails closed: the lookup resolves no origins
for that request, and — because a transient RPC failure must not be frozen
for a TTL — the result is not cached, so the next request retries.
Structs§
- Chain
Origin Directory - Chain-backed origin directory: a lazy TTL cache over
getOrigins, resolving operators to activeNodeIds against the shared capacity-bond reverse projection. No background watcher and no whole-directory mirror — a singlegetOrigins(ns)RPC fires only on a cold-namespace miss, and chain reads therefore scale with the namespaces this node is actually asked to serve, not the permissionless global namespace count.