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 {}