essential_server_types/
lib.rs

1#![deny(missing_docs)]
2
3//! # Types for interacting with the Essential Server.
4
5use std::collections::BTreeMap;
6
7use essential_types::{
8    contract::Contract,
9    predicate::Predicate,
10    solution::{Solution, SolutionData, SolutionDataIndex},
11    ContentAddress, Key, PredicateAddress, StateReadBytecode, Value,
12};
13
14const ZEROED_PREDICATE: PredicateAddress = PredicateAddress {
15    contract: ContentAddress([0; 32]),
16    predicate: ContentAddress([0; 32]),
17};
18
19pub mod ser;
20
21/// Utility and gas used as a result of checking a solution's state transitions.
22#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
23pub struct CheckSolutionOutput {
24    /// The utility of the solution.
25    pub utility: f64,
26    /// The gas used by the solution.
27    pub gas: u64,
28}
29
30/// The outcome of a solution, that is:
31/// - Utility if the solution was included in a block.
32/// - Failure reason if solution failed constraint checking or was not composable with other solutions.
33/// This may be a stringified `SolutionFailReason`.
34#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
35pub enum SolutionOutcome {
36    /// The solution was successful and included in a block.
37    Success(u64),
38    /// The solution failed and was not included in a block.
39    Fail(String),
40}
41
42/// Solution with contract read from storage that will be used for checking.
43#[derive(serde::Serialize, serde::Deserialize)]
44pub struct CheckSolution {
45    /// The solution to check.
46    pub solution: Solution,
47    /// The contracts this solution depends on.
48    pub contracts: Vec<Contract>,
49}
50
51/// Query the results of running an ordered list of state read programs.
52///
53/// The query can be derived from a solution, or be inline.
54/// The request type can be for just the keys and values read, or for the slots read
55/// or both.
56#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
57pub struct QueryStateReads {
58    /// The programs that read state.
59    #[serde(
60        serialize_with = "essential_types::serde::bytecode::serialize_vec",
61        deserialize_with = "essential_types::serde::bytecode::deserialize_vec"
62    )]
63    pub state_read: Vec<StateReadBytecode>,
64    /// The index of the solution data that is used for the state query,
65    pub index: SolutionDataIndex,
66    /// The solution for this query.
67    pub solution: Solution,
68    /// The type of results for this request.
69    pub request_type: StateReadRequestType,
70}
71
72/// The type of results for this request.
73#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
74pub enum StateReadRequestType {
75    /// Request the keys and values that are read with the state slots.
76    All(SlotsRequest),
77    /// Request only the slots that are read into.
78    Slots(SlotsRequest),
79    /// Request only the keys and values that are read.
80    Reads,
81}
82
83/// The slots that are returned for the state read request.
84#[derive(Default, Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
85pub enum SlotsRequest {
86    /// Return both the pre and post state slots.
87    #[default]
88    All,
89    /// Return only the pre state slots.
90    Pre,
91    /// Return only the post state slots.
92    Post,
93}
94
95/// The output of a state read query.
96#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
97pub enum QueryStateReadsOutput {
98    #[serde(
99        serialize_with = "ser::serialize_map",
100        deserialize_with = "ser::deserialize_map"
101    )]
102    /// The keys and values that were read.
103    Reads(BTreeMap<ContentAddress, BTreeMap<Key, Value>>),
104    /// The slots that were read into.
105    Slots(Slots),
106    /// The keys and values that were read and the slots that were read into.
107    All(
108        #[serde(
109            serialize_with = "ser::serialize_map",
110            deserialize_with = "ser::deserialize_map"
111        )]
112        BTreeMap<ContentAddress, BTreeMap<Key, Value>>,
113        Slots,
114    ),
115    /// The state reads failed.
116    Failure(String),
117}
118
119/// Pre and post state slots.
120#[derive(Default, Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
121pub struct Slots {
122    /// The pre state slots.
123    pub pre: Vec<Value>,
124    /// The post state slots. Read after the mutations are applied.
125    pub post: Vec<Value>,
126}
127
128impl QueryStateReads {
129    /// Create a query from a solution and a predicate.
130    ///
131    /// It is assumed the provided predicate is the predicate that the solution data
132    /// at the provided index is solving. This is not checked.
133    pub fn from_solution(
134        mut solution: Solution,
135        index: SolutionDataIndex,
136        predicate: &Predicate,
137        request_type: StateReadRequestType,
138    ) -> Self {
139        for (i, d) in solution.data.iter_mut().enumerate() {
140            if i as SolutionDataIndex == index {
141                continue;
142            }
143            d.decision_variables = Default::default();
144        }
145        Self {
146            state_read: predicate.state_read.clone(),
147            index,
148            solution,
149            request_type,
150        }
151    }
152
153    /// Create a query that only reads external state.
154    /// The predicate address is zeroed out.
155    pub fn inline_empty(
156        state_read: Vec<StateReadBytecode>,
157        request_type: StateReadRequestType,
158    ) -> Self {
159        let data = SolutionData {
160            predicate_to_solve: ZEROED_PREDICATE,
161            decision_variables: Default::default(),
162            transient_data: Default::default(),
163            state_mutations: Default::default(),
164        };
165
166        Self::inline(state_read, data, request_type)
167    }
168
169    /// Create an inline query from state reads and a single solution data.
170    pub fn inline(
171        state_read: Vec<StateReadBytecode>,
172        data: SolutionData,
173        request_type: StateReadRequestType,
174    ) -> Self {
175        Self {
176            state_read,
177            index: 0,
178            solution: Solution { data: vec![data] },
179            request_type,
180        }
181    }
182}
183
184impl Default for StateReadRequestType {
185    fn default() -> Self {
186        Self::All(SlotsRequest::default())
187    }
188}