freenet_stdlib/contract_interface/
encoding.rs1use std::{
3 collections::{HashMap, HashSet},
4 marker::PhantomData,
5};
6
7use serde::{de::DeserializeOwned, Serialize};
8
9use super::*;
10use crate::parameters::Parameters;
11
12pub enum MergeResult {
13 Success,
14 RequestRelated(RelatedContractsContainer),
15 Error(ContractError),
16}
17
18#[derive(Default)]
19pub struct RelatedContractsContainer {
20 contracts: HashMap<ContractInstanceId, State<'static>>,
21 pending: HashSet<ContractInstanceId>,
22 not_found: HashSet<ContractInstanceId>,
23}
24
25impl From<RelatedContracts<'static>> for RelatedContractsContainer {
26 fn from(found: RelatedContracts<'static>) -> Self {
27 let mut not_found = HashSet::new();
28 let mut contracts = HashMap::new();
29 for (id, state) in found.states() {
30 match state {
31 Some(state) => {
32 contracts.insert(*id, state.clone());
33 }
34 None => {
35 not_found.insert(*id);
36 }
37 }
38 }
39 RelatedContractsContainer {
40 contracts,
41 pending: HashSet::new(),
42 not_found,
43 }
44 }
45}
46
47impl From<RelatedContractsContainer> for Vec<crate::contract_interface::RelatedContract> {
48 fn from(related: RelatedContractsContainer) -> Self {
49 related
50 .pending
51 .into_iter()
52 .map(|id| RelatedContract {
53 contract_instance_id: id,
54 mode: RelatedMode::StateOnce,
55 })
56 .collect()
57 }
58}
59
60impl From<Vec<UpdateData<'static>>> for RelatedContractsContainer {
61 fn from(updates: Vec<UpdateData<'static>>) -> Self {
62 let mut this = RelatedContractsContainer::default();
63 for update in updates {
64 match update {
65 UpdateData::RelatedState { related_to, state } => {
66 this.contracts.insert(related_to, state);
67 }
68 UpdateData::RelatedStateAndDelta {
69 related_to, state, ..
70 } => {
71 this.contracts.insert(related_to, state);
72 }
73 _ => {}
74 }
75 }
76 this
77 }
78}
79
80impl RelatedContractsContainer {
81 pub fn get<C: TypedContract>(
82 &self,
83 params: &C::Parameters,
84 ) -> Result<Related<C>, <<C as EncodingAdapter>::SelfEncoder as Encoder<C>>::Error> {
85 let id = <C as TypedContract>::instance_id(params);
86 if let Some(res) = self.contracts.get(&id) {
87 let state = <<C as EncodingAdapter>::SelfEncoder>::deserialize(res.as_ref())?;
88 return Ok(Related::Found { state });
89 }
90 if self.pending.contains(&id) {
91 return Ok(Related::RequestPending);
92 }
93 if self.not_found.contains(&id) {
94 return Ok(Related::NotFound);
95 }
96 Ok(Related::NotRequested)
97 }
98
99 pub fn request<C: TypedContract>(&mut self, id: ContractInstanceId) {
100 self.pending.insert(id);
101 }
102
103 pub fn merge(&mut self, other: Self) {
104 let Self {
105 contracts,
106 pending,
107 not_found,
108 } = other;
109 self.pending.extend(pending);
110 self.not_found.extend(not_found);
111 self.contracts.extend(contracts);
112 }
113}
114
115pub enum Related<C: TypedContract> {
116 Found { state: C },
118 NotFound,
120 RequestPending,
122 NotRequested,
125}
126
127pub trait EncodingAdapter
130where
131 Self: Sized,
132{
133 type Parameters;
134 type Delta;
135 type Summary;
136
137 type SelfEncoder: Encoder<Self>;
138 type ParametersEncoder: Encoder<Self::Parameters>;
139 type DeltaEncoder: Encoder<Self::Delta>;
140 type SummaryEncoder: Encoder<Self::Summary>;
141}
142
143pub enum TypedUpdateData<T: EncodingAdapter> {
144 RelatedState { state: T },
145 RelatedDelta { delta: T::Delta },
146 RelatedStateAndDelta { state: T, delta: T::Delta },
147}
148
149impl<T: EncodingAdapter> TypedUpdateData<T> {
150 pub fn from_other<Parent>(value: &TypedUpdateData<Parent>) -> Self
151 where
152 Parent: EncodingAdapter,
153 T: for<'x> From<&'x Parent>,
154 T::Delta: for<'x> From<&'x Parent::Delta>,
155 {
156 match value {
157 TypedUpdateData::RelatedState { state } => {
158 let state = T::from(state);
159 TypedUpdateData::RelatedState { state }
160 }
161 TypedUpdateData::RelatedDelta { delta } => {
162 let delta: T::Delta = <T as EncodingAdapter>::Delta::from(delta);
163 TypedUpdateData::RelatedDelta { delta }
164 }
165 TypedUpdateData::RelatedStateAndDelta { state, delta } => {
166 let state = T::from(state);
167 let delta: T::Delta = <T as EncodingAdapter>::Delta::from(delta);
168 TypedUpdateData::RelatedStateAndDelta { state, delta }
169 }
170 }
171 }
172}
173
174impl<T: EncodingAdapter> TryFrom<(Option<T>, Option<T::Delta>)> for TypedUpdateData<T> {
175 type Error = ContractError;
176 fn try_from((state, delta): (Option<T>, Option<T::Delta>)) -> Result<Self, Self::Error> {
177 match (state, delta) {
178 (None, None) => Err(ContractError::InvalidState),
179 (None, Some(delta)) => Ok(Self::RelatedDelta { delta }),
180 (Some(state), None) => Ok(Self::RelatedState { state }),
181 (Some(state), Some(delta)) => Ok(Self::RelatedStateAndDelta { state, delta }),
182 }
183 }
184}
185
186pub trait TypedContract: EncodingAdapter {
187 fn instance_id(params: &Self::Parameters) -> ContractInstanceId;
188
189 fn verify(
190 &self,
191 parameters: Self::Parameters,
192 related: RelatedContractsContainer,
193 ) -> Result<ValidateResult, ContractError>;
194
195 fn merge(
196 &mut self,
197 parameters: &Self::Parameters,
198 update: TypedUpdateData<Self>,
199 related: &RelatedContractsContainer,
200 ) -> MergeResult;
201
202 fn summarize(&self, parameters: Self::Parameters) -> Result<Self::Summary, ContractError>;
203
204 fn delta(
205 &self,
206 parameters: Self::Parameters,
207 summary: Self::Summary,
208 ) -> Result<Self::Delta, ContractError>;
209}
210
211pub trait Encoder<T> {
212 type Error: Into<ContractError>;
213 fn deserialize(bytes: &[u8]) -> Result<T, Self::Error>;
214 fn serialize(value: &T) -> Result<Vec<u8>, Self::Error>;
215}
216
217pub struct JsonEncoder<T>(PhantomData<T>);
218
219impl<T> Encoder<T> for JsonEncoder<T>
220where
221 T: DeserializeOwned + Serialize,
222{
223 type Error = serde_json::Error;
224
225 fn deserialize(bytes: &[u8]) -> Result<T, Self::Error> {
226 serde_json::from_slice(bytes)
227 }
228
229 fn serialize(value: &T) -> Result<Vec<u8>, Self::Error> {
230 serde_json::to_vec(value)
231 }
232}
233
234impl From<serde_json::Error> for ContractError {
235 fn from(value: serde_json::Error) -> Self {
236 ContractError::Deser(format!("{value}"))
237 }
238}
239
240pub struct BincodeEncoder<T>(PhantomData<T>);
241
242impl<T> Encoder<T> for BincodeEncoder<T>
243where
244 T: DeserializeOwned + Serialize,
245{
246 type Error = bincode::Error;
247
248 fn deserialize(bytes: &[u8]) -> Result<T, Self::Error> {
249 bincode::deserialize(bytes)
250 }
251
252 fn serialize(value: &T) -> Result<Vec<u8>, Self::Error> {
253 bincode::serialize(value)
254 }
255}
256
257impl From<bincode::Error> for ContractError {
258 fn from(value: bincode::Error) -> Self {
259 ContractError::Deser(format!("{value}"))
260 }
261}
262
263pub fn inner_validate_state<T>(
264 parameters: Parameters<'static>,
265 state: State<'static>,
266 related: RelatedContracts<'static>,
267) -> Result<ValidateResult, ContractError>
268where
269 T: EncodingAdapter + TypedContract,
270 ContractError: From<
271 <<T as EncodingAdapter>::ParametersEncoder as Encoder<
272 <T as EncodingAdapter>::Parameters,
273 >>::Error,
274 >,
275 ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
276{
277 let typed_params =
278 <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
279 let typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
280 let related_container = RelatedContractsContainer::from(related);
281 typed_state.verify(typed_params, related_container)
282}
283
284pub fn inner_update_state<T>(
285 parameters: Parameters<'static>,
286 state: State<'static>,
287 data: Vec<UpdateData<'static>>,
288) -> Result<UpdateModification<'static>, ContractError>
289where
290 T: EncodingAdapter + TypedContract,
291 ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
292 ContractError: From<
293 <<T as EncodingAdapter>::ParametersEncoder as Encoder<
294 <T as EncodingAdapter>::Parameters,
295 >>::Error,
296 >,
297 ContractError: From<
298 <<T as EncodingAdapter>::DeltaEncoder as Encoder<<T as EncodingAdapter>::Delta>>::Error,
299 >,
300{
301 let typed_params =
302 <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
303 let mut typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
304 let self_updates = UpdateData::get_self_states(&data);
305 let related_container = RelatedContractsContainer::from(data);
306 for (state, delta) in self_updates {
307 let state = state
308 .map(|s| <<T as EncodingAdapter>::SelfEncoder>::deserialize(s.as_ref()))
309 .transpose()?;
310 let delta = delta
311 .map(|d| <<T as EncodingAdapter>::DeltaEncoder>::deserialize(d.as_ref()))
312 .transpose()?;
313 let typed_update = TypedUpdateData::try_from((state, delta))?;
314 match typed_state.merge(&typed_params, typed_update, &related_container) {
315 MergeResult::Success => {}
316 MergeResult::RequestRelated(req) => {
317 return UpdateModification::requires(req.into());
318 }
319 MergeResult::Error(err) => return Err(err),
320 }
321 }
322 let encoded = <<T as EncodingAdapter>::SelfEncoder>::serialize(&typed_state)?;
323 Ok(UpdateModification::valid(encoded.into()))
324}
325
326pub fn inner_summarize_state<T>(
327 parameters: Parameters<'static>,
328 state: State<'static>,
329) -> Result<StateSummary<'static>, ContractError>
330where
331 T: EncodingAdapter + TypedContract,
332 ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
333 ContractError: From<
334 <<T as EncodingAdapter>::ParametersEncoder as Encoder<
335 <T as EncodingAdapter>::Parameters,
336 >>::Error,
337 >,
338 ContractError: From<
339 <<T as EncodingAdapter>::SummaryEncoder as Encoder<<T as EncodingAdapter>::Summary>>::Error,
340 >,
341{
342 let typed_params =
343 <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
344 let typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
345 let summary = typed_state.summarize(typed_params)?;
346 let encoded = <<T as EncodingAdapter>::SummaryEncoder>::serialize(&summary)?;
347 Ok(encoded.into())
348}
349
350pub fn inner_state_delta<T>(
351 parameters: Parameters<'static>,
352 state: State<'static>,
353 summary: StateSummary<'static>,
354) -> Result<StateDelta<'static>, ContractError>
355where
356 T: EncodingAdapter + TypedContract,
357 ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
358 ContractError: From<
359 <<T as EncodingAdapter>::ParametersEncoder as Encoder<
360 <T as EncodingAdapter>::Parameters,
361 >>::Error,
362 >,
363 ContractError: From<
364 <<T as EncodingAdapter>::SummaryEncoder as Encoder<<T as EncodingAdapter>::Summary>>::Error,
365 >,
366 ContractError: From<
367 <<T as EncodingAdapter>::DeltaEncoder as Encoder<<T as EncodingAdapter>::Delta>>::Error,
368 >,
369{
370 let typed_params =
371 <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
372 let typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
373 let typed_summary = <<T as EncodingAdapter>::SummaryEncoder>::deserialize(summary.as_ref())?;
374 let summary = typed_state.delta(typed_params, typed_summary)?;
375 let encoded = <<T as EncodingAdapter>::DeltaEncoder>::serialize(&summary)?;
376 Ok(encoded.into())
377}