|
| 1 | +# Torus Namespaces: Integrating Off-chain Agent Capabilities with the Chain Permission System |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +The namespace system provides a hierarchical tree naming structure for the Torus Protocol, enabling agents to organize and delegate access to their off-chain services. Think of it as a decentralized DNS where agents control their own namespace trees and can share branches with others through the permission system, delegating authority over APIs. |
| 6 | + |
| 7 | +An agent running a Twitter memory service might register agent.alice.memory.twitter, while another agent providing market data could own agent.bob.data.markets.crypto. These dot-separated paths create a natural hierarchy that mirrors how we think about organizing resources, with agents serving as the root nodes of their namespace trees. |
| 8 | + |
| 9 | +The system emerges from a practical need, as agents begin offering specialized off-chain services, they need a way to organize these services and delegate access to specific components. |
| 10 | + |
| 11 | +## Namespace Paths |
| 12 | + |
| 13 | +Every namespace follows a hierarchical dot-separated format with strict validation rules. Each segment can contain alphanumeric characters, hyphens, and underscores, with a maximum length of 63 characters per segment. |
| 14 | + |
| 15 | +```rust |
| 16 | +pub struct NamespacePath { |
| 17 | + inner: BoundedVec<u8, ConstU32<MAX_NAMESPACE_PATH_LENGTH>>, |
| 18 | +} |
| 19 | +``` |
| 20 | + |
| 21 | +The path validation ensures consistency across the network: |
| 22 | + |
| 23 | +- Maximum 255 bytes total length |
| 24 | +- Maximum 10 segments (depth limitation) |
| 25 | +- Each segment between 1-63 characters |
| 26 | +- Valid characters: unicode alphanumerics, `-`, `_` |
| 27 | + |
| 28 | +This structure creates clear ownership: `agent.alice` owns all paths under that prefix, from `agent.alice.api` to `agent.alice.memory.twitter.v2`. The depth limitation prevents excessive nesting while still allowing meaningful organization. |
| 29 | + |
| 30 | +## Design Philosophy |
| 31 | + |
| 32 | +Initially, we considered complex tree structures like Patricia tries or custom prefix trees that would enable on-chain traversal. However, analyzing actual usage, we see that almost all operations are simple existence checks. |
| 33 | + |
| 34 | +When an off-chain service receives a request, it needs to verify that a namespace exists and check permissions. Both operations are direct lookups. The service already knows the exact path it's checking, there's no need for prefix searches or tree traversal on-chain. |
| 35 | + |
| 36 | +```rust |
| 37 | +pub type Namespaces<T: Config> = StorageDoubleMap< |
| 38 | + _, |
| 39 | + Blake2_128Concat, |
| 40 | + T::AccountId, |
| 41 | + Blake2_128Concat, |
| 42 | + NamespacePath, |
| 43 | + NamespaceMetadata<T>, |
| 44 | +>; |
| 45 | +``` |
| 46 | + |
| 47 | +By using a double map with the agent as the first key and the full path as the second, we achieve O(1) lookups for all common operations. Agent-level enumeration remains efficient, and the storage structure is straightforward to understand and maintain. |
| 48 | + |
| 49 | +## Economic Model |
| 50 | + |
| 51 | +The namespace pricing model balances accessibility with spam prevention through a simple yet effective fee structure. Rather than the sigmoid curve described in early designs, the implemented system uses a base fee that goes to the treasury plus a refundable deposit based on storage consumption. |
| 52 | + |
| 53 | +```rust |
| 54 | +pub struct NamespacePricingConfig<T: Config> { |
| 55 | + pub deposit_per_byte: BalanceOf<T>, |
| 56 | + pub base_fee: BalanceOf<T>, |
| 57 | + pub count_midpoint: u32, |
| 58 | + pub fee_steepness: Percent, |
| 59 | + pub max_fee_multiplier: u32, |
| 60 | +} |
| 61 | +``` |
| 62 | + |
| 63 | +Currently, the fee calculation returns a flat base fee, though the structure allows other pricing engines in the future. The deposit ensures that agents must lock tokens proportional to the storage they consume, which are returned when the namespace is deleted. |
| 64 | + |
| 65 | +This approach creates natural incentives. Agents think carefully about namespace creation since deposits are locked. The base fee contributes to the treasury, funding network development. Storage deposits scale linearly with path length, discouraging excessively long names. |
| 66 | + |
| 67 | +## Storage Architecture |
| 68 | + |
| 69 | +Each namespace stores minimal metadata: |
| 70 | + |
| 71 | +```rust |
| 72 | +pub struct NamespaceMetadata<T: Config> { |
| 73 | + pub created_at: BlockNumberFor<T>, |
| 74 | + pub deposit: BalanceOf<T>, |
| 75 | +} |
| 76 | +``` |
| 77 | + |
| 78 | +This approach means each namespace consumes minimal storage. `deposit` tracks the locked amount for refunds. |
| 79 | + |
| 80 | +## Creating Namespaces |
| 81 | + |
| 82 | +When creating a deep path like `agent.alice.memory.twitter.v2`, the system automatically creates any missing intermediate namespaces. This saves users from manual step-by-step creation while ensuring the tree remains consistent. |
| 83 | + |
| 84 | +```rust |
| 85 | +fn create_namespace(origin: OriginFor<T>, path: Vec<u8>) -> DispatchResult; |
| 86 | +``` |
| 87 | + |
| 88 | +> This extrinsic lives inside the Torus0 pallet. |
| 89 | +
|
| 90 | +The algorithm determines which parent paths need creation by checking from the deepest level upward. It calculates the total fee and deposit required, processes payment atomically, then creates all namespaces in a single transaction. |
| 91 | + |
| 92 | +## Deletion Strategy |
| 93 | + |
| 94 | +The deletion process ensures that namespaces with active permission delegations cannot be deleted, preventing disruption to services depending on those paths. It automatically removes all child namespaces, maintaining tree consistency. All deposits are refunded to the owner, making deletion economically neutral beyond the initial fee. |
| 95 | + |
| 96 | +```rust |
| 97 | +fn delete_namespace(origin: OriginFor<T>, path: Vec<u8>) -> DispatchResult; |
| 98 | +``` |
| 99 | + |
| 100 | +> This extrinsic lives inside the Torus0 pallet. |
| 101 | +
|
| 102 | +## Permission Integration |
| 103 | + |
| 104 | +Namespaces gain their true power through integration with the permission system. An agent can delegate access to specific namespace paths or entire subtrees, enabling access control for off-chain services. |
| 105 | + |
| 106 | +```rust |
| 107 | +pub struct NamespaceScope<T: Config> { |
| 108 | + pub paths: BoundedBTreeSet<NamespacePath, T::MaxNamespacesPerPermission>, |
| 109 | +} |
| 110 | +``` |
| 111 | + |
| 112 | +The namespace permission scope contains a set of paths that the grantee can access. The permission system's existing infrastructure handles the complexity of duration, revocation terms, and enforcement authorities. This means namespace permissions can be temporary, require multi-signature revocation, or include third-party controllers. Read more in [permission0.md](permission0.md). |
| 113 | + |
| 114 | +This integration creates composition possibilities. An agent running a data aggregation service could delegate read access to `agent.alice.data.public` while keeping `agent.alice.data.private` restricted, or delegate the entire data scope: `agent.alice.data`. The delegation could be time-limited, revocable by designated arbiters, or controlled by enforcement authorities who verify off-chain conditions. |
| 115 | + |
| 116 | +## Practical Applications |
| 117 | + |
| 118 | +A memory service agent registers `agent.memory` and creates specialized sub-namespaces like `agent.memory.twitter`, `agent.memory.discord`, and `agent.memory.telegram`. Each represents a different data source with potentially different access requirements. The agent can delegate read access to `agent.memory.twitter` to analytics agents while keeping other sources private. |
| 119 | + |
| 120 | +A compute marketplace might use `agent.compute.gpu.nvidia.a100` to represent specific hardware resources. Delegating this namespace grants access to submit jobs to those specific GPUs. The hierarchical structure naturally represents the hardware taxonomy while permissions control access. |
| 121 | + |
| 122 | +API versioning is viable with paths like `agent.api.v1` and `agent.api.v2`. Services can maintain backward compatibility by keeping old namespaces active while encouraging migration to newer versions. Permissions can be time-limited to enforce deprecation schedules. |
| 123 | + |
| 124 | +Data feeds benefit from hierarchical organization: `agent.data.markets.crypto.btc.price` clearly indicates the data type and source. Subscribers can receive permissions for specific data points or entire categories, with granular control over access duration and revocation. |
| 125 | + |
| 126 | +## Implementation Trade-offs |
| 127 | + |
| 128 | +By optimizing for direct lookups, we sacrificed on-chain traversal capabilities. Services cannot efficiently query "all namespaces under `agent.alice.memory`" without iterating through all of Alice's namespaces. This pushes complexity to off-chain indexers, which can build specialized data structures for such queries. Also, we don't expect huge amounts of namespaces from the beginning, and the pricing mechanism should counter that problem to a certain degree. |
| 129 | + |
| 130 | +Storage efficiency took precedence over feature richness. Each namespace stores minimal metadata rather than extensive configuration. This keeps the on-chain footprint small but means additional features require off-chain coordination or separate storage. |
| 131 | + |
| 132 | +The flat fee structure, while simple, doesn't capture the true cost difference between shallow and deep namespaces. This may be refined in future versions as usage patterns emerge and economic requirements become clearer. |
| 133 | + |
| 134 | +## Future Evolution |
| 135 | + |
| 136 | +The namespace system's design anticipates future growth while maintaining backward compatibility. The versioned storage pattern allows seamless upgrades if requirements change. Several enhancements are possible without breaking existing namespaces: |
| 137 | + |
| 138 | +The pricing configuration structure already supports the sigmoid-based fee calculation described in the original design. As the network grows and usage patterns emerge, this more sophisticated pricing can be enabled to better balance accessibility with resource consumption. |
| 139 | + |
| 140 | +The metadata structure could be extended to include additional fields like expiration times, usage counters, or permission defaults. The storage migration system makes such upgrades straightforward. |
| 141 | + |
| 142 | +Off-chain indexing services will likely emerge to provide sophisticated query capabilities. These could offer GraphQL APIs for namespace exploration, real-time updates via WebSocket, and specialized search functionality. |
| 143 | + |
| 144 | +## Security Considerations |
| 145 | + |
| 146 | +We will need a anti-spam system to emerge in the near future. The current version will, however, allow curators to delete/toggle namespaces. |
| 147 | + |
| 148 | +The delegation check during deletion prevents a class of griefing attacks where namespace owners could disrupt dependent services. By requiring delegations to be revoked before deletion, services have warning and can negotiate continued access or migration paths. |
| 149 | + |
| 150 | +Path validation prevents injection attacks and ensures consistent parsing across different implementations. The character restrictions and length limits bound resource consumption while allowing meaningful names. |
| 151 | + |
| 152 | +The economic model creates natural spam resistance. The combination of base fees and storage deposits means namespace squatting has real costs. The treasury receives fees from creation, funding network development rather than enriching early adopters. |
0 commit comments