Skip to main content

Context

Struct Context 

Source
pub struct Context<'a> {
    pub program_id: &'a Address,
    pub instruction_data: &'a [u8],
    /* private fields */
}
Expand description

Execution context for a Hopper instruction handler.

Wraps the program_id, account slice, and instruction data into a single object with structured access patterns.

§Authored flow

pub fn deposit(ctx: &Context, amount: u64) -> ProgramResult {
    let authority = ctx.account(0)?;
    let vault = ctx.account(1)?;

    authority.require_signer()?;
    vault.require_writable()?;
    vault.check_disc(1)?;

    let mut state = vault.load_mut::<VaultState>()?;
    state.balance = state.balance.checked_add(amount).ok_or(ProgramError::ArithmeticOverflow)?;
    Ok(())
}

Fields§

§program_id: &'a Address

The program’s own address.

§instruction_data: &'a [u8]

Raw instruction data (past the discriminator byte, if applicable).

Implementations§

Source§

impl<'a> Context<'a>

Source

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

Create a new context from the entrypoint parameters.

Source

pub fn program_id(&self) -> &Address

Program ID.

Source

pub fn instruction_data(&self) -> &'a [u8]

Raw instruction data.

Source

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

Get an account by index.

Source

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

Get an account by index (mutation-intent variant).

Functionally identical to account() since AccountView uses interior mutability for data access (overlay_mut, load_mut, try_borrow_mut). The distinct name signals that the caller intends to write through the returned reference.

Source

pub fn num_accounts(&self) -> usize

Get the total number of accounts.

Source

pub fn accounts(&self) -> &[AccountView]

Get all accounts as a slice.

Source

pub fn borrows(&self) -> &SegmentBorrowRegistry

Access the instruction-scoped segment borrow registry.

Source

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

Mutably access the instruction-scoped segment borrow registry.

Source

pub fn audit_accounts(&self) -> AccountAudit<'a>

Inspect the instruction account slice for duplicate aliases.

Source

pub fn remaining_accounts(&self, from: usize) -> &[AccountView]

Get the remaining accounts starting at from.

Source

pub fn require_accounts(&self, n: usize) -> ProgramResult

Require at least n accounts are present.

Source

pub fn require_unique_accounts(&self) -> ProgramResult

Require all account addresses to be unique.

Source

pub fn require_unique_writable_accounts(&self) -> ProgramResult

Require that no duplicated account is writable in this instruction.

Source

pub fn require_unique_signer_accounts(&self) -> ProgramResult

Require that no duplicated account is used as a signer role.

Source

pub fn require_data_len(&self, n: usize) -> ProgramResult

Require at least n bytes of instruction data.

Source

pub fn load<T: LayoutContract>( &self, index: usize, ) -> Result<Ref<'_, T>, ProgramError>

Validate-and-load the full typed layout for an account.

This is the indexed shortcut for ctx.account(idx)?.load::<T>(). It’s the canonical “Tier A” access path: the runtime checks the Hopper header, validates the data length, and projects the typed view in one inlined call. no extra cost over the spelled-out form.

Source

pub fn load_mut<T: LayoutContract>( &self, index: usize, ) -> Result<RefMut<'_, T>, ProgramError>

Validate-and-load a mutable typed layout for an account.

Indexed shortcut for ctx.account(idx)?.load_mut::<T>(). The returned guard holds the account-level exclusive borrow until it drops.

Source

pub fn load_cross_program<T: LayoutContract>( &self, index: usize, ) -> Result<Ref<'_, T>, ProgramError>

Cross-program load: validate ABI fingerprint without ownership check.

Use this when reading an account whose owner is another program but whose layout is published as a Hopper layout contract.

Source

pub fn segment_ref<'b, T: Pod>( &'b mut self, index: usize, abs_offset: u32, ) -> Result<SegRef<'b, T>, ProgramError>

Register a read borrow for a segment of an account and return a SegRef<T> that releases both the account-level byte guard and the segment registry lease on drop.

index is the account index. abs_offset is the absolute byte offset within the account data (including header bytes).

§Type Safety

T must implement Pod (substrate-level “safe to overlay on raw bytes” contract: every bit pattern valid, align-1, no padding, no interior pointers). Segment borrow tracking prevents conflicting write access to the same byte range for the guard’s lifetime.

§Canonical path (audit ST1 / winning-architecture spec)

Three variants exist for different offset sources:

VariantUse when
segment_ref_typed (canonical)Offset is a compile-time constant (the common case). The const OFFSET: u32 generic becomes an immediate in the pointer arithmetic.
segment_ref_constOffset comes from a runtime [Segment] value (dispatching dynamically between named fields).
segment_ref (this method)Offset is fully dynamic (iterating segments in a loop, for example).

#[hopper::context]-generated accessors default to the canonical typed path; reach for the others only when the use case genuinely needs a runtime offset.

Source

pub fn segment_mut<'b, T: Pod>( &'b mut self, index: usize, abs_offset: u32, ) -> Result<SegRefMut<'b, T>, ProgramError>

Register a write borrow for a segment of an account.

Validates bounds, checks writable, and registers a leased exclusive borrow, then returns a SegRefMut<T> that releases on drop.

This is the primitive that enables safe concurrent mutation of non-overlapping account regions. Hopper’s core innovation . and the lease model (added post-audit) makes sequential same-region borrows inside one instruction work correctly.

Source

pub fn segment_ref_const<'b, T: Pod>( &'b mut self, index: usize, segment: Segment, ) -> Result<SegRef<'b, T>, ProgramError>

Const-driven segment read: pass a compile-time [Segment] and the account index. Lowers to the same pointer-plus-const-offset shape as segment_ref but without the caller hand-rolling the offset + size arguments.

Source

pub fn segment_mut_const<'b, T: Pod>( &'b mut self, index: usize, segment: Segment, ) -> Result<SegRefMut<'b, T>, ProgramError>

Const-driven exclusive segment access. Pair with #[hopper::state] constants for zero-overhead field writes.

Source

pub fn segment_ref_typed<'b, T: Pod, const OFFSET: u32>( &'b mut self, index: usize, segment: TypedSegment<T, OFFSET>, ) -> Result<SegRef<'b, T>, ProgramError>

Typed-segment read: the type and offset are both compile-time constants, baked into a [TypedSegment] zero-sized marker.

Source

pub fn segment_mut_typed<'b, T: Pod, const OFFSET: u32>( &'b mut self, index: usize, segment: TypedSegment<T, OFFSET>, ) -> Result<SegRefMut<'b, T>, ProgramError>

Typed-segment write. Mirrors [segment_ref_typed] for the exclusive path.

Source

pub unsafe fn raw_ref<T: Pod>( &self, index: usize, ) -> Result<Ref<'_, T>, ProgramError>

Explicit unsafe whole-account typed read.

Source

pub unsafe fn raw_mut<T: Pod>( &self, index: usize, ) -> Result<RefMut<'_, T>, ProgramError>

Explicit unsafe whole-account typed write.

Source

pub unsafe fn raw_unchecked<T: Pod>( &self, index: usize, ) -> Result<RefMut<'_, T>, ProgramError>

Explicit unsafe escape hatch for whole-account typed projection.

This bypasses segment borrow tracking. The caller is responsible for alias safety and for using a type that matches the account bytes.

Source

pub unsafe fn as_mut_ptr(&self, index: usize) -> Result<*mut u8, ProgramError>

Canonical raw-pointer escape hatch to an account’s data buffer.

Returns a pointer to the first byte of accounts[index]’s data region (after the runtime account header, before any Hopper 16-byte layout header). The pointer is valid for reads and writes for the lifetime of the account view and carries no borrow-tracking obligations. Dereferencing it is unsafe because the caller takes over alias-safety responsibility that the segment registry normally upholds.

This is the explicit power-user primitive the audit asks for: safe code reaches for segment_ref_typed / segment_mut_typed / the generated ctx.<field>_segment_mut(...) accessors; raw code drops to unsafe { ctx.as_mut_ptr(0)?.add(offset) as *mut T }.

§Safety

The caller must guarantee no aliasing mutable borrow is held on the same account for the duration of any write through the returned pointer. The returned pointer must be dereferenced within the 'info lifetime of the account view; reading past AccountView::data_len() is undefined behaviour.

Source

pub fn as_ptr(&self, index: usize) -> Result<*const u8, ProgramError>

Immutable sibling of as_mut_ptr. Returns a *const u8.

Shared-borrow checking still runs, so calling this while an exclusive borrow is live on the same account fails with AccountBorrowFailed. The return value is safe to obtain; the caller only needs unsafe to dereference it.

Source

pub fn read_data<T: Pod>(&self, offset: usize) -> Result<T, ProgramError>

Read instruction data as a typed value (unaligned, little-endian safe).

Reads size_of::<T>() bytes starting at offset via read_unaligned. Caller must ensure T is a plain-old-data type where all bit patterns are valid.

Source

pub fn data_slice( &self, offset: usize, len: usize, ) -> Result<&[u8], ProgramError>

Get a byte slice from instruction data.

Source

pub fn instruction_tag(&self) -> Result<u8, ProgramError>

Read the first byte of instruction data as an instruction tag.

Common pattern for byte-tag dispatch.

Auto Trait Implementations§

§

impl<'a> Freeze for Context<'a>

§

impl<'a> RefUnwindSafe for Context<'a>

§

impl<'a> Send for Context<'a>

§

impl<'a> Sync for Context<'a>

§

impl<'a> Unpin for Context<'a>

§

impl<'a> UnsafeUnpin for Context<'a>

§

impl<'a> UnwindSafe for Context<'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.