Skip to main content

Frame

Struct Frame 

Source
pub struct Frame<'a> { /* private fields */ }
Expand description

Execution frame holding the instruction’s accounts and data.

Frame is the entry point for Hopper’s phased execution model. It tracks which accounts have been borrowed (mutably or immutably) to prevent aliasing violations at runtime.

Implementations§

Source§

impl<'a> Frame<'a>

Source

pub fn new( program_id: &'a Address, accounts: &'a [AccountView], instruction_data: &'a [u8], ) -> Result<Self, ProgramError>

Create a new execution frame.

Source

pub fn program_id(&self) -> &Address

Program ID.

Source

pub fn account_count(&self) -> usize

Number of accounts in this frame.

Source

pub fn account_view(&self, index: usize) -> Result<&AccountView, ProgramError>

Get raw account view by index.

Source

pub fn ix_data(&mut self) -> &mut SliceCursor<'a>

Get instruction data cursor.

Source

pub fn ix_data_raw(&self) -> &[u8]

Get raw instruction data.

Source

pub fn account(&self, index: usize) -> Result<FrameAccount<'_>, ProgramError>

Get an immutable account view (no borrow tracking needed for reads).

Source

pub fn account_mut( &mut self, index: usize, ) -> Result<FrameAccountMut<'_>, ProgramError>

Get a mutable account view with runtime borrow checking.

Returns an error if this account is already borrowed mutably. This prevents the most dangerous aliasing pattern in Solana programs.

Source

pub fn segment_borrows(&self) -> &SegmentBorrowRegistry

Get the segment borrow registry for direct manipulation.

Source

pub fn segment_borrows_mut(&mut self) -> &mut SegmentBorrowRegistry

Get the mutable segment borrow registry.

Source

pub fn segment_ref<'f, T: Pod + FixedLayout>( &'f mut self, index: usize, offset: u32, ) -> Result<SegRef<'f, T>, ProgramError>

Read a typed value from a segment of an account’s data region.

Registers a read borrow for the given byte range, then projects the pointer through the live byte-borrow guard into a Ref<'_, T>. Returns an error if the range conflicts with an existing write borrow on the same account.

offset is relative to the layout body (after the 16-byte header).

§Preferred path

Most programs don’t need to construct a Frame at all, the hopper_runtime::Context handler signature gives you ctx.segment_ref::<T>(index, abs_offset) with the same tightened Pod contract, the same RAII guard, and none of the phased execution bookkeeping. Reach for Frame::segment_ref only when you’re inside the advanced frame-gated execution model.

§Safety Contract
  • T must be Pod + FixedLayout (safe to interpret from any bit pattern, alignment-1, no padding).
  • Bounds are checked at runtime.
  • Borrow conflicts are checked at runtime.
  • The returned SegRef<T> owns both the byte-slice borrow and a RAII lease on the segment registry entry. Dropping it releases both, no sticky-ledger residue from post-audit.
Source

pub fn segment_mut<'f, T: Pod + FixedLayout>( &'f mut self, index: usize, offset: u32, ) -> Result<SegRefMut<'f, T>, ProgramError>

Get a mutable typed reference to a segment of an account’s data.

Registers a write borrow for the given byte range, then projects the pointer through the live byte-borrow guard into a RefMut<'_, T>. Returns an error if the range overlaps any existing borrow (read or write) on the same account.

This is the core primitive that makes Hopper strictly better than raw Pinocchio: you get the same pointer arithmetic, but with segment-level conflict detection that prevents aliasing bugs.

offset is relative to the layout body (after the 16-byte header).

§Safety Contract
  • T must be Pod + FixedLayout.
  • Bounds are checked at runtime.
  • Borrow conflicts are checked at runtime.
  • The returned SegRefMut<T> carries both the account-level exclusive byte guard and a RAII registry lease, dropping it releases the full borrow cleanly, so sequential patterns on the same segment compose like ordinary Rust borrows.
§Example
// Only borrows the "balance" region [32..40), not the entire account.
{
    let mut balance = frame.segment_mut::<WireU64>(0, 32)?;
    balance.set(balance.get() + amount);
} // SegRefMut drops here, releasing both guards.

// Now we can re-borrow the same (or a different) segment safely.
let mut balance_again = frame.segment_mut::<WireU64>(0, 32)?;
Source

pub unsafe fn segment_mut_unchecked<T: Pod + FixedLayout>( &self, index: usize, offset: u32, ) -> Result<RefMut<'_, T>, ProgramError>

Unsafe escape hatch for performance-critical paths.

Skips borrow tracking entirely. The caller takes full responsibility for aliasing safety. Returns a RefMut<T> so the borrow guard is still tied to the returned value’s lifetime, the “unchecked” part is only the conflict-detection skip, not the lifetime tying.

§Safety

The caller must guarantee no other mutable reference to the same byte range exists for the duration of the returned reference, and that no overlapping segment borrow has been registered.

Source

pub fn require_signer(&self, index: usize) -> ProgramResult

Validate that account at index is a signer.

Source

pub fn require_writable(&self, index: usize) -> ProgramResult

Validate that account at index is writable.

Source

pub fn require_owned(&self, index: usize) -> ProgramResult

Validate that account at index is owned by this program.

Source

pub fn require_authority(&self, index: usize) -> ProgramResult

Validate signer + writable (common pattern for authority accounts).

Source

pub fn require_unique(&self, a: usize, b: usize) -> ProgramResult

Validate two accounts are unique.

Source

pub fn require_program(&self, index: usize, program: &Address) -> ProgramResult

Require an account matches a specific program address.

Auto Trait Implementations§

§

impl<'a> Freeze for Frame<'a>

§

impl<'a> RefUnwindSafe for Frame<'a>

§

impl<'a> Send for Frame<'a>

§

impl<'a> Sync for Frame<'a>

§

impl<'a> Unpin for Frame<'a>

§

impl<'a> UnsafeUnpin for Frame<'a>

§

impl<'a> UnwindSafe for Frame<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.