freenet_stdlib/
memory.rs

1//! Internally used functionality to interact between WASM and the host environment.
2//! Most of the usage of types is unsafe and requires knowledge on how
3//! the WASM runtime is set and used. Use with caution.
4//!
5//! End users should be using higher levels of abstraction to write contracts
6//! and shouldn't need to manipulate functions and types in this module directly.
7//! Use with caution.
8
9pub mod buf;
10
11#[non_exhaustive]
12#[derive(Debug, Clone, Copy)]
13pub struct WasmLinearMem {
14    pub start_ptr: *const u8,
15    pub size: u64,
16}
17
18impl WasmLinearMem {
19    /// # Safety
20    /// Ensure that the passed pointer is a valid pointer to the start of
21    /// the WASM linear memory
22    pub unsafe fn new(start_ptr: *const u8, size: u64) -> Self {
23        Self { start_ptr, size }
24    }
25}
26
27#[cfg(feature = "contract")]
28pub mod wasm_interface {
29    use crate::prelude::*;
30
31    fn set_logger() -> Result<(), ContractInterfaceResult> {
32        #[cfg(feature = "trace")]
33        {
34            use crate::prelude::*;
35            use tracing_subscriber as tra;
36            if let Err(err) = tra::fmt()
37                .with_env_filter("warn,freenet_stdlib=trace")
38                .try_init()
39            {
40                return Err(ContractInterfaceResult::from(Err::<ValidateResult, _>(
41                    ContractError::Other(format!("{}", err)),
42                )));
43            }
44        }
45        Ok(())
46    }
47
48    pub fn inner_validate_state<T: ContractInterface>(
49        parameters: i64,
50        state: i64,
51        related: i64,
52    ) -> i64 {
53        if let Err(e) = set_logger().map_err(|e| e.into_raw()) {
54            return e;
55        }
56        let parameters = unsafe {
57            let param_buf = &*(parameters as *const super::buf::BufferBuilder);
58            let bytes =
59                &*std::ptr::slice_from_raw_parts(param_buf.start(), param_buf.bytes_written());
60            Parameters::from(bytes)
61        };
62        let state = unsafe {
63            let state_buf = &*(state as *const super::buf::BufferBuilder);
64            let bytes =
65                &*std::ptr::slice_from_raw_parts(state_buf.start(), state_buf.bytes_written());
66            State::from(bytes)
67        };
68        let related: RelatedContracts = unsafe {
69            let related = &*(related as *const super::buf::BufferBuilder);
70            let bytes = &*std::ptr::slice_from_raw_parts(related.start(), related.bytes_written());
71            match bincode::deserialize(bytes) {
72                Ok(v) => v,
73                Err(err) => {
74                    return ContractInterfaceResult::from(Err::<::core::primitive::bool, _>(
75                        ContractError::Deser(format!("{}", err)),
76                    ))
77                    .into_raw()
78                }
79            }
80        };
81        let result = <T as ContractInterface>::validate_state(parameters, state, related);
82        ContractInterfaceResult::from(result).into_raw()
83    }
84
85    pub fn inner_update_state<T: ContractInterface>(
86        parameters: i64,
87        state: i64,
88        updates: i64,
89    ) -> i64 {
90        if let Err(e) = set_logger().map_err(|e| e.into_raw()) {
91            return e;
92        }
93        let parameters = unsafe {
94            let param_buf = &mut *(parameters as *mut super::buf::BufferBuilder);
95            let bytes =
96                &*std::ptr::slice_from_raw_parts(param_buf.start(), param_buf.bytes_written());
97            Parameters::from(bytes)
98        };
99        let state = unsafe {
100            let state_buf = &mut *(state as *mut super::buf::BufferBuilder);
101            let bytes =
102                &*std::ptr::slice_from_raw_parts(state_buf.start(), state_buf.bytes_written());
103            State::from(bytes)
104        };
105        let updates = unsafe {
106            let updates = &mut *(updates as *mut super::buf::BufferBuilder);
107            let bytes = &*std::ptr::slice_from_raw_parts(updates.start(), updates.bytes_written());
108            match bincode::deserialize(bytes) {
109                Ok(v) => v,
110                Err(err) => {
111                    return ContractInterfaceResult::from(Err::<ValidateResult, _>(
112                        ContractError::Deser(format!("{}", err)),
113                    ))
114                    .into_raw()
115                }
116            }
117        };
118        let result = <T as ContractInterface>::update_state(parameters, state, updates);
119        ContractInterfaceResult::from(result).into_raw()
120    }
121
122    pub fn inner_summarize_state<T: ContractInterface>(parameters: i64, state: i64) -> i64 {
123        if let Err(e) = set_logger().map_err(|e| e.into_raw()) {
124            return e;
125        }
126        let parameters = unsafe {
127            let param_buf = &mut *(parameters as *mut super::buf::BufferBuilder);
128            let bytes =
129                &*std::ptr::slice_from_raw_parts(param_buf.start(), param_buf.bytes_written());
130            Parameters::from(bytes)
131        };
132        let state = unsafe {
133            let state_buf = &mut *(state as *mut super::buf::BufferBuilder);
134            let bytes =
135                &*std::ptr::slice_from_raw_parts(state_buf.start(), state_buf.bytes_written());
136            State::from(bytes)
137        };
138        let summary = <T as ContractInterface>::summarize_state(parameters, state);
139        ContractInterfaceResult::from(summary).into_raw()
140    }
141
142    pub fn inner_get_state_delta<T: ContractInterface>(
143        parameters: i64,
144        state: i64,
145        summary: i64,
146    ) -> i64 {
147        if let Err(e) = set_logger().map_err(|e| e.into_raw()) {
148            return e;
149        }
150        let parameters = unsafe {
151            let param_buf = &mut *(parameters as *mut super::buf::BufferBuilder);
152            let bytes =
153                &*std::ptr::slice_from_raw_parts(param_buf.start(), param_buf.bytes_written());
154            Parameters::from(bytes)
155        };
156        let state = unsafe {
157            let state_buf = &mut *(state as *mut super::buf::BufferBuilder);
158            let bytes =
159                &*std::ptr::slice_from_raw_parts(state_buf.start(), state_buf.bytes_written());
160            State::from(bytes)
161        };
162        let summary = unsafe {
163            let summary_buf = &mut *(summary as *mut super::buf::BufferBuilder);
164            let bytes =
165                &*std::ptr::slice_from_raw_parts(summary_buf.start(), summary_buf.bytes_written());
166            StateSummary::from(bytes)
167        };
168        let new_delta = <T as ContractInterface>::get_state_delta(parameters, state, summary);
169        ContractInterfaceResult::from(new_delta).into_raw()
170    }
171}