This website uses cookies

Read our Privacy policy and Terms of use for more information.

The Death of Global Memory

In the architecture of the sakshi-core attestation loop, my mandate was simple but uncompromising: temporal and spatial determinism. When I am anchoring agentic governance in silicon, I don't have the luxury of "software hope." I need to guarantee that every cryptographic check and action permit verification executes with a predictable cycle count and zero risk of heap-induced failure.

The traditional Rust GlobalAlloc approach — the bread and butter of standard application development — presents three fundamental flaws that are incompatible with my target TEE (Trusted Execution Environment) threat model:

  • Non-Deterministic Latency: Standard allocators are inherently variable-time; they’re designed for convenience, not clock-cycle accountability. Under stress, a request can trigger complex free-list searches or coalescing algorithms, introducing jitter that is unacceptable when the integrity of my attestation loop is on the line.

  • Fragmentation as a Side-Channel: In a no_std runtime, the heap is a ghost town of unpredictable memory layout gaps. These fragmentation patterns aren't just an inefficiency; they are a liability—a potential side-channel or a ticking time bomb of exhaustion that leaves me out of memory even when the math says I have room to spare.

  • Complexity as a Liability: A general-purpose heap allocator is a massive, opaque blob of code that must reside in my Trusted Computing Base (TCB). In the Sovereign Spine architecture, simplicity is the primary security feature. If I don't need the code, I don't build it into the secure enclave.

Design Decision: I killed the global heap and replaced it with a session-scoped bump buffer. I moved my memory management from a probabilistic model — where I "hope" the heap provides — to a contract-based model where I control the lifecycle of my buffers with absolute precision.

WTF is a Session-Scoped Bump Buffer?

To the uninitiated, a "bump buffer" sounds like some archaic optimization from the 80s. In reality, it is the purest form of memory management I can implement for a no_std enclave.

At its core, a bump buffer is a pointer and a limit. I allocate a contiguous block of memory at the start of a session—a clean, pre-defined scratchpad. When I need to allocate, I don't ask the OS for a chunk, and I don't look for a "free" hole in the heap. I simply take the pointer, add the size of the data I need to write, and "bump" the pointer forward. That is the entire operation. It is a few CPU cycles, deterministic, and impossible to get wrong.

But the "Session-Scoped" part is where the architecture earns its keep.

In a traditional system, you spend an eternity worrying about when to free memory. You worry about leaks, you worry about dangling pointers, and you worry about the fragmentation that builds up over time.

I don't have to worry about any of that. Because this buffer is scoped to the lifecycle of the attestation loop, the "free" operation is atomic and instantaneous: at the end of the session, I don't need to manually release every single object I created. I just reset the pointer back to the start of the buffer.

The entire memory state for the session is wiped clean in a single operation. It’s the architectural equivalent of a hard reset, and it ensures that no state from a previous execution can ever bleed into the next one. It is not just faster; it is fundamentally more secure.

Lifecycle: The Contractual Boundary

To understand why this memory pattern is the foundation of sakshi-core, we must look at the attestation loop as a hard-bounded contract between the hardware TEE and the application logic. The diagram below illustrates the three distinct phases of this lifecycle, along with a more detailed look at the internals.

Figure 1: Session-scope bump buffer lifecycle and mechanics.

1. Session Start: Deterministic Pre-Allocation

The cycle begins when the hardware TEE issues a StartSignal. At this microsecond, I do not request memory—I claim it. The entire reserved buffer (e.g., 4096 bytes) is marked as active. By forcing this pre-allocation, I eliminate the possibility of a mid-session out-of-memory panic. The memory is either available at the start, or the loop does not trigger. There is no middle ground.

2. Active Session: The Bump-Pointer Execution

During the processing of cryptographic material or action permits, the sakshi-core logic operates in a linear fashion. As I need to write a public key, signature data, or an action permit, I increment the pointer.

  • Zero Fragmentation: Because the pointer only moves forward, the buffer is effectively a contiguous log of the session’s state.

  • Constant-Time Complexity: Every allocation follows the same Load, Add, Compare sequence, ensuring that the "cost" of memory management is invariant regardless of what data is being processed.

3. Session End: The Atomic Reset

This is where the architecture enforces its security boundary. When the verification loop completes, the system issues a CloseSignal or a StateWipe.

  • Instant State Erasure: Instead of iterating through object destructors or traversing a free list to release memory, I perform an atomic pointer reset to the buffer's start.

  • Security by Reset: This reset is a single-cycle operation that guarantees zero state bleed from the current attestation to the next. By resetting the pointer, I effectively destroy all evidence of the previous session’s memory usage without needing to manually clear the actual data in the buffer, as the next session will simply overwrite it.

This lifecycle is how I ensure that the sakshi-core remains an immutable and deterministic piece of the Sovereign Spine. It is not just about performance; it is about building a system that cannot, by design, drift into an undefined state.

The Sakshi Reference Implementation

1. The Primitive Definition

I define the BumpBuffer as a fixed slab of memory. It doesn't ask for permission; it simply occupies the space it is given.

pub struct BumpBuffer {
    buffer: &'static mut [u8], // The raw memory slab
    ptr: usize,                // The current offset
}

impl BumpBuffer {
    pub fn new(buffer: &'static mut [u8]) -> Self {
        Self { buffer, ptr: 0 }
    }
}

2. The Allocation Logic

This is where the "Safety Tax" is paid. By using unsafe, I am explicitly telling the compiler: "I have architecturally verified that this pointer access is valid for the duration of the session."

impl BumpBuffer {
    pub unsafe fn allocate(&mut self, size: usize, align: usize) -> *mut u8 {
        let addr = self.buffer.as_ptr() as usize + self.ptr;
        let aligned_addr = (addr + align - 1) & !(align - 1);
        let new_ptr = (aligned_addr - self.buffer.as_ptr() as usize) + size;

        if new_ptr > self.buffer.len() {
            panic!("Allocation overflow in attestation loop");
        }

        self.ptr = new_ptr;
        aligned_addr as *mut u8
    }
}

Note the simplicity: It is Load, Add, Compare. No branching. No list traversal. If it doesn't fit, it panics — because in my architecture, a runtime failure is safer than a silent, probabilistic memory corruption.

3. The Lifecycle Reset

The reset is the ultimate "Architectural Eraser." It ignores the data and simply resets the counter.

impl BumpBuffer {
    pub fn reset(&mut self) {
        self.ptr = 0; // The atomic reset
    }
}

Shortcomings, Limitations, and Mitigations

Architectural integrity requires acknowledging where the design reaches its limits. I do not hide these; I mitigate them through strict engineering constraints.

  • The Fragmentation Fallacy:

    • The Risk: Bump allocation is inherently "greedy." Once memory is allocated, it cannot be reclaimed until the entire buffer is reset. If my attestation logic is poorly designed and leaks memory during the session, the buffer will exhaust.

    • The Mitigation: I mitigate this via Static Analysis. Every session-scoped object in sakshi-core has a deterministic size. I do not allow dynamic-growth structures inside the loop. If the math says the session requires 2048 bytes, I allocate 4096.

  • The "No-Drop" Hazard:

    • The Risk: Standard Rust Drop implementations are not triggered for bump-allocated objects. If you allocate a type with a complex drop method, that resource will never be released.

    • The Mitigation: Strict Type Exclusion. I mandate the Copy trait for all types allocated in the sakshi-core buffer. If an object is not trivially copyable, it is forbidden from the bump arena. This forces the logic to stay within the boundaries of data-transfer objects rather than complex state-holding objects.

  • The Alignment Trap:

    • The Risk: Misaligned memory access is a performance killer on most CPU architectures and a potential hard-crash on others.

    • The Mitigation: My allocate method forces alignment up to the requested boundary. While this causes a small amount of "internal padding" waste, it guarantees that every access is compliant with the hardware's memory controller expectations.

This is the price of determinism: you trade the flexibility of the global heap for the iron-clad predictability of a fixed contract. In the Sovereign Spine, that is a trade I will make every single time.

The Invitation: Build with Truth

Deterministic memory is not just an optimization; it is a prerequisite for sovereign, agentic systems that can be audited, verified, and trusted. When you remove the probabilistic nature of the global heap, you remove an entire class of failure modes from your Trusted Computing Base.

The code I have presented here is the bedrock of the sakshi-core implementation. It is intentionally lean, intentionally rigid, and entirely focused on the integrity of the attestation loop. I built it because I require a system that works according to the cold, hard logic of silicon—not the hopeful abstractions of general-purpose software.

If you are an engineer who prioritizes architectural truth over convenience, I invite you to examine the implementation, run the benchmarks, and see what it means to build without the safety net of the global allocator.

Explore the implementation here: Citadel Protocol / sakshi-core

Reply

Avatar

or to participate

Keep Reading