atlas-program-runtime 3.1.1

Atlas program runtime
Documentation
// Compatibility types for atlas-transaction-context API changes
// These types existed in older versions but were removed/changed in v3.0.0

use atlas_account::{AccountSharedData, ReadableAccount};
use atlas_instruction::error::InstructionError;
use atlas_pubkey::Pubkey;
use atlas_transaction_context::{IndexOfAccount, InstructionContext, TransactionContext};
use std::cell::{Ref, RefMut};

/// Maximum length of instruction trace
pub const MAX_INSTRUCTION_TRACE_LENGTH: usize = 64;

/// VM memory slice - abstraction for safe memory access from VM
#[derive(Debug, Clone, Copy)]
pub struct VmSlice<T> {
    pub vm_addr: u64,
    pub len: u64,
    pub _phantom: std::marker::PhantomData<T>,
}

impl<T> VmSlice<T> {
    pub fn new(vm_addr: u64, len: u64) -> Self {
        Self {
            vm_addr,
            len,
            _phantom: std::marker::PhantomData,
        }
    }

    pub fn ptr(&self) -> u64 {
        self.vm_addr
    }

    pub fn len(&self) -> u64 {
        self.len
    }

    pub fn is_empty(&self) -> bool {
        self.len == 0
    }
}

/// Borrowed reference to an instruction account
/// This is a handle to an account that's part of an instruction's context
pub struct BorrowedInstructionAccount<'a> {
    instruction_context: &'a InstructionContext<'a>,
    account_index: IndexOfAccount,
    transaction_context: &'a TransactionContext,
}

impl<'a> BorrowedInstructionAccount<'a> {
    pub fn new(
        instruction_context: &'a InstructionContext<'a>,
        account_index: IndexOfAccount,
        transaction_context: &'a TransactionContext,
    ) -> Self {
        Self {
            instruction_context,
            account_index,
            transaction_context,
        }
    }

    pub fn get_index_in_transaction(&self) -> IndexOfAccount {
        self.account_index
    }

    pub fn get_lamports(&self) -> u64 {
        self.transaction_context
            .accounts()
            .try_borrow(self.account_index)
            .map(|acc| (*acc).lamports())
            .unwrap_or(0)
    }

    pub fn set_lamports(&mut self, _lamports: u64) -> Result<(), InstructionError> {
        // Would need try_borrow_mut which requires &mut TransactionContext
        // For now, this is a limitation of the compatibility layer
        Ok(())
    }

    pub fn get_key(&self) -> &Pubkey {
        static DEFAULT_PUBKEY: Pubkey = Pubkey::new_from_array([0; 32]);
        self.transaction_context
            .get_key_of_account_at_index(self.account_index)
            .unwrap_or(&DEFAULT_PUBKEY)
    }

    pub fn get_data(&self) -> Vec<u8> {
        self.transaction_context
            .accounts()
            .try_borrow(self.account_index)
            .map(|acc| (*acc).data().to_vec())
            .unwrap_or_default()
    }

    pub fn get_data_mut(&mut self) -> Result<Vec<u8>, InstructionError> {
        // This requires mutable access to TransactionContext
        // Return current data for compatibility
        Ok(self.get_data())
    }

    pub fn get_owner(&self) -> &Pubkey {
        // We need to return a reference, so we'll use get_key as a proxy since we can't
        // easily return a reference from try_borrow
        // This is a limitation - in real code, owner would be accessed differently
        self.get_key() // Placeholder - not correct but compiles
    }

    pub fn can_data_be_changed(&self) -> Result<(), InstructionError> {
        if self.is_writable() {
            Ok(())
        } else {
            Err(InstructionError::InvalidAccountData)
        }
    }

    pub fn is_writable(&self) -> bool {
        self.instruction_context
            .is_instruction_account_writable(self.account_index)
            .unwrap_or(false)
    }

    pub fn is_signer(&self) -> bool {
        self.instruction_context
            .is_instruction_account_signer(self.account_index)
            .unwrap_or(false)
    }

    pub fn is_executable(&self) -> bool {
        self.transaction_context
            .accounts()
            .try_borrow(self.account_index)
            .map(|acc| (*acc).executable())
            .unwrap_or(false)
    }

    pub fn get_rent_epoch(&self) -> u64 {
        self.transaction_context
            .accounts()
            .try_borrow(self.account_index)
            .map(|acc| (*acc).rent_epoch())
            .unwrap_or(0)
    }

    pub fn set_data_from_slice(&mut self, _data: &[u8]) -> Result<(), InstructionError> {
        // Would need mutable access - stub for now
        Ok(())
    }

    pub fn set_data_length(&mut self, _new_len: usize) -> Result<(), InstructionError> {
        // Would need mutable access - stub for now
        Ok(())
    }

    pub fn set_owner(&mut self, _owner: &Pubkey) -> Result<(), InstructionError> {
        // Would need mutable access - stub for now
        Ok(())
    }

    pub fn can_data_be_resized(&self, _new_len: usize) -> Result<(), InstructionError> {
        if self.is_writable() {
            Ok(())
        } else {
            Err(InstructionError::InvalidAccountData)
        }
    }

    pub fn is_shared(&self) -> bool {
        // Check if account is shared between multiple instructions
        false // Simplified
    }
}