ergotree_interpreter/eval/
context.rs

1use crate::sigma_protocol::prover::ContextExtension;
2use bounded_vec::BoundedVec;
3use ergo_chain_types::{Header, PreHeader};
4use ergotree_ir::chain::ergo_box::ErgoBox;
5
6/// BoundedVec type for Tx inputs, output_candidates and outputs
7pub type TxIoVec<T> = BoundedVec<T, 1, { i16::MAX as usize }>;
8
9/// Interpreter's context (blockchain state)
10#[derive(Debug)]
11pub struct Context<'ctx> {
12    /// Current height
13    pub height: u32,
14    /// Box that contains the script we're evaluating (from spending transaction inputs)
15    pub self_box: &'ctx ErgoBox,
16    /// Spending transaction outputs
17    pub outputs: &'ctx [ErgoBox],
18    /// Spending transaction data inputs
19    pub data_inputs: Option<TxIoVec<&'ctx ErgoBox>>,
20    /// Spending transaction inputs
21    pub inputs: TxIoVec<&'ctx ErgoBox>,
22    /// Pre header of current block
23    pub pre_header: PreHeader,
24    /// Fixed number of last block headers in descending order (first header is the newest one)
25    pub headers: [Header; 10],
26    /// prover-defined key-value pairs, that may be used inside a script
27    pub extension: ContextExtension,
28}
29
30impl<'ctx> Context<'ctx> {
31    /// Return a new Context with given context extension
32    pub fn with_extension(self, ext: ContextExtension) -> Self {
33        Context {
34            extension: ext,
35            ..self
36        }
37    }
38}
39
40#[cfg(feature = "arbitrary")]
41#[allow(clippy::unwrap_used)]
42mod arbitrary {
43
44    use super::*;
45    use proptest::{collection::vec, option::of, prelude::*};
46
47    impl Arbitrary for Context<'static> {
48        type Parameters = ();
49
50        fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
51            (
52                0..i32::MAX as u32,
53                any::<ErgoBox>(),
54                vec(any::<ErgoBox>(), 1..3),
55                vec(any::<ErgoBox>(), 1..3),
56                of(vec(any::<ErgoBox>(), 1..3)),
57                any::<PreHeader>(),
58                any::<ContextExtension>(),
59                any::<[Header; 10]>(),
60            )
61                .prop_map(
62                    |(
63                        height,
64                        self_box,
65                        outputs,
66                        inputs,
67                        data_inputs,
68                        pre_header,
69                        extension,
70                        headers,
71                    )| {
72                        // Leak variables. Since this is only used for testing this is acceptable and avoids introducing a new type (ContextOwned)
73                        Self {
74                            height,
75                            self_box: Box::leak(Box::new(self_box)),
76                            outputs: Vec::leak(outputs),
77                            data_inputs: data_inputs.map(|v| {
78                                v.into_iter()
79                                    .map(|i| &*Box::leak(Box::new(i)))
80                                    .collect::<Vec<_>>()
81                                    .try_into()
82                                    .unwrap()
83                            }),
84                            inputs: inputs
85                                .into_iter()
86                                .map(|i| &*Box::leak(Box::new(i)))
87                                .collect::<Vec<_>>()
88                                .try_into()
89                                .unwrap(),
90                            pre_header,
91                            extension,
92                            headers,
93                        }
94                    },
95                )
96                .boxed()
97        }
98
99        type Strategy = BoxedStrategy<Self>;
100    }
101}
102
103#[cfg(test)]
104mod tests {}