essential_types/
solution.rs

1//! # Solutions
2//! Data types that are used to create solutions to predicates.
3
4use serde::{Deserialize, Serialize};
5
6use crate::{Key, PredicateAddress, Value, Word};
7
8pub mod decode;
9pub mod encode;
10
11#[cfg(feature = "schema")]
12use schemars::JsonSchema;
13
14/// An index into a [`SolutionSet`]'s `solutions` slice.
15///
16/// Note that this type is purely provided as a utility. Implementations should not depend on the
17/// order of `Solution`s within a `SolutionSet` as it must be possible for `SolutionSet`s to be
18/// merged.
19pub type SolutionIndex = u16;
20
21#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
22#[cfg_attr(feature = "schema", derive(JsonSchema))]
23/// A set of [`Solution`]s.
24///
25/// A `SolutionSet`'s `ContentAddress` is the same regardless of the ordering of its solutions.
26///
27/// `SolutionSet`s may be safely merged with one another in the case that there are no [`Key`]
28/// conflicts in the proposed [`state_mutations`][Solution::state_mutations] and/or post-state
29/// reads within the [`predicate_to_solve`][Solution::predicate_to_solve].
30pub struct SolutionSet {
31    /// The input data for each predicate.
32    // Support deserializing the old `data` name.
33    #[serde(alias = "data")]
34    pub solutions: Vec<Solution>,
35}
36
37#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
38#[cfg_attr(feature = "schema", derive(JsonSchema))]
39/// A solution for a single contract predicate.
40pub struct Solution {
41    /// The predicate that the solution attempts to solve.
42    pub predicate_to_solve: PredicateAddress,
43    /// The input data required by the predicate.
44    // Support deserializing the old `decision_variables` name.
45    #[serde(alias = "decision_variables")]
46    pub predicate_data: Vec<Value>,
47    /// The state mutations proposed by the solution.
48    pub state_mutations: Vec<Mutation>,
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
52#[cfg_attr(feature = "schema", derive(JsonSchema))]
53/// A mutation to a single [`Key`] in state.
54pub struct Mutation {
55    /// Key to data.
56    pub key: Key,
57    /// The new value.
58    ///
59    /// Empty value means the value is being deleted.
60    pub value: Value,
61}
62
63impl SolutionSet {
64    /// Get the sum of all state mutations within the set of solutions.
65    pub fn state_mutations_len(&self) -> usize {
66        self.solutions.iter().map(|d| d.state_mutations.len()).sum()
67    }
68}
69
70impl Mutation {
71    /// Get the size in words of this mutation encoded.
72    pub fn encode_size(&self) -> usize {
73        encode::encode_mutation_size(self)
74    }
75
76    /// Encodes a mutation into a sequence of words.
77    ///
78    /// # Layout
79    /// ```text
80    /// +-----------------+-----------------+
81    /// | key length      | key             |
82    /// +-----------------+-----------------+
83    /// | value length    | value           |
84    /// +-----------------+-----------------+
85    /// ```
86    pub fn encode(&self) -> impl Iterator<Item = Word> + use<'_> {
87        encode::encode_mutation(self)
88    }
89
90    /// Decode a mutation from words.
91    ///
92    /// # Layout
93    /// ```text
94    /// +-----------------+-----------------+
95    /// | key length      | key             |
96    /// +-----------------+-----------------+
97    /// | value length    | value           |
98    /// +-----------------+-----------------+
99    /// ```
100    pub fn decode_mutation(bytes: &[Word]) -> Result<Self, decode::MutationDecodeError> {
101        decode::decode_mutation(bytes)
102    }
103}