Skip to main content

Module segment_lease

Module segment_lease 

Source
Expand description

RAII-leased typed segment guards.

The Hopper Safety Audit called out that SegmentBorrowRegistry was being used as an instruction-sticky ledger: every segment_ref / segment_mut call appended an entry, nothing ever released, and the entries outlived the returned Ref<T> / RefMut<T> for the rest of the instruction. That model makes legitimate sequential patterns like

{ let mut b = ctx.segment_mut::<WireU64>(0, BAL)?; *b += amount; }
{ let mut b = ctx.segment_mut::<WireU64>(0, BAL)?; *b += more;   }

impossible inside one instruction, because the second call would collide with the lingering entry from the first.

SegmentLease, SegRef, and SegRefMut replace that model with real RAII: the registry entry lives exactly as long as the returned typed guard, and dropping the guard releases the entry. Sequential non-overlapping (and sequential same-region-read-then- write) patterns now behave exactly the way Rust borrowers expect.

§Representation

SegmentLease stores a raw pointer to the registry plus a PhantomData<&'a mut SegmentBorrowRegistry>. Raw is necessary because the returned SegRef<T> otherwise exclusively borrows the whole Context, which would prevent even reading another account , a regression far worse than the sticky behavior we are fixing. The PhantomData ties the lease’s lifetime to the registry’s, so use-after-free is impossible at the type level. Drop performs a single swap-remove; no allocation, no heap touch.

§Why a wrapper, not a field on Ref/RefMut

The canonical hopper_runtime::Ref / RefMut are kept flat on Solana ({ptr, state_ptr} = 2 words, see borrow.rs). Adding a registry pointer to them would re-inflate the flat representation for every access path, even the whole-account load() path that doesn’t touch the segment registry. Keeping the lease as a separate wrapper means load() stays at 2 words and only segment access pays for the lease (one extra pointer-word on Solana).

Structs§

SegRef
Shared typed segment guard: a Ref<T> paired with a SegmentLease that releases the registry entry on drop.
SegRefMut
Exclusive typed segment guard.
SegmentLease
RAII lease on one registered entry in a SegmentBorrowRegistry.