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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use core::fmt;

// ADVICE EXTRACTORS
// ================================================================================================

/// Defines a set of actions which can be initiated from the VM to extract data from the advice
/// provider. These actions can only modify the advice stack.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum AdviceExtractor {
    /// Pops an element from the advice stack and returns it.
    ///
    /// # Errors
    /// Returns an error if the advice stack is empty.
    ///
    /// Inputs:
    ///  Operand stack: [...]
    ///  Advice stack: [value, ...]
    ///  Advice map: {...}
    ///  Merkle store: {...}
    ///
    /// Outputs:
    ///  Operand stack: [...]
    ///  Advice stack: [...]
    ///  Advice map: {...}
    ///  Merkle store: {...}
    ///  Return: [value]
    PopStack,

    /// Pops a word (4 elements) from the advice stack and returns it.
    ///
    /// Note: a word is popped off the stack element-by-element. For example, a `[d, c, b, a, ...]`
    /// stack (i.e., `d` is at the top of the stack) will yield `[d, c, b, a]`.
    ///
    /// # Errors
    /// Returns an error if the advice stack does not contain a full word.
    ///
    /// Inputs:
    ///  Operand stack: [...]
    ///  Advice stack: [d, c, b, a, ...]
    ///  Advice map: {...}
    ///  Merkle store: {...}
    ///
    /// Outputs:
    ///  Operand stack: [...]
    ///  Advice stack: [...]
    ///  Advice map: {...}
    ///  Merkle store: {...}
    ///  Return: [a, b, c, d]
    PopStackWord,

    /// Pops a double word (8 elements) from the advice stack and returns them.
    ///
    /// Note: words are popped off the stack element-by-element. For example, a
    /// `[h, g, f, e, d, c, b, a, ...]` stack (i.e., `h` is at the top of the stack) will yield
    /// two words: `[h, g, f,e ], [d, c, b, a]`.
    ///
    /// # Errors
    /// Returns an error if the advice stack does not contain two words.
    ///
    /// Inputs:
    ///  Operand stack: [...]
    ///  Advice stack: [h, g, f, e, d, c, b, a, ...]
    ///  Advice map: {...}
    ///  Merkle store: {...}
    ///
    /// Outputs:
    ///  Operand stack: [...]
    ///  Advice stack: [...]
    ///  Advice map: {...}
    ///  Merkle store: {...}
    ///  Return: [a, b, c, d, e, f, g, h]
    PopStackDWord,

    /// Extracts a Merkle path for the node specified by the values at the top of the operand stack
    /// and returns it to the caller.
    ///
    /// # Errors
    /// Returns an error if the Merkle store does not contain the specified Merkle path.
    ///
    /// Inputs:
    ///  Operand stack: [WORD, depth, index, ROOT, ...]
    ///  Advice stack: [...]
    ///  Advice map: {...}
    ///  Merkle store: {path, ...}
    ///
    /// Outputs:
    ///  Operand stack: [WORD, depth, index, ROOT, ...]
    ///  Advice stack: [...]
    ///  Advice map: {...}
    ///  Merkle store: {path, ...}
    ///  Return: [path]
    GetMerklePath,
}

impl fmt::Display for AdviceExtractor {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::PopStack => write!(f, "pop_stack"),
            Self::PopStackWord => write!(f, "pop_stack_word"),
            Self::PopStackDWord => write!(f, "pop_stack_dword"),
            Self::GetMerklePath => {
                write!(f, "get_merkle_path")
            }
        }
    }
}