freenet_stdlib/
contract_interface.rs

1//! Interface and related utilities for interaction with the compiled WASM contracts.
2//! Contracts have an isomorphic interface which partially maps to this interface,
3//! allowing interaction between the runtime and the contracts themselves.
4//!
5//! This abstraction layer shouldn't leak beyond the contract handler.
6
7use std::{
8    borrow::{Borrow, Cow},
9    collections::HashMap,
10    fmt::Display,
11    fs::File,
12    hash::{Hash, Hasher},
13    io::{Cursor, Read},
14    ops::{Deref, DerefMut},
15    path::Path,
16    str::FromStr,
17    sync::Arc,
18};
19
20use blake3::{traits::digest::Digest, Hasher as Blake3};
21use byteorder::{LittleEndian, ReadBytesExt};
22use serde::{Deserialize, Deserializer, Serialize};
23use serde_with::serde_as;
24
25use crate::client_api::TryFromFbs;
26use crate::common_generated::common::{
27    ContractKey as FbsContractKey, UpdateData as FbsUpdateData, UpdateDataType,
28};
29use crate::generated::client_request::RelatedContracts as FbsRelatedContracts;
30use crate::{client_api::WsApiError, code_hash::CodeHash, parameters::Parameters};
31
32pub(crate) const CONTRACT_KEY_SIZE: usize = 32;
33
34/// Type of errors during interaction with a contract.
35#[derive(Debug, thiserror::Error, Serialize, Deserialize)]
36pub enum ContractError {
37    #[error("de/serialization error: {0}")]
38    Deser(String),
39    #[error("invalid contract update")]
40    InvalidUpdate,
41    #[error("invalid contract update, reason: {reason}")]
42    InvalidUpdateWithInfo { reason: String },
43    #[error("trying to read an invalid state")]
44    InvalidState,
45    #[error("trying to read an invalid delta")]
46    InvalidDelta,
47    #[error("{0}")]
48    Other(String),
49}
50
51/// An update to a contract state or any required related contracts to update that state.
52// todo: this should be an enum probably
53#[non_exhaustive]
54#[derive(Debug, Serialize, Deserialize)]
55pub struct UpdateModification<'a> {
56    #[serde(borrow)]
57    pub new_state: Option<State<'a>>,
58    /// Request an other contract so updates can be resolved.
59    pub related: Vec<RelatedContract>,
60}
61
62impl<'a> UpdateModification<'a> {
63    /// Constructor for self when the state is valid.
64    pub fn valid(new_state: State<'a>) -> Self {
65        Self {
66            new_state: Some(new_state),
67            related: vec![],
68        }
69    }
70
71    /// Unwraps self returning a [`State`].
72    ///
73    /// Panics if self does not contain a state.
74    pub fn unwrap_valid(self) -> State<'a> {
75        match self.new_state {
76            Some(s) => s,
77            _ => panic!("failed unwrapping state in modification"),
78        }
79    }
80}
81
82impl UpdateModification<'_> {
83    /// Constructor for self when this contract still is missing some [`RelatedContract`]
84    /// to proceed with any verification or updates.
85    pub fn requires(related: Vec<RelatedContract>) -> Result<Self, ContractError> {
86        if related.is_empty() {
87            return Err(ContractError::InvalidUpdateWithInfo {
88                reason: "At least one related contract is required".into(),
89            });
90        }
91        Ok(Self {
92            new_state: None,
93            related,
94        })
95    }
96
97    /// Gets the pending related contracts.
98    pub fn get_related(&self) -> &[RelatedContract] {
99        &self.related
100    }
101
102    /// Copies the data if not owned and returns an owned version of self.
103    pub fn into_owned(self) -> UpdateModification<'static> {
104        let Self { new_state, related } = self;
105        UpdateModification {
106            new_state: new_state.map(State::into_owned),
107            related,
108        }
109    }
110
111    pub fn requires_dependencies(&self) -> bool {
112        !self.related.is_empty()
113    }
114}
115
116/// The contracts related to a parent or root contract. Tipically this means
117/// contracts which state requires to be verified or integrated in some way with
118/// the parent contract.
119#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Default)]
120pub struct RelatedContracts<'a> {
121    #[serde(borrow)]
122    map: HashMap<ContractInstanceId, Option<State<'a>>>,
123}
124
125impl RelatedContracts<'_> {
126    pub fn new() -> Self {
127        Self {
128            map: HashMap::new(),
129        }
130    }
131
132    /// Copies the data if not owned and returns an owned version of self.
133    pub fn into_owned(self) -> RelatedContracts<'static> {
134        let mut map = HashMap::with_capacity(self.map.len());
135        for (k, v) in self.map {
136            map.insert(k, v.map(|s| s.into_owned()));
137        }
138        RelatedContracts { map }
139    }
140
141    pub fn deser_related_contracts<'de, D>(deser: D) -> Result<RelatedContracts<'static>, D::Error>
142    where
143        D: serde::Deserializer<'de>,
144    {
145        let value = <RelatedContracts as Deserialize>::deserialize(deser)?;
146        Ok(value.into_owned())
147    }
148}
149
150impl RelatedContracts<'static> {
151    pub fn states(&self) -> impl Iterator<Item = (&ContractInstanceId, &Option<State<'static>>)> {
152        self.map.iter()
153    }
154}
155
156impl<'a> RelatedContracts<'a> {
157    pub fn update(
158        &mut self,
159    ) -> impl Iterator<Item = (&ContractInstanceId, &mut Option<State<'a>>)> + '_ {
160        self.map.iter_mut()
161    }
162
163    pub fn missing(&mut self, contracts: Vec<ContractInstanceId>) {
164        for key in contracts {
165            self.map.entry(key).or_default();
166        }
167    }
168}
169
170impl<'a> TryFromFbs<&FbsRelatedContracts<'a>> for RelatedContracts<'a> {
171    fn try_decode_fbs(related_contracts: &FbsRelatedContracts<'a>) -> Result<Self, WsApiError> {
172        let mut map = HashMap::with_capacity(related_contracts.contracts().len());
173        for related in related_contracts.contracts().iter() {
174            let id = ContractInstanceId::from_bytes(related.instance_id().data().bytes()).unwrap();
175            let state = State::from(related.state().bytes());
176            map.insert(id, Some(state));
177        }
178        Ok(RelatedContracts::from(map))
179    }
180}
181
182impl<'a> From<HashMap<ContractInstanceId, Option<State<'a>>>> for RelatedContracts<'a> {
183    fn from(related_contracts: HashMap<ContractInstanceId, Option<State<'a>>>) -> Self {
184        Self {
185            map: related_contracts,
186        }
187    }
188}
189
190/// A contract related to an other contract and the specification
191/// of the kind of update notifications that should be received by this contract.
192#[derive(Debug, Serialize, Deserialize)]
193pub struct RelatedContract {
194    pub contract_instance_id: ContractInstanceId,
195    pub mode: RelatedMode,
196    // todo: add a timeout so we stop listening/subscribing eventually
197}
198
199/// Specification of the notifications of interest from a related contract.
200#[derive(Debug, Serialize, Deserialize)]
201pub enum RelatedMode {
202    /// Retrieve the state once, don't be concerned with subsequent changes.
203    StateOnce,
204    /// Retrieve the state once, and then subscribe to updates.
205    StateThenSubscribe,
206}
207
208/// The result of calling the [`ContractInterface::validate_state`] function.
209#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
210pub enum ValidateResult {
211    Valid,
212    Invalid,
213    /// The peer will attempt to retrieve the requested contract states
214    /// and will call validate_state() again when it retrieves them.
215    RequestRelated(Vec<ContractInstanceId>),
216}
217
218/// Update notifications for a contract or a related contract.
219#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
220pub enum UpdateData<'a> {
221    State(#[serde(borrow)] State<'a>),
222    Delta(#[serde(borrow)] StateDelta<'a>),
223    StateAndDelta {
224        #[serde(borrow)]
225        state: State<'a>,
226        #[serde(borrow)]
227        delta: StateDelta<'a>,
228    },
229    RelatedState {
230        related_to: ContractInstanceId,
231        #[serde(borrow)]
232        state: State<'a>,
233    },
234    RelatedDelta {
235        related_to: ContractInstanceId,
236        #[serde(borrow)]
237        delta: StateDelta<'a>,
238    },
239    RelatedStateAndDelta {
240        related_to: ContractInstanceId,
241        #[serde(borrow)]
242        state: State<'a>,
243        #[serde(borrow)]
244        delta: StateDelta<'a>,
245    },
246}
247
248impl UpdateData<'_> {
249    pub fn size(&self) -> usize {
250        match self {
251            UpdateData::State(state) => state.size(),
252            UpdateData::Delta(delta) => delta.size(),
253            UpdateData::StateAndDelta { state, delta } => state.size() + delta.size(),
254            UpdateData::RelatedState { state, .. } => state.size() + CONTRACT_KEY_SIZE,
255            UpdateData::RelatedDelta { delta, .. } => delta.size() + CONTRACT_KEY_SIZE,
256            UpdateData::RelatedStateAndDelta { state, delta, .. } => {
257                state.size() + delta.size() + CONTRACT_KEY_SIZE
258            }
259        }
260    }
261
262    pub fn unwrap_delta(&self) -> &StateDelta<'_> {
263        match self {
264            UpdateData::Delta(delta) => delta,
265            _ => panic!(),
266        }
267    }
268
269    /// Copies the data if not owned and returns an owned version of self.
270    pub fn into_owned(self) -> UpdateData<'static> {
271        match self {
272            UpdateData::State(s) => UpdateData::State(State::from(s.into_bytes())),
273            UpdateData::Delta(d) => UpdateData::Delta(StateDelta::from(d.into_bytes())),
274            UpdateData::StateAndDelta { state, delta } => UpdateData::StateAndDelta {
275                delta: StateDelta::from(delta.into_bytes()),
276                state: State::from(state.into_bytes()),
277            },
278            UpdateData::RelatedState { related_to, state } => UpdateData::RelatedState {
279                related_to,
280                state: State::from(state.into_bytes()),
281            },
282            UpdateData::RelatedDelta { related_to, delta } => UpdateData::RelatedDelta {
283                related_to,
284                delta: StateDelta::from(delta.into_bytes()),
285            },
286            UpdateData::RelatedStateAndDelta {
287                related_to,
288                state,
289                delta,
290            } => UpdateData::RelatedStateAndDelta {
291                related_to,
292                state: State::from(state.into_bytes()),
293                delta: StateDelta::from(delta.into_bytes()),
294            },
295        }
296    }
297
298    pub(crate) fn get_self_states<'a>(
299        updates: &[UpdateData<'a>],
300    ) -> Vec<(Option<State<'a>>, Option<StateDelta<'a>>)> {
301        let mut own_states = Vec::with_capacity(updates.len());
302        for update in updates {
303            match update {
304                UpdateData::State(state) => own_states.push((Some(state.clone()), None)),
305                UpdateData::Delta(delta) => own_states.push((None, Some(delta.clone()))),
306                UpdateData::StateAndDelta { state, delta } => {
307                    own_states.push((Some(state.clone()), Some(delta.clone())))
308                }
309                _ => {}
310            }
311        }
312        own_states
313    }
314
315    pub(crate) fn deser_update_data<'de, D>(deser: D) -> Result<UpdateData<'static>, D::Error>
316    where
317        D: serde::Deserializer<'de>,
318    {
319        let value = <UpdateData as Deserialize>::deserialize(deser)?;
320        Ok(value.into_owned())
321    }
322}
323
324impl<'a> From<StateDelta<'a>> for UpdateData<'a> {
325    fn from(delta: StateDelta<'a>) -> Self {
326        UpdateData::Delta(delta)
327    }
328}
329
330impl<'a> TryFromFbs<&FbsUpdateData<'a>> for UpdateData<'a> {
331    fn try_decode_fbs(update_data: &FbsUpdateData<'a>) -> Result<Self, WsApiError> {
332        match update_data.update_data_type() {
333            UpdateDataType::StateUpdate => {
334                let update = update_data.update_data_as_state_update().unwrap();
335                let state = State::from(update.state().bytes());
336                Ok(UpdateData::State(state))
337            }
338            UpdateDataType::DeltaUpdate => {
339                let update = update_data.update_data_as_delta_update().unwrap();
340                let delta = StateDelta::from(update.delta().bytes());
341                Ok(UpdateData::Delta(delta))
342            }
343            UpdateDataType::StateAndDeltaUpdate => {
344                let update = update_data.update_data_as_state_and_delta_update().unwrap();
345                let state = State::from(update.state().bytes());
346                let delta = StateDelta::from(update.delta().bytes());
347                Ok(UpdateData::StateAndDelta { state, delta })
348            }
349            UpdateDataType::RelatedStateUpdate => {
350                let update = update_data.update_data_as_related_state_update().unwrap();
351                let state = State::from(update.state().bytes());
352                let related_to =
353                    ContractInstanceId::from_bytes(update.related_to().data().bytes()).unwrap();
354                Ok(UpdateData::RelatedState { related_to, state })
355            }
356            UpdateDataType::RelatedDeltaUpdate => {
357                let update = update_data.update_data_as_related_delta_update().unwrap();
358                let delta = StateDelta::from(update.delta().bytes());
359                let related_to =
360                    ContractInstanceId::from_bytes(update.related_to().data().bytes()).unwrap();
361                Ok(UpdateData::RelatedDelta { related_to, delta })
362            }
363            UpdateDataType::RelatedStateAndDeltaUpdate => {
364                let update = update_data
365                    .update_data_as_related_state_and_delta_update()
366                    .unwrap();
367                let state = State::from(update.state().bytes());
368                let delta = StateDelta::from(update.delta().bytes());
369                let related_to =
370                    ContractInstanceId::from_bytes(update.related_to().data().bytes()).unwrap();
371                Ok(UpdateData::RelatedStateAndDelta {
372                    related_to,
373                    state,
374                    delta,
375                })
376            }
377            _ => unreachable!(),
378        }
379    }
380}
381
382/// Trait to implement for the contract building.
383///
384/// Contains all necessary methods to interact with the contract.
385///
386/// # Examples
387///
388/// Implementing `ContractInterface` on a type:
389///
390/// ```
391/// # use freenet_stdlib::prelude::*;
392/// struct Contract;
393///
394/// #[contract]
395/// impl ContractInterface for Contract {
396///     fn validate_state(
397///         _parameters: Parameters<'static>,
398///         _state: State<'static>,
399///         _related: RelatedContracts
400///     ) -> Result<ValidateResult, ContractError> {
401///         Ok(ValidateResult::Valid)
402///     }
403///
404///     fn update_state(
405///         _parameters: Parameters<'static>,
406///         state: State<'static>,
407///         _data: Vec<UpdateData>,
408///     ) -> Result<UpdateModification<'static>, ContractError> {
409///         Ok(UpdateModification::valid(state))
410///     }
411///
412///     fn summarize_state(
413///         _parameters: Parameters<'static>,
414///         _state: State<'static>,
415///     ) -> Result<StateSummary<'static>, ContractError> {
416///         Ok(StateSummary::from(vec![]))
417///     }
418///
419///     fn get_state_delta(
420///         _parameters: Parameters<'static>,
421///         _state: State<'static>,
422///         _summary: StateSummary<'static>,
423///     ) -> Result<StateDelta<'static>, ContractError> {
424///         Ok(StateDelta::from(vec![]))
425///     }
426/// }
427/// ```
428// ANCHOR: contractifce
429/// # ContractInterface
430///
431/// This trait defines the core functionality for managing and updating a contract's state.
432/// Implementations must ensure that state delta updates are *commutative*. In other words,
433/// when applying multiple delta updates to a state, the order in which these updates are
434/// applied should not affect the final state. Once all deltas are applied, the resulting
435/// state should be the same, regardless of the order in which the deltas were applied.
436///
437/// Noncompliant behavior, such as failing to obey the commutativity rule, may result
438/// in the contract being deprioritized or removed from the p2p network.
439pub trait ContractInterface {
440    /// Verify that the state is valid, given the parameters.
441    fn validate_state(
442        parameters: Parameters<'static>,
443        state: State<'static>,
444        related: RelatedContracts<'static>,
445    ) -> Result<ValidateResult, ContractError>;
446
447    /// Update the state to account for the new data
448    fn update_state(
449        parameters: Parameters<'static>,
450        state: State<'static>,
451        data: Vec<UpdateData<'static>>,
452    ) -> Result<UpdateModification<'static>, ContractError>;
453
454    /// Generate a concise summary of a state that can be used to create deltas
455    /// relative to this state.
456    fn summarize_state(
457        parameters: Parameters<'static>,
458        state: State<'static>,
459    ) -> Result<StateSummary<'static>, ContractError>;
460
461    /// Generate a state delta using a summary from the current state.
462    /// This along with [`Self::summarize_state`] allows flexible and efficient
463    /// state synchronization between peers.
464    fn get_state_delta(
465        parameters: Parameters<'static>,
466        state: State<'static>,
467        summary: StateSummary<'static>,
468    ) -> Result<StateDelta<'static>, ContractError>;
469}
470// ANCHOR_END: contractifce
471
472/// A complete contract specification requires a `parameters` section
473/// and a `contract` section.
474#[derive(Debug, Serialize, Deserialize, Clone)]
475#[cfg_attr(
476    any(feature = "testing", all(test, any(unix, windows))),
477    derive(arbitrary::Arbitrary)
478)]
479pub struct Contract<'a> {
480    #[serde(borrow)]
481    pub parameters: Parameters<'a>,
482    #[serde(borrow)]
483    pub data: ContractCode<'a>,
484    // todo: skip serializing and instead compute it
485    key: ContractKey,
486}
487
488impl<'a> Contract<'a> {
489    /// Returns a contract from [contract code](ContractCode) and given [parameters](Parameters).
490    pub fn new(contract: ContractCode<'a>, parameters: Parameters<'a>) -> Contract<'a> {
491        let key = ContractKey::from_params_and_code(&parameters, &contract);
492        Contract {
493            parameters,
494            data: contract,
495            key,
496        }
497    }
498
499    /// Key portion of the specification.
500    pub fn key(&self) -> &ContractKey {
501        &self.key
502    }
503
504    /// Code portion of the specification.
505    pub fn into_code(self) -> ContractCode<'a> {
506        self.data
507    }
508}
509
510impl TryFrom<Vec<u8>> for Contract<'static> {
511    type Error = std::io::Error;
512
513    fn try_from(data: Vec<u8>) -> Result<Self, Self::Error> {
514        let mut reader = Cursor::new(data);
515
516        let params_len = reader.read_u64::<LittleEndian>()?;
517        let mut params_buf = vec![0; params_len as usize];
518        reader.read_exact(&mut params_buf)?;
519        let parameters = Parameters::from(params_buf);
520
521        let contract_len = reader.read_u64::<LittleEndian>()?;
522        let mut contract_buf = vec![0; contract_len as usize];
523        reader.read_exact(&mut contract_buf)?;
524        let contract = ContractCode::from(contract_buf);
525
526        let key = ContractKey::from_params_and_code(&parameters, &contract);
527
528        Ok(Contract {
529            parameters,
530            data: contract,
531            key,
532        })
533    }
534}
535
536impl PartialEq for Contract<'_> {
537    fn eq(&self, other: &Self) -> bool {
538        self.key == other.key
539    }
540}
541
542impl Eq for Contract<'_> {}
543
544impl std::fmt::Display for Contract<'_> {
545    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
546        write!(f, "ContractSpec( key: ")?;
547        internal_fmt_key(&self.key.instance.0, f)?;
548        let data: String = if self.data.data.len() > 8 {
549            self.data.data[..4]
550                .iter()
551                .map(|b| char::from(*b))
552                .chain("...".chars())
553                .chain(self.data.data[4..].iter().map(|b| char::from(*b)))
554                .collect()
555        } else {
556            self.data.data.iter().copied().map(char::from).collect()
557        };
558        write!(f, ", data: [{data}])")
559    }
560}
561
562/// Data associated with a contract that can be retrieved by Applications and Delegates.
563///
564/// For efficiency and flexibility, contract state is represented as a simple [u8] byte array.
565#[serde_as]
566#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
567#[cfg_attr(feature = "testing", derive(arbitrary::Arbitrary))]
568pub struct State<'a>(
569    // TODO: conver this to Arc<[u8]> instead
570    #[serde_as(as = "serde_with::Bytes")]
571    #[serde(borrow)]
572    Cow<'a, [u8]>,
573);
574
575impl State<'_> {
576    /// Gets the number of bytes of data stored in the `State`.
577    pub fn size(&self) -> usize {
578        self.0.len()
579    }
580
581    pub fn into_owned(self) -> State<'static> {
582        State(self.0.into_owned().into())
583    }
584
585    /// Extracts the owned data as a `Vec<u8>`.
586    pub fn into_bytes(self) -> Vec<u8> {
587        self.0.into_owned()
588    }
589
590    /// Acquires a mutable reference to the owned form of the `State` data.
591    pub fn to_mut(&mut self) -> &mut Vec<u8> {
592        self.0.to_mut()
593    }
594}
595
596impl From<Vec<u8>> for State<'_> {
597    fn from(state: Vec<u8>) -> Self {
598        State(Cow::from(state))
599    }
600}
601
602impl<'a> From<&'a [u8]> for State<'a> {
603    fn from(state: &'a [u8]) -> Self {
604        State(Cow::from(state))
605    }
606}
607
608impl AsRef<[u8]> for State<'_> {
609    fn as_ref(&self) -> &[u8] {
610        match &self.0 {
611            Cow::Borrowed(arr) => arr,
612            Cow::Owned(arr) => arr.as_ref(),
613        }
614    }
615}
616
617impl<'a> Deref for State<'a> {
618    type Target = Cow<'a, [u8]>;
619
620    fn deref(&self) -> &Self::Target {
621        &self.0
622    }
623}
624
625impl DerefMut for State<'_> {
626    fn deref_mut(&mut self) -> &mut Self::Target {
627        &mut self.0
628    }
629}
630
631impl std::io::Read for State<'_> {
632    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
633        self.as_ref().read(buf)
634    }
635}
636
637/// Represents a modification to some state - similar to a diff in source code.
638///
639/// The exact format of a delta is determined by the contract. A [contract](Contract) implementation will determine whether
640/// a delta is valid - perhaps by verifying it is signed by someone authorized to modify the
641/// contract state. A delta may be created in response to a [State Summary](StateSummary) as part of the State
642/// Synchronization mechanism.
643#[serde_as]
644#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
645#[cfg_attr(feature = "testing", derive(arbitrary::Arbitrary))]
646pub struct StateDelta<'a>(
647    // TODO: conver this to Arc<[u8]> instead
648    #[serde_as(as = "serde_with::Bytes")]
649    #[serde(borrow)]
650    Cow<'a, [u8]>,
651);
652
653impl StateDelta<'_> {
654    /// Gets the number of bytes of data stored in the `StateDelta`.
655    pub fn size(&self) -> usize {
656        self.0.len()
657    }
658
659    /// Extracts the owned data as a `Vec<u8>`.
660    pub fn into_bytes(self) -> Vec<u8> {
661        self.0.into_owned()
662    }
663
664    pub fn into_owned(self) -> StateDelta<'static> {
665        StateDelta(self.0.into_owned().into())
666    }
667}
668
669impl From<Vec<u8>> for StateDelta<'_> {
670    fn from(delta: Vec<u8>) -> Self {
671        StateDelta(Cow::from(delta))
672    }
673}
674
675impl<'a> From<&'a [u8]> for StateDelta<'a> {
676    fn from(delta: &'a [u8]) -> Self {
677        StateDelta(Cow::from(delta))
678    }
679}
680
681impl AsRef<[u8]> for StateDelta<'_> {
682    fn as_ref(&self) -> &[u8] {
683        match &self.0 {
684            Cow::Borrowed(arr) => arr,
685            Cow::Owned(arr) => arr.as_ref(),
686        }
687    }
688}
689
690impl<'a> Deref for StateDelta<'a> {
691    type Target = Cow<'a, [u8]>;
692
693    fn deref(&self) -> &Self::Target {
694        &self.0
695    }
696}
697
698impl DerefMut for StateDelta<'_> {
699    fn deref_mut(&mut self) -> &mut Self::Target {
700        &mut self.0
701    }
702}
703
704/// Summary of `State` changes.
705///
706/// Given a contract state, this is a small piece of data that can be used to determine a delta
707/// between two contracts as part of the state synchronization mechanism. The format of a state
708/// summary is determined by the state's contract.
709#[serde_as]
710#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
711#[cfg_attr(feature = "testing", derive(arbitrary::Arbitrary))]
712pub struct StateSummary<'a>(
713    // TODO: conver this to Arc<[u8]> instead
714    #[serde_as(as = "serde_with::Bytes")]
715    #[serde(borrow)]
716    Cow<'a, [u8]>,
717);
718
719impl StateSummary<'_> {
720    /// Extracts the owned data as a `Vec<u8>`.
721    pub fn into_bytes(self) -> Vec<u8> {
722        self.0.into_owned()
723    }
724
725    /// Gets the number of bytes of data stored in the `StateSummary`.
726    pub fn size(&self) -> usize {
727        self.0.len()
728    }
729
730    pub fn into_owned(self) -> StateSummary<'static> {
731        StateSummary(self.0.into_owned().into())
732    }
733
734    pub fn deser_state_summary<'de, D>(deser: D) -> Result<StateSummary<'static>, D::Error>
735    where
736        D: serde::Deserializer<'de>,
737    {
738        let value = <StateSummary as Deserialize>::deserialize(deser)?;
739        Ok(value.into_owned())
740    }
741}
742
743impl From<Vec<u8>> for StateSummary<'_> {
744    fn from(state: Vec<u8>) -> Self {
745        StateSummary(Cow::from(state))
746    }
747}
748
749impl<'a> From<&'a [u8]> for StateSummary<'a> {
750    fn from(state: &'a [u8]) -> Self {
751        StateSummary(Cow::from(state))
752    }
753}
754
755impl AsRef<[u8]> for StateSummary<'_> {
756    fn as_ref(&self) -> &[u8] {
757        match &self.0 {
758            Cow::Borrowed(arr) => arr,
759            Cow::Owned(arr) => arr.as_ref(),
760        }
761    }
762}
763
764impl<'a> Deref for StateSummary<'a> {
765    type Target = Cow<'a, [u8]>;
766
767    fn deref(&self) -> &Self::Target {
768        &self.0
769    }
770}
771
772impl DerefMut for StateSummary<'_> {
773    fn deref_mut(&mut self) -> &mut Self::Target {
774        &mut self.0
775    }
776}
777
778/// The executable contract.
779///
780/// It is the part of the executable belonging to the full specification
781/// and does not include any other metadata (like the parameters).
782#[serde_as]
783#[derive(Serialize, Deserialize, Clone)]
784#[cfg_attr(
785    any(feature = "testing", all(test, any(unix, windows))),
786    derive(arbitrary::Arbitrary)
787)]
788pub struct ContractCode<'a> {
789    // TODO: conver this to Arc<[u8]> instead
790    #[serde_as(as = "serde_with::Bytes")]
791    #[serde(borrow)]
792    pub(crate) data: Cow<'a, [u8]>,
793    // todo: skip serializing and instead compute it
794    pub(crate) code_hash: CodeHash,
795}
796
797impl ContractCode<'static> {
798    /// Loads the contract raw wasm module, without any version.
799    pub fn load_raw(path: &Path) -> Result<Self, std::io::Error> {
800        let contract_data = Self::load_bytes(path)?;
801        Ok(ContractCode::from(contract_data))
802    }
803
804    pub(crate) fn load_bytes(path: &Path) -> Result<Vec<u8>, std::io::Error> {
805        let mut contract_file = File::open(path)?;
806        let mut contract_data = if let Ok(md) = contract_file.metadata() {
807            Vec::with_capacity(md.len() as usize)
808        } else {
809            Vec::new()
810        };
811        contract_file.read_to_end(&mut contract_data)?;
812        Ok(contract_data)
813    }
814}
815
816impl ContractCode<'_> {
817    /// Contract code hash.
818    pub fn hash(&self) -> &CodeHash {
819        &self.code_hash
820    }
821
822    /// Returns the `Base58` string representation of the contract key.
823    pub fn hash_str(&self) -> String {
824        Self::encode_hash(&self.code_hash.0)
825    }
826
827    /// Reference to contract code.
828    pub fn data(&self) -> &[u8] {
829        &self.data
830    }
831
832    /// Extracts the owned contract code data as a `Vec<u8>`.
833    pub fn into_bytes(self) -> Vec<u8> {
834        self.data.to_vec()
835    }
836
837    /// Returns the `Base58` string representation of a hash.
838    pub fn encode_hash(hash: &[u8; CONTRACT_KEY_SIZE]) -> String {
839        bs58::encode(hash)
840            .with_alphabet(bs58::Alphabet::BITCOIN)
841            .into_string()
842    }
843
844    /// Copies the data if not owned and returns an owned version of self.
845    pub fn into_owned(self) -> ContractCode<'static> {
846        ContractCode {
847            data: self.data.into_owned().into(),
848            code_hash: self.code_hash,
849        }
850    }
851
852    fn gen_hash(data: &[u8]) -> CodeHash {
853        let mut hasher = Blake3::new();
854        hasher.update(data);
855        let key_arr = hasher.finalize();
856        debug_assert_eq!(key_arr[..].len(), CONTRACT_KEY_SIZE);
857        let mut key = [0; CONTRACT_KEY_SIZE];
858        key.copy_from_slice(&key_arr);
859        CodeHash(key)
860    }
861}
862
863impl From<Vec<u8>> for ContractCode<'static> {
864    fn from(data: Vec<u8>) -> Self {
865        let key = ContractCode::gen_hash(&data);
866        ContractCode {
867            data: Cow::from(data),
868            code_hash: key,
869        }
870    }
871}
872
873impl<'a> From<&'a [u8]> for ContractCode<'a> {
874    fn from(data: &'a [u8]) -> ContractCode<'a> {
875        let hash = ContractCode::gen_hash(data);
876        ContractCode {
877            data: Cow::from(data),
878            code_hash: hash,
879        }
880    }
881}
882
883impl PartialEq for ContractCode<'_> {
884    fn eq(&self, other: &Self) -> bool {
885        self.code_hash == other.code_hash
886    }
887}
888
889impl Eq for ContractCode<'_> {}
890
891impl std::fmt::Display for ContractCode<'_> {
892    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
893        write!(f, "Contract( key: ")?;
894        internal_fmt_key(&self.code_hash.0, f)?;
895        let data: String = if self.data.len() > 8 {
896            self.data[..4]
897                .iter()
898                .map(|b| char::from(*b))
899                .chain("...".chars())
900                .chain(self.data[4..].iter().map(|b| char::from(*b)))
901                .collect()
902        } else {
903            self.data.iter().copied().map(char::from).collect()
904        };
905        write!(f, ", data: [{data}])")
906    }
907}
908
909impl std::fmt::Debug for ContractCode<'_> {
910    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
911        f.debug_struct("ContractCode")
912            .field("hash", &self.code_hash);
913        Ok(())
914    }
915}
916
917/// The key representing the hash of the contract executable code hash and a set of `parameters`.
918#[serde_as]
919#[derive(PartialEq, Eq, Clone, Copy, Serialize, Deserialize, Hash)]
920#[cfg_attr(
921    any(feature = "testing", all(test, any(unix, windows))),
922    derive(arbitrary::Arbitrary)
923)]
924#[repr(transparent)]
925pub struct ContractInstanceId(#[serde_as(as = "[_; CONTRACT_KEY_SIZE]")] [u8; CONTRACT_KEY_SIZE]);
926
927impl ContractInstanceId {
928    pub fn from_params_and_code<'a>(
929        params: impl Borrow<Parameters<'a>>,
930        code: impl Borrow<ContractCode<'a>>,
931    ) -> Self {
932        generate_id(params.borrow(), code.borrow())
933    }
934
935    pub const fn new(key: [u8; CONTRACT_KEY_SIZE]) -> Self {
936        Self(key)
937    }
938
939    /// `Base58` string representation of the `contract id`.
940    pub fn encode(&self) -> String {
941        bs58::encode(self.0)
942            .with_alphabet(bs58::Alphabet::BITCOIN)
943            .into_string()
944    }
945
946    pub fn as_bytes(&self) -> &[u8] {
947        self.0.as_slice()
948    }
949
950    /// Build `ContractId` from the binary representation.
951    pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Result<Self, bs58::decode::Error> {
952        let mut spec = [0; CONTRACT_KEY_SIZE];
953        bs58::decode(bytes)
954            .with_alphabet(bs58::Alphabet::BITCOIN)
955            .onto(&mut spec)?;
956        Ok(Self(spec))
957    }
958}
959
960impl Deref for ContractInstanceId {
961    type Target = [u8; CONTRACT_KEY_SIZE];
962
963    fn deref(&self) -> &Self::Target {
964        &self.0
965    }
966}
967
968impl FromStr for ContractInstanceId {
969    type Err = bs58::decode::Error;
970
971    fn from_str(s: &str) -> Result<Self, Self::Err> {
972        ContractInstanceId::from_bytes(s)
973    }
974}
975
976impl TryFrom<String> for ContractInstanceId {
977    type Error = bs58::decode::Error;
978
979    fn try_from(s: String) -> Result<Self, Self::Error> {
980        ContractInstanceId::from_bytes(s)
981    }
982}
983
984impl Display for ContractInstanceId {
985    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
986        write!(f, "{}", self.encode())
987    }
988}
989
990impl std::fmt::Debug for ContractInstanceId {
991    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
992        f.debug_tuple("ContractInstanceId")
993            .field(&self.encode())
994            .finish()
995    }
996}
997
998/// A complete key specification, that represents a cryptographic hash that identifies the contract.
999#[serde_as]
1000#[derive(Debug, Eq, Copy, Clone, Serialize, Deserialize)]
1001#[cfg_attr(
1002    any(feature = "testing", all(test, any(unix, windows))),
1003    derive(arbitrary::Arbitrary)
1004)]
1005pub struct ContractKey {
1006    instance: ContractInstanceId,
1007    code: Option<CodeHash>,
1008}
1009
1010impl ContractKey {
1011    pub fn from_params_and_code<'a>(
1012        params: impl Borrow<Parameters<'a>>,
1013        wasm_code: impl Borrow<ContractCode<'a>>,
1014    ) -> Self {
1015        let code = wasm_code.borrow();
1016        let id = generate_id(params.borrow(), code);
1017        let code_hash = code.hash();
1018        Self {
1019            instance: id,
1020            code: Some(*code_hash),
1021        }
1022    }
1023
1024    /// Builds a partial [`ContractKey`](ContractKey), the contract code part is unspecified.
1025    pub fn from_id(instance: impl Into<String>) -> Result<Self, bs58::decode::Error> {
1026        let instance = ContractInstanceId::try_from(instance.into())?;
1027        Ok(Self {
1028            instance,
1029            code: None,
1030        })
1031    }
1032
1033    /// Gets the whole spec key hash.
1034    pub fn as_bytes(&self) -> &[u8] {
1035        self.instance.0.as_ref()
1036    }
1037
1038    /// Returns the hash of the contract code only, if the key is fully specified.
1039    pub fn code_hash(&self) -> Option<&CodeHash> {
1040        self.code.as_ref()
1041    }
1042
1043    /// Returns the encoded hash of the contract code, if the key is fully specified.
1044    pub fn encoded_code_hash(&self) -> Option<String> {
1045        self.code.as_ref().map(|c| {
1046            bs58::encode(c.0)
1047                .with_alphabet(bs58::Alphabet::BITCOIN)
1048                .into_string()
1049        })
1050    }
1051
1052    /// Returns the contract key from the encoded hash of the contract code and the given
1053    /// parameters.
1054    pub fn from_params(
1055        code_hash: impl Into<String>,
1056        parameters: Parameters,
1057    ) -> Result<Self, bs58::decode::Error> {
1058        let mut code_key = [0; CONTRACT_KEY_SIZE];
1059        bs58::decode(code_hash.into())
1060            .with_alphabet(bs58::Alphabet::BITCOIN)
1061            .onto(&mut code_key)?;
1062
1063        let mut hasher = Blake3::new();
1064        hasher.update(code_key.as_slice());
1065        hasher.update(parameters.as_ref());
1066        let full_key_arr = hasher.finalize();
1067
1068        let mut spec = [0; CONTRACT_KEY_SIZE];
1069        spec.copy_from_slice(&full_key_arr);
1070        Ok(Self {
1071            instance: ContractInstanceId(spec),
1072            code: Some(CodeHash(code_key)),
1073        })
1074    }
1075
1076    /// Returns the `Base58` encoded string of the [`ContractInstanceId`](ContractInstanceId).
1077    pub fn encoded_contract_id(&self) -> String {
1078        self.instance.encode()
1079    }
1080
1081    pub fn id(&self) -> &ContractInstanceId {
1082        &self.instance
1083    }
1084}
1085
1086impl PartialEq for ContractKey {
1087    fn eq(&self, other: &Self) -> bool {
1088        self.instance == other.instance
1089    }
1090}
1091
1092impl std::hash::Hash for ContractKey {
1093    fn hash<H: Hasher>(&self, state: &mut H) {
1094        self.instance.0.hash(state);
1095    }
1096}
1097
1098impl From<ContractInstanceId> for ContractKey {
1099    fn from(instance: ContractInstanceId) -> Self {
1100        Self {
1101            instance,
1102            code: None,
1103        }
1104    }
1105}
1106
1107impl From<ContractKey> for ContractInstanceId {
1108    fn from(key: ContractKey) -> Self {
1109        key.instance
1110    }
1111}
1112
1113impl Deref for ContractKey {
1114    type Target = [u8; CONTRACT_KEY_SIZE];
1115
1116    fn deref(&self) -> &Self::Target {
1117        &self.instance.0
1118    }
1119}
1120
1121impl std::fmt::Display for ContractKey {
1122    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1123        self.instance.fmt(f)
1124    }
1125}
1126
1127impl<'a> TryFromFbs<&FbsContractKey<'a>> for ContractKey {
1128    fn try_decode_fbs(key: &FbsContractKey<'a>) -> Result<Self, WsApiError> {
1129        let key_bytes: [u8; CONTRACT_KEY_SIZE] = key.instance().data().bytes().try_into().unwrap();
1130        let instance = ContractInstanceId::new(key_bytes);
1131        let code = key
1132            .code()
1133            .map(|code_hash| CodeHash::from_code(code_hash.bytes()));
1134        Ok(ContractKey { instance, code })
1135    }
1136}
1137
1138fn generate_id<'a>(
1139    parameters: &Parameters<'a>,
1140    code_data: &ContractCode<'a>,
1141) -> ContractInstanceId {
1142    let contract_hash = code_data.hash();
1143
1144    let mut hasher = Blake3::new();
1145    hasher.update(contract_hash.0.as_slice());
1146    hasher.update(parameters.as_ref());
1147    let full_key_arr = hasher.finalize();
1148
1149    debug_assert_eq!(full_key_arr[..].len(), CONTRACT_KEY_SIZE);
1150    let mut spec = [0; CONTRACT_KEY_SIZE];
1151    spec.copy_from_slice(&full_key_arr);
1152    ContractInstanceId(spec)
1153}
1154
1155#[inline]
1156fn internal_fmt_key(
1157    key: &[u8; CONTRACT_KEY_SIZE],
1158    f: &mut std::fmt::Formatter<'_>,
1159) -> std::fmt::Result {
1160    let r = bs58::encode(key)
1161        .with_alphabet(bs58::Alphabet::BITCOIN)
1162        .into_string();
1163    write!(f, "{}", &r[..8])
1164}
1165
1166// TODO:  get rid of this when State is internally an Arc<[u8]>
1167/// The state for a contract.
1168#[derive(PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
1169#[cfg_attr(feature = "testing", derive(arbitrary::Arbitrary))]
1170pub struct WrappedState(
1171    #[serde(
1172        serialize_with = "WrappedState::ser_state",
1173        deserialize_with = "WrappedState::deser_state"
1174    )]
1175    Arc<Vec<u8>>,
1176);
1177
1178impl WrappedState {
1179    pub fn new(bytes: Vec<u8>) -> Self {
1180        WrappedState(Arc::new(bytes))
1181    }
1182
1183    pub fn size(&self) -> usize {
1184        self.0.len()
1185    }
1186
1187    fn ser_state<S>(data: &Arc<Vec<u8>>, ser: S) -> Result<S::Ok, S::Error>
1188    where
1189        S: serde::Serializer,
1190    {
1191        serde_bytes::serialize(&**data, ser)
1192    }
1193
1194    fn deser_state<'de, D>(deser: D) -> Result<Arc<Vec<u8>>, D::Error>
1195    where
1196        D: Deserializer<'de>,
1197    {
1198        let data: Vec<u8> = serde_bytes::deserialize(deser)?;
1199        Ok(Arc::new(data))
1200    }
1201}
1202
1203impl From<Vec<u8>> for WrappedState {
1204    fn from(bytes: Vec<u8>) -> Self {
1205        Self::new(bytes)
1206    }
1207}
1208
1209impl From<&'_ [u8]> for WrappedState {
1210    fn from(bytes: &[u8]) -> Self {
1211        Self::new(bytes.to_owned())
1212    }
1213}
1214
1215impl AsRef<[u8]> for WrappedState {
1216    fn as_ref(&self) -> &[u8] {
1217        self.0.as_ref()
1218    }
1219}
1220
1221impl Deref for WrappedState {
1222    type Target = [u8];
1223
1224    fn deref(&self) -> &Self::Target {
1225        &self.0
1226    }
1227}
1228
1229impl Borrow<[u8]> for WrappedState {
1230    fn borrow(&self) -> &[u8] {
1231        &self.0
1232    }
1233}
1234
1235impl From<WrappedState> for State<'static> {
1236    fn from(value: WrappedState) -> Self {
1237        match Arc::try_unwrap(value.0) {
1238            Ok(v) => State::from(v),
1239            Err(v) => State::from(v.as_ref().to_vec()),
1240        }
1241    }
1242}
1243
1244impl std::fmt::Display for WrappedState {
1245    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1246        write!(f, "ContractState(data: [0x")?;
1247        for b in self.0.iter().take(8) {
1248            write!(f, "{:02x}", b)?;
1249        }
1250        write!(f, "...])")
1251    }
1252}
1253
1254impl std::fmt::Debug for WrappedState {
1255    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1256        <Self as Display>::fmt(self, f)
1257    }
1258}
1259
1260/// Just as `freenet_stdlib::Contract` but with some convenience impl.
1261#[non_exhaustive]
1262#[derive(Clone, Debug, Serialize, Deserialize)]
1263pub struct WrappedContract {
1264    #[serde(
1265        serialize_with = "WrappedContract::ser_contract_data",
1266        deserialize_with = "WrappedContract::deser_contract_data"
1267    )]
1268    pub data: Arc<ContractCode<'static>>,
1269    #[serde(deserialize_with = "Parameters::deser_params")]
1270    pub params: Parameters<'static>,
1271    pub key: ContractKey,
1272}
1273
1274impl PartialEq for WrappedContract {
1275    fn eq(&self, other: &Self) -> bool {
1276        self.key == other.key
1277    }
1278}
1279
1280impl Eq for WrappedContract {}
1281
1282impl WrappedContract {
1283    pub fn new(data: Arc<ContractCode<'static>>, params: Parameters<'static>) -> WrappedContract {
1284        let key = ContractKey::from_params_and_code(&params, &*data);
1285        WrappedContract { data, params, key }
1286    }
1287
1288    #[inline]
1289    pub fn key(&self) -> &ContractKey {
1290        &self.key
1291    }
1292
1293    #[inline]
1294    pub fn code(&self) -> &Arc<ContractCode<'static>> {
1295        &self.data
1296    }
1297
1298    #[inline]
1299    pub fn params(&self) -> &Parameters<'static> {
1300        &self.params
1301    }
1302
1303    fn ser_contract_data<S>(data: &Arc<ContractCode<'_>>, ser: S) -> Result<S::Ok, S::Error>
1304    where
1305        S: serde::Serializer,
1306    {
1307        data.serialize(ser)
1308    }
1309
1310    fn deser_contract_data<'de, D>(deser: D) -> Result<Arc<ContractCode<'static>>, D::Error>
1311    where
1312        D: Deserializer<'de>,
1313    {
1314        let data: ContractCode<'de> = Deserialize::deserialize(deser)?;
1315        Ok(Arc::new(data.into_owned()))
1316    }
1317}
1318
1319impl TryInto<Vec<u8>> for WrappedContract {
1320    type Error = ();
1321    fn try_into(self) -> Result<Vec<u8>, Self::Error> {
1322        Arc::try_unwrap(self.data)
1323            .map(|r| r.into_bytes())
1324            .map_err(|_| ())
1325    }
1326}
1327
1328impl Display for WrappedContract {
1329    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1330        self.key.fmt(f)
1331    }
1332}
1333
1334#[cfg(feature = "testing")]
1335impl<'a> arbitrary::Arbitrary<'a> for WrappedContract {
1336    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1337        use arbitrary::Arbitrary;
1338        let data = <ContractCode as Arbitrary>::arbitrary(u)?.into_owned();
1339        let param_bytes: Vec<u8> = Arbitrary::arbitrary(u)?;
1340        let params = Parameters::from(param_bytes);
1341        let key = ContractKey::from_params_and_code(&params, &data);
1342        Ok(Self {
1343            data: Arc::new(data),
1344            params,
1345            key,
1346        })
1347    }
1348}
1349
1350#[doc(hidden)]
1351pub(crate) mod wasm_interface {
1352    //! Contains all the types to interface between the host environment and
1353    //! the wasm module execution.
1354    use super::*;
1355    use crate::memory::WasmLinearMem;
1356
1357    #[repr(i32)]
1358    enum ResultKind {
1359        ValidateState = 0,
1360        ValidateDelta = 1,
1361        UpdateState = 2,
1362        SummarizeState = 3,
1363        StateDelta = 4,
1364    }
1365
1366    impl From<i32> for ResultKind {
1367        fn from(v: i32) -> Self {
1368            match v {
1369                0 => ResultKind::ValidateState,
1370                1 => ResultKind::ValidateDelta,
1371                2 => ResultKind::UpdateState,
1372                3 => ResultKind::SummarizeState,
1373                4 => ResultKind::StateDelta,
1374                _ => panic!(),
1375            }
1376        }
1377    }
1378
1379    #[doc(hidden)]
1380    #[repr(C)]
1381    #[derive(Debug, Clone, Copy)]
1382    pub struct ContractInterfaceResult {
1383        ptr: i64,
1384        kind: i32,
1385        size: u32,
1386    }
1387
1388    impl ContractInterfaceResult {
1389        pub unsafe fn unwrap_validate_state_res(
1390            self,
1391            mem: WasmLinearMem,
1392        ) -> Result<ValidateResult, ContractError> {
1393            #![allow(clippy::let_and_return)]
1394            let kind = ResultKind::from(self.kind);
1395            match kind {
1396                ResultKind::ValidateState => {
1397                    let ptr = crate::memory::buf::compute_ptr(self.ptr as *mut u8, &mem);
1398                    let serialized = std::slice::from_raw_parts(ptr as *const u8, self.size as _);
1399                    let value = bincode::deserialize(serialized)
1400                        .map_err(|e| ContractError::Other(format!("{e}")))?;
1401                    #[cfg(feature = "trace")]
1402                    self.log_input(serialized, &value, ptr);
1403                    value
1404                }
1405                _ => unreachable!(),
1406            }
1407        }
1408
1409        pub unsafe fn unwrap_update_state(
1410            self,
1411            mem: WasmLinearMem,
1412        ) -> Result<UpdateModification<'static>, ContractError> {
1413            let kind = ResultKind::from(self.kind);
1414            match kind {
1415                ResultKind::UpdateState => {
1416                    let ptr = crate::memory::buf::compute_ptr(self.ptr as *mut u8, &mem);
1417                    let serialized = std::slice::from_raw_parts(ptr as *const u8, self.size as _);
1418                    let value: Result<UpdateModification<'_>, ContractError> =
1419                        bincode::deserialize(serialized)
1420                            .map_err(|e| ContractError::Other(format!("{e}")))?;
1421                    #[cfg(feature = "trace")]
1422                    self.log_input(serialized, &value, ptr);
1423                    // TODO: it may be possible to not own this value while deserializing
1424                    //       under certain circumstances (e.g. when the cotnract mem is kept alive)
1425                    value.map(|r| r.into_owned())
1426                }
1427                _ => unreachable!(),
1428            }
1429        }
1430
1431        pub unsafe fn unwrap_summarize_state(
1432            self,
1433            mem: WasmLinearMem,
1434        ) -> Result<StateSummary<'static>, ContractError> {
1435            let kind = ResultKind::from(self.kind);
1436            match kind {
1437                ResultKind::SummarizeState => {
1438                    let ptr = crate::memory::buf::compute_ptr(self.ptr as *mut u8, &mem);
1439                    let serialized = std::slice::from_raw_parts(ptr as *const u8, self.size as _);
1440                    let value: Result<StateSummary<'static>, ContractError> =
1441                        bincode::deserialize(serialized)
1442                            .map_err(|e| ContractError::Other(format!("{e}")))?;
1443                    #[cfg(feature = "trace")]
1444                    self.log_input(serialized, &value, ptr);
1445                    // TODO: it may be possible to not own this value while deserializing
1446                    //       under certain circumstances (e.g. when the contract mem is kept alive)
1447                    value.map(|s| StateSummary::from(s.into_bytes()))
1448                }
1449                _ => unreachable!(),
1450            }
1451        }
1452
1453        pub unsafe fn unwrap_get_state_delta(
1454            self,
1455            mem: WasmLinearMem,
1456        ) -> Result<StateDelta<'static>, ContractError> {
1457            let kind = ResultKind::from(self.kind);
1458            match kind {
1459                ResultKind::StateDelta => {
1460                    let ptr = crate::memory::buf::compute_ptr(self.ptr as *mut u8, &mem);
1461                    let serialized = std::slice::from_raw_parts(ptr as *const u8, self.size as _);
1462                    let value: Result<StateDelta<'static>, ContractError> =
1463                        bincode::deserialize(serialized)
1464                            .map_err(|e| ContractError::Other(format!("{e}")))?;
1465                    #[cfg(feature = "trace")]
1466                    self.log_input(serialized, &value, ptr);
1467                    // TODO: it may be possible to not own this value while deserializing
1468                    //       under certain circumstances (e.g. when the contract mem is kept alive)
1469                    value.map(|d| StateDelta::from(d.into_bytes()))
1470                }
1471                _ => unreachable!(),
1472            }
1473        }
1474
1475        #[cfg(feature = "contract")]
1476        pub fn into_raw(self) -> i64 {
1477            #[cfg(feature = "trace")]
1478            {
1479                tracing::trace!("returning FFI -> {self:?}");
1480            }
1481            let ptr = Box::into_raw(Box::new(self));
1482            #[cfg(feature = "trace")]
1483            {
1484                tracing::trace!("FFI result ptr: {ptr:p} ({}i64)", ptr as i64);
1485            }
1486            ptr as _
1487        }
1488
1489        pub unsafe fn from_raw(ptr: i64, mem: &WasmLinearMem) -> Self {
1490            let result = Box::leak(Box::from_raw(crate::memory::buf::compute_ptr(
1491                ptr as *mut Self,
1492                mem,
1493            )));
1494            #[cfg(feature = "trace")]
1495            {
1496                tracing::trace!(
1497                    "got FFI result @ {ptr} ({:p}) -> {result:?}",
1498                    ptr as *mut Self
1499                );
1500            }
1501            *result
1502        }
1503
1504        #[cfg(feature = "trace")]
1505        fn log_input<T: std::fmt::Debug>(&self, serialized: &[u8], value: &T, ptr: *mut u8) {
1506            tracing::trace!(
1507                "got result through FFI; addr: {:p} ({}i64, mapped: {ptr:p})
1508                 serialized: {serialized:?}
1509                 value: {value:?}",
1510                self.ptr as *mut u8,
1511                self.ptr
1512            );
1513        }
1514    }
1515
1516    #[cfg(feature = "contract")]
1517    macro_rules! conversion {
1518        ($value:ty: $kind:expr) => {
1519            impl From<$value> for ContractInterfaceResult {
1520                fn from(value: $value) -> Self {
1521                    let kind = $kind as i32;
1522                    // TODO: research if there is a safe way to just transmute the pointer in memory
1523                    //       independently of the architecture when stored in WASM and accessed from
1524                    //       the host, maybe even if is just for some architectures
1525                    let serialized = bincode::serialize(&value).unwrap();
1526                    let size = serialized.len() as _;
1527                    let ptr = serialized.as_ptr();
1528                    #[cfg(feature = "trace")] {
1529                        tracing::trace!(
1530                            "sending result through FFI; addr: {ptr:p} ({}),\n  serialized: {serialized:?}\n  value: {value:?}",
1531                            ptr as i64
1532                        );
1533                    }
1534                    std::mem::forget(serialized);
1535                    Self { kind, ptr: ptr as i64, size }
1536                }
1537            }
1538        };
1539    }
1540
1541    #[cfg(feature = "contract")]
1542    conversion!(Result<ValidateResult, ContractError>: ResultKind::ValidateState);
1543    #[cfg(feature = "contract")]
1544    conversion!(Result<bool, ContractError>: ResultKind::ValidateDelta);
1545    #[cfg(feature = "contract")]
1546    conversion!(Result<UpdateModification<'static>, ContractError>: ResultKind::UpdateState);
1547    #[cfg(feature = "contract")]
1548    conversion!(Result<StateSummary<'static>, ContractError>: ResultKind::SummarizeState);
1549    #[cfg(feature = "contract")]
1550    conversion!(Result<StateDelta<'static>, ContractError>: ResultKind::StateDelta);
1551}
1552
1553#[cfg(all(test, any(unix, windows)))]
1554mod test {
1555    use super::*;
1556    use once_cell::sync::Lazy;
1557    use rand::{rngs::SmallRng, Rng, SeedableRng};
1558
1559    static RND_BYTES: Lazy<[u8; 1024]> = Lazy::new(|| {
1560        let mut bytes = [0; 1024];
1561        let mut rng = SmallRng::from_entropy();
1562        rng.fill(&mut bytes);
1563        bytes
1564    });
1565
1566    #[test]
1567    fn key_encoding() -> Result<(), Box<dyn std::error::Error>> {
1568        let code = ContractCode::from(vec![1, 2, 3]);
1569        let expected = ContractKey::from_params_and_code(Parameters::from(vec![]), &code);
1570        // let encoded_key = expected.encode();
1571        // println!("encoded key: {encoded_key}");
1572        // let encoded_code = expected.contract_part_as_str();
1573        // println!("encoded key: {encoded_code}");
1574
1575        let decoded = ContractKey::from_params(code.hash_str(), [].as_ref().into())?;
1576        assert_eq!(expected, decoded);
1577        assert_eq!(expected.code_hash(), decoded.code_hash());
1578        Ok(())
1579    }
1580
1581    #[test]
1582    fn key_ser() -> Result<(), Box<dyn std::error::Error>> {
1583        let mut gen = arbitrary::Unstructured::new(&*RND_BYTES);
1584        let expected: ContractKey = gen.arbitrary()?;
1585        let encoded = bs58::encode(expected.as_bytes()).into_string();
1586        // println!("encoded key: {encoded}");
1587
1588        let serialized = bincode::serialize(&expected)?;
1589        let deserialized: ContractKey = bincode::deserialize(&serialized)?;
1590        let decoded = bs58::encode(deserialized.as_bytes()).into_string();
1591        assert_eq!(encoded, decoded);
1592        assert_eq!(deserialized, expected);
1593        Ok(())
1594    }
1595
1596    #[test]
1597    fn contract_ser() -> Result<(), Box<dyn std::error::Error>> {
1598        let mut gen = arbitrary::Unstructured::new(&*RND_BYTES);
1599        let expected: Contract = gen.arbitrary()?;
1600
1601        let serialized = bincode::serialize(&expected)?;
1602        let deserialized: Contract = bincode::deserialize(&serialized)?;
1603        assert_eq!(deserialized, expected);
1604        Ok(())
1605    }
1606}
1607
1608pub mod encoding {
1609    //! Helper types for interaction between wasm and host boundaries.
1610    use std::{collections::HashSet, marker::PhantomData};
1611
1612    use serde::de::DeserializeOwned;
1613
1614    use super::*;
1615
1616    pub enum MergeResult {
1617        Success,
1618        RequestRelated(RelatedContractsContainer),
1619        Error(ContractError),
1620    }
1621
1622    #[derive(Default)]
1623    pub struct RelatedContractsContainer {
1624        contracts: HashMap<ContractInstanceId, State<'static>>,
1625        pending: HashSet<ContractInstanceId>,
1626        not_found: HashSet<ContractInstanceId>,
1627    }
1628
1629    impl From<RelatedContracts<'static>> for RelatedContractsContainer {
1630        fn from(found: RelatedContracts<'static>) -> Self {
1631            let mut not_found = HashSet::new();
1632            let mut contracts = HashMap::with_capacity(found.map.len());
1633            for (id, state) in found.map.into_iter() {
1634                match state {
1635                    Some(state) => {
1636                        contracts.insert(id, state);
1637                    }
1638                    None => {
1639                        not_found.insert(id);
1640                    }
1641                }
1642            }
1643            RelatedContractsContainer {
1644                contracts,
1645                pending: HashSet::new(),
1646                not_found,
1647            }
1648        }
1649    }
1650
1651    impl From<RelatedContractsContainer> for Vec<crate::contract_interface::RelatedContract> {
1652        fn from(related: RelatedContractsContainer) -> Self {
1653            related
1654                .pending
1655                .into_iter()
1656                .map(|id| RelatedContract {
1657                    contract_instance_id: id,
1658                    mode: RelatedMode::StateOnce,
1659                })
1660                .collect()
1661        }
1662    }
1663
1664    impl From<Vec<UpdateData<'static>>> for RelatedContractsContainer {
1665        fn from(updates: Vec<UpdateData<'static>>) -> Self {
1666            let mut this = RelatedContractsContainer::default();
1667            for update in updates {
1668                match update {
1669                    UpdateData::RelatedState { related_to, state } => {
1670                        this.contracts.insert(related_to, state);
1671                    }
1672                    UpdateData::RelatedStateAndDelta {
1673                        related_to, state, ..
1674                    } => {
1675                        this.contracts.insert(related_to, state);
1676                    }
1677                    _ => {}
1678                }
1679            }
1680            this
1681        }
1682    }
1683
1684    impl RelatedContractsContainer {
1685        pub fn get<C: TypedContract>(
1686            &self,
1687            params: &C::Parameters,
1688        ) -> Result<Related<C>, <<C as EncodingAdapter>::SelfEncoder as Encoder<C>>::Error>
1689        {
1690            let id = <C as TypedContract>::instance_id(params);
1691            if let Some(res) = self.contracts.get(&id) {
1692                match <<C as EncodingAdapter>::SelfEncoder>::deserialize(res.as_ref()) {
1693                    Ok(state) => return Ok(Related::Found { state }),
1694                    Err(err) => return Err(err),
1695                }
1696            }
1697            if self.pending.contains(&id) {
1698                return Ok(Related::RequestPending);
1699            }
1700            if self.not_found.contains(&id) {
1701                return Ok(Related::NotFound);
1702            }
1703            Ok(Related::NotRequested)
1704        }
1705
1706        pub fn request<C: TypedContract>(&mut self, id: ContractInstanceId) {
1707            self.pending.insert(id);
1708        }
1709
1710        pub fn merge(&mut self, other: Self) {
1711            let Self {
1712                contracts,
1713                pending,
1714                not_found,
1715            } = other;
1716            self.pending.extend(pending);
1717            self.not_found.extend(not_found);
1718            self.contracts.extend(contracts);
1719        }
1720    }
1721
1722    pub enum Related<C: TypedContract> {
1723        /// The state was previously requested and found
1724        Found { state: C },
1725        /// The state was previously requested but not found
1726        NotFound,
1727        /// The state was previously requested but request is still in flight
1728        RequestPending,
1729        /// The state was not previously requested, this enum can be included
1730        /// in the MergeResult return value which will request it
1731        NotRequested,
1732    }
1733
1734    /// A contract state and it's associated types which can be encoded and decoded
1735    /// via an specific encoder.
1736    pub trait EncodingAdapter
1737    where
1738        Self: Sized,
1739    {
1740        type Parameters;
1741        type Delta;
1742        type Summary;
1743
1744        type SelfEncoder: Encoder<Self>;
1745        type ParametersEncoder: Encoder<Self::Parameters>;
1746        type DeltaEncoder: Encoder<Self::Delta>;
1747        type SummaryEncoder: Encoder<Self::Summary>;
1748    }
1749
1750    pub enum TypedUpdateData<T: EncodingAdapter> {
1751        RelatedState { state: T },
1752        RelatedDelta { delta: T::Delta },
1753        RelatedStateAndDelta { state: T, delta: T::Delta },
1754    }
1755
1756    impl<T: EncodingAdapter> TypedUpdateData<T> {
1757        pub fn from_other<Parent>(value: &TypedUpdateData<Parent>) -> Self
1758        where
1759            Parent: EncodingAdapter,
1760            T: for<'x> From<&'x Parent>,
1761            T::Delta: for<'x> From<&'x Parent::Delta>,
1762        {
1763            match value {
1764                TypedUpdateData::RelatedState { state } => {
1765                    let state = T::from(state);
1766                    TypedUpdateData::RelatedState { state }
1767                }
1768                TypedUpdateData::RelatedDelta { delta } => {
1769                    let delta: T::Delta = <T as EncodingAdapter>::Delta::from(delta);
1770                    TypedUpdateData::RelatedDelta { delta }
1771                }
1772                TypedUpdateData::RelatedStateAndDelta { state, delta } => {
1773                    let state = T::from(state);
1774                    let delta: T::Delta = <T as EncodingAdapter>::Delta::from(delta);
1775                    TypedUpdateData::RelatedStateAndDelta { state, delta }
1776                }
1777            }
1778        }
1779    }
1780
1781    impl<T: EncodingAdapter> TryFrom<(Option<T>, Option<T::Delta>)> for TypedUpdateData<T> {
1782        type Error = ContractError;
1783        fn try_from((state, delta): (Option<T>, Option<T::Delta>)) -> Result<Self, Self::Error> {
1784            match (state, delta) {
1785                (None, None) => Err(ContractError::InvalidState),
1786                (None, Some(delta)) => Ok(Self::RelatedDelta { delta }),
1787                (Some(state), None) => Ok(Self::RelatedState { state }),
1788                (Some(state), Some(delta)) => Ok(Self::RelatedStateAndDelta { state, delta }),
1789            }
1790        }
1791    }
1792
1793    pub trait TypedContract: EncodingAdapter {
1794        fn instance_id(params: &Self::Parameters) -> ContractInstanceId;
1795
1796        fn verify(
1797            &self,
1798            parameters: Self::Parameters,
1799            related: RelatedContractsContainer,
1800        ) -> Result<ValidateResult, ContractError>;
1801
1802        fn merge(
1803            &mut self,
1804            parameters: &Self::Parameters,
1805            update: TypedUpdateData<Self>,
1806            related: &RelatedContractsContainer,
1807        ) -> MergeResult;
1808
1809        fn summarize(&self, parameters: Self::Parameters) -> Result<Self::Summary, ContractError>;
1810
1811        fn delta(
1812            &self,
1813            parameters: Self::Parameters,
1814            summary: Self::Summary,
1815        ) -> Result<Self::Delta, ContractError>;
1816    }
1817
1818    pub trait Encoder<T> {
1819        type Error: Into<ContractError>;
1820        fn deserialize(bytes: &[u8]) -> Result<T, Self::Error>;
1821        fn serialize(value: &T) -> Result<Vec<u8>, Self::Error>;
1822    }
1823
1824    pub struct JsonEncoder<T>(PhantomData<T>);
1825
1826    impl<T> Encoder<T> for JsonEncoder<T>
1827    where
1828        T: DeserializeOwned + Serialize,
1829    {
1830        type Error = serde_json::Error;
1831
1832        fn deserialize(bytes: &[u8]) -> Result<T, Self::Error> {
1833            serde_json::from_slice(bytes)
1834        }
1835
1836        fn serialize(value: &T) -> Result<Vec<u8>, Self::Error> {
1837            serde_json::to_vec(value)
1838        }
1839    }
1840
1841    impl From<serde_json::Error> for ContractError {
1842        fn from(value: serde_json::Error) -> Self {
1843            ContractError::Deser(format!("{value}"))
1844        }
1845    }
1846
1847    pub struct BincodeEncoder<T>(PhantomData<T>);
1848
1849    impl<T> Encoder<T> for BincodeEncoder<T>
1850    where
1851        T: DeserializeOwned + Serialize,
1852    {
1853        type Error = bincode::Error;
1854
1855        fn deserialize(bytes: &[u8]) -> Result<T, Self::Error> {
1856            bincode::deserialize(bytes)
1857        }
1858
1859        fn serialize(value: &T) -> Result<Vec<u8>, Self::Error> {
1860            bincode::serialize(value)
1861        }
1862    }
1863
1864    impl From<bincode::Error> for ContractError {
1865        fn from(value: bincode::Error) -> Self {
1866            ContractError::Deser(format!("{value}"))
1867        }
1868    }
1869
1870    pub fn inner_validate_state<T>(
1871        parameters: Parameters<'static>,
1872        state: State<'static>,
1873        related: RelatedContracts<'static>,
1874    ) -> Result<ValidateResult, ContractError>
1875    where
1876        T: EncodingAdapter + TypedContract,
1877        ContractError: From<
1878            <<T as EncodingAdapter>::ParametersEncoder as Encoder<
1879                <T as EncodingAdapter>::Parameters,
1880            >>::Error,
1881        >,
1882        ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
1883    {
1884        let typed_params =
1885            <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
1886        let typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
1887        let related_container = RelatedContractsContainer::from(related);
1888        typed_state.verify(typed_params, related_container)
1889    }
1890
1891    pub fn inner_update_state<T>(
1892        parameters: Parameters<'static>,
1893        state: State<'static>,
1894        data: Vec<UpdateData<'static>>,
1895    ) -> Result<UpdateModification<'static>, ContractError>
1896    where
1897        T: EncodingAdapter + TypedContract,
1898        ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
1899        ContractError: From<
1900            <<T as EncodingAdapter>::ParametersEncoder as Encoder<
1901                <T as EncodingAdapter>::Parameters,
1902            >>::Error,
1903        >,
1904        ContractError: From<
1905            <<T as EncodingAdapter>::DeltaEncoder as Encoder<<T as EncodingAdapter>::Delta>>::Error,
1906        >,
1907    {
1908        let typed_params =
1909            <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
1910        let mut typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
1911        let self_updates = UpdateData::get_self_states(&data);
1912        let related_container = RelatedContractsContainer::from(data);
1913        for (state, delta) in self_updates {
1914            let state = state
1915                .map(|s| <<T as EncodingAdapter>::SelfEncoder>::deserialize(s.as_ref()))
1916                .transpose()?;
1917            let delta = delta
1918                .map(|d| <<T as EncodingAdapter>::DeltaEncoder>::deserialize(d.as_ref()))
1919                .transpose()?;
1920            let typed_update = TypedUpdateData::try_from((state, delta))?;
1921            match typed_state.merge(&typed_params, typed_update, &related_container) {
1922                MergeResult::Success => {}
1923                MergeResult::RequestRelated(req) => {
1924                    return UpdateModification::requires(req.into());
1925                }
1926                MergeResult::Error(err) => return Err(err),
1927            }
1928        }
1929        let encoded = <<T as EncodingAdapter>::SelfEncoder>::serialize(&typed_state)?;
1930        Ok(UpdateModification::valid(encoded.into()))
1931    }
1932
1933    pub fn inner_summarize_state<T>(
1934        parameters: Parameters<'static>,
1935        state: State<'static>,
1936    ) -> Result<StateSummary<'static>, ContractError>
1937    where
1938        T: EncodingAdapter + TypedContract,
1939        ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
1940        ContractError: From<
1941            <<T as EncodingAdapter>::ParametersEncoder as Encoder<
1942                <T as EncodingAdapter>::Parameters,
1943            >>::Error,
1944        >,
1945        ContractError:
1946            From<
1947                <<T as EncodingAdapter>::SummaryEncoder as Encoder<
1948                    <T as EncodingAdapter>::Summary,
1949                >>::Error,
1950            >,
1951    {
1952        let typed_params =
1953            <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
1954        let typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
1955        let summary = typed_state.summarize(typed_params)?;
1956        let encoded = <<T as EncodingAdapter>::SummaryEncoder>::serialize(&summary)?;
1957        Ok(encoded.into())
1958    }
1959
1960    pub fn inner_state_delta<T>(
1961        parameters: Parameters<'static>,
1962        state: State<'static>,
1963        summary: StateSummary<'static>,
1964    ) -> Result<StateDelta<'static>, ContractError>
1965    where
1966        T: EncodingAdapter + TypedContract,
1967        ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
1968        ContractError: From<
1969            <<T as EncodingAdapter>::ParametersEncoder as Encoder<
1970                <T as EncodingAdapter>::Parameters,
1971            >>::Error,
1972        >,
1973        ContractError:
1974            From<
1975                <<T as EncodingAdapter>::SummaryEncoder as Encoder<
1976                    <T as EncodingAdapter>::Summary,
1977                >>::Error,
1978            >,
1979        ContractError: From<
1980            <<T as EncodingAdapter>::DeltaEncoder as Encoder<<T as EncodingAdapter>::Delta>>::Error,
1981        >,
1982    {
1983        let typed_params =
1984            <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
1985        let typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
1986        let typed_summary =
1987            <<T as EncodingAdapter>::SummaryEncoder>::deserialize(summary.as_ref())?;
1988        let summary = typed_state.delta(typed_params, typed_summary)?;
1989        let encoded = <<T as EncodingAdapter>::DeltaEncoder>::serialize(&summary)?;
1990        Ok(encoded.into())
1991    }
1992}