Skip to main content

solana_program_runtime/
memory_context.rs

1use {
2    crate::invoke_context::BpfAllocator, solana_instruction::error::InstructionError,
3    solana_sbpf::memory_region::MemoryMapping,
4};
5
6enum MemoryContextType {
7    ABIv1(MemoryContext),
8    Placeholder,
9}
10
11pub struct MemoryContexts {
12    contexts: Vec<MemoryContextType>,
13}
14
15impl MemoryContexts {
16    pub(crate) fn new() -> Self {
17        Self {
18            contexts: Vec::new(),
19        }
20    }
21
22    /// Set this instruction's [`MemoryContext`].
23    pub fn set_memory_context_abi_v1(
24        &mut self,
25        memory_context: MemoryContext,
26    ) -> Result<(), InstructionError> {
27        *self
28            .contexts
29            .last_mut()
30            .ok_or(InstructionError::CallDepth)? = MemoryContextType::ABIv1(memory_context);
31        Ok(())
32    }
33
34    /// Get current instruction's [`MemoryContext`]
35    pub fn memory_context_abi_v1(&self) -> Result<&MemoryContext, InstructionError> {
36        match self.contexts.last().ok_or(InstructionError::CallDepth)? {
37            MemoryContextType::ABIv1(ctx) => Ok(ctx),
38            MemoryContextType::Placeholder => Err(InstructionError::ProgramEnvironmentSetupFailure),
39        }
40    }
41
42    /// Get current instruction's [`MemoryContext`] for mutable use.
43    pub fn memory_context_mut_abi_v1(&mut self) -> Result<&mut MemoryContext, InstructionError> {
44        let context = self
45            .contexts
46            .last_mut()
47            .ok_or(InstructionError::CallDepth)?;
48
49        match context {
50            MemoryContextType::ABIv1(ctx) => Ok(ctx),
51            MemoryContextType::Placeholder => Err(InstructionError::ProgramEnvironmentSetupFailure),
52        }
53    }
54
55    pub fn memory_mapping(&self) -> Result<&MemoryMapping, InstructionError> {
56        let mapping = match self.contexts.last().ok_or(InstructionError::CallDepth)? {
57            MemoryContextType::ABIv1(ctx) => &ctx.memory_mapping,
58            MemoryContextType::Placeholder => {
59                return Err(InstructionError::ProgramEnvironmentSetupFailure);
60            }
61        };
62
63        Ok(mapping)
64    }
65
66    pub fn memory_mapping_mut(&mut self) -> Result<&mut MemoryMapping, InstructionError> {
67        let mapping = match self
68            .contexts
69            .last_mut()
70            .ok_or(InstructionError::CallDepth)?
71        {
72            MemoryContextType::ABIv1(ctx) => &mut ctx.memory_mapping,
73            MemoryContextType::Placeholder => {
74                return Err(InstructionError::ProgramEnvironmentSetupFailure);
75            }
76        };
77
78        Ok(mapping)
79    }
80
81    #[cfg(feature = "dev-context-only-utils")]
82    pub fn mock_set_mapping_abi_v1(&mut self, memory_mapping: MemoryMapping) {
83        self.contexts = vec![MemoryContextType::ABIv1(MemoryContext {
84            allocator: BpfAllocator::new(0),
85            accounts_metadata: vec![],
86            memory_mapping: Box::new(memory_mapping),
87        })];
88    }
89
90    pub fn push_placeholder(&mut self) {
91        // We are only pushing a placeholder to be configured later
92        self.contexts.push(MemoryContextType::Placeholder);
93    }
94
95    pub fn pop(&mut self) {
96        self.contexts.pop();
97    }
98}
99
100/// This structure contains metadata about the memory for each instruction under execution.
101/// The BpfAllocator, accounts addresses in the guest and the memory mapping.
102pub struct MemoryContext {
103    pub allocator: BpfAllocator,
104    pub accounts_metadata: Vec<SerializedAccountMetadata>,
105    memory_mapping: Box<MemoryMapping>,
106}
107
108impl MemoryContext {
109    /// Creates a new memory context
110    pub fn new(
111        allocator: BpfAllocator,
112        accounts_metadata: Vec<SerializedAccountMetadata>,
113        memory_mapping: MemoryMapping,
114    ) -> Self {
115        Self {
116            allocator,
117            accounts_metadata,
118            memory_mapping: Box::new(memory_mapping),
119        }
120    }
121}
122
123#[derive(Debug, Clone)]
124pub struct SerializedAccountMetadata {
125    /// Address of the first byte of the serialized account record (the
126    /// `NON_DUP_MARKER`/duplicate-marker byte).
127    pub vm_addr: u64,
128    pub original_data_len: usize,
129    pub vm_data_addr: u64,
130    pub vm_key_addr: u64,
131    pub vm_lamports_addr: u64,
132    pub vm_owner_addr: u64,
133}