1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
use {
    solana_sdk::{
        instruction::{CompiledInstruction, Instruction},
        message::SanitizedMessage,
    },
    std::{cell::RefCell, rc::Rc},
};

/// Records and compiles cross-program invoked instructions
#[derive(Clone, Debug, Default, PartialEq)]
pub struct InstructionRecorder {
    inner: Rc<RefCell<Vec<(usize, Instruction)>>>,
}

impl InstructionRecorder {
    pub fn compile_instructions(
        &self,
        message: &SanitizedMessage,
    ) -> Option<Vec<CompiledInstruction>> {
        self.inner
            .borrow()
            .iter()
            .skip(1)
            .map(|(_, ix)| message.try_compile_instruction(ix))
            .collect()
    }

    pub fn record_instruction(&self, stack_height: usize, instruction: Instruction) {
        self.inner.borrow_mut().push((stack_height, instruction));
    }

    pub fn get(&self, index: usize) -> Option<Instruction> {
        self.inner
            .borrow()
            .get(index)
            .map(|(_, instruction)| instruction.clone())
    }

    pub fn find(&self, stack_height: usize, index: usize) -> Option<Instruction> {
        let mut current_index = 0;
        self.inner
            .borrow()
            .iter()
            .rev()
            .skip(1)
            .find(|(this_stack_height, _)| {
                if stack_height == *this_stack_height {
                    if index == current_index {
                        return true;
                    } else {
                        current_index = current_index.saturating_add(1);
                    }
                }
                false
            })
            .map(|(_, instruction)| instruction.clone())
    }
}