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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
#![deny(missing_docs)]
//! # Types for interacting with the Essential Server.
use std::collections::BTreeMap;
use essential_types::{
contract::Contract,
predicate::Predicate,
solution::{Solution, SolutionData, SolutionDataIndex},
ContentAddress, Key, PredicateAddress, StateReadBytecode, Value,
};
const ZEROED_PREDICATE: PredicateAddress = PredicateAddress {
contract: ContentAddress([0; 32]),
predicate: ContentAddress([0; 32]),
};
pub mod ser;
/// Utility and gas used as a result of checking a solution's state transitions.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
pub struct CheckSolutionOutput {
/// The utility of the solution.
pub utility: f64,
/// The gas used by the solution.
pub gas: u64,
}
/// The outcome of a solution, that is:
/// - Utility if the solution was included in a block.
/// - Failure reason if solution failed constraint checking or was not composable with other solutions.
/// This may be a stringified `SolutionFailReason`.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
pub enum SolutionOutcome {
/// The solution was successful and included in a block.
Success(u64),
/// The solution failed and was not included in a block.
Fail(String),
}
/// Solution with contract read from storage that will be used for checking.
#[derive(serde::Serialize, serde::Deserialize)]
pub struct CheckSolution {
/// The solution to check.
pub solution: Solution,
/// The contracts this solution depends on.
pub contracts: Vec<Contract>,
}
/// Query the results of running an ordered list of state read programs.
///
/// The query can be derived from a solution, or be inline.
/// The request type can be for just the keys and values read, or for the slots read
/// or both.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
pub struct QueryStateReads {
/// The programs that read state.
#[serde(
serialize_with = "essential_types::serde::bytecode::serialize_vec",
deserialize_with = "essential_types::serde::bytecode::deserialize_vec"
)]
pub state_read: Vec<StateReadBytecode>,
/// The index of the solution data that is used for the state query,
pub index: SolutionDataIndex,
/// The solution for this query.
pub solution: Solution,
/// The type of results for this request.
pub request_type: StateReadRequestType,
}
/// The type of results for this request.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
pub enum StateReadRequestType {
/// Request the keys and values that are read with the state slots.
All(SlotsRequest),
/// Request only the slots that are read into.
Slots(SlotsRequest),
/// Request only the keys and values that are read.
Reads,
}
/// The slots that are returned for the state read request.
#[derive(Default, Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
pub enum SlotsRequest {
/// Return both the pre and post state slots.
#[default]
All,
/// Return only the pre state slots.
Pre,
/// Return only the post state slots.
Post,
}
/// The output of a state read query.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
pub enum QueryStateReadsOutput {
#[serde(
serialize_with = "ser::serialize_map",
deserialize_with = "ser::deserialize_map"
)]
/// The keys and values that were read.
Reads(BTreeMap<ContentAddress, BTreeMap<Key, Value>>),
/// The slots that were read into.
Slots(Slots),
/// The keys and values that were read and the slots that were read into.
All(
#[serde(
serialize_with = "ser::serialize_map",
deserialize_with = "ser::deserialize_map"
)]
BTreeMap<ContentAddress, BTreeMap<Key, Value>>,
Slots,
),
/// The state reads failed.
Failure(String),
}
/// Pre and post state slots.
#[derive(Default, Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)]
pub struct Slots {
/// The pre state slots.
pub pre: Vec<Value>,
/// The post state slots. Read after the mutations are applied.
pub post: Vec<Value>,
}
impl QueryStateReads {
/// Create a query from a solution and a predicate.
///
/// It is assumed the provided predicate is the predicate that the solution data
/// at the provided index is solving. This is not checked.
pub fn from_solution(
mut solution: Solution,
index: SolutionDataIndex,
predicate: &Predicate,
request_type: StateReadRequestType,
) -> Self {
for (i, d) in solution.data.iter_mut().enumerate() {
if i as SolutionDataIndex == index {
continue;
}
d.decision_variables = Default::default();
}
Self {
state_read: predicate.state_read.clone(),
index,
solution,
request_type,
}
}
/// Create a query that only reads external state.
/// The predicate address is zeroed out.
pub fn inline_empty(
state_read: Vec<StateReadBytecode>,
request_type: StateReadRequestType,
) -> Self {
let data = SolutionData {
predicate_to_solve: ZEROED_PREDICATE,
decision_variables: Default::default(),
transient_data: Default::default(),
state_mutations: Default::default(),
};
Self::inline(state_read, data, request_type)
}
/// Create an inline query from state reads and a single solution data.
pub fn inline(
state_read: Vec<StateReadBytecode>,
data: SolutionData,
request_type: StateReadRequestType,
) -> Self {
Self {
state_read,
index: 0,
solution: Solution { data: vec![data] },
request_type,
}
}
}
impl Default for StateReadRequestType {
fn default() -> Self {
Self::All(SlotsRequest::default())
}
}