1use alloc::{borrow::Cow, boxed::Box, string::String, vec::Vec};
21use core::fmt::{Debug, Display};
22
23pub use sp_externalities::{Externalities, ExternalitiesExt};
24
25#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd)]
30pub enum CallContext {
31 Offchain,
33 Onchain {
35 import: bool,
37 },
38}
39
40pub trait CodeExecutor: Sized + Send + Sync + ReadRuntimeVersion + Clone + 'static {
42 type Error: Display + Debug + Send + Sync + 'static;
44
45 fn call(
50 &self,
51 ext: &mut dyn Externalities,
52 runtime_code: &RuntimeCode,
53 method: &str,
54 data: &[u8],
55 context: CallContext,
56 ) -> (Result<Vec<u8>, Self::Error>, bool);
57}
58
59pub trait FetchRuntimeCode {
61 fn fetch_runtime_code(&self) -> Option<Cow<'_, [u8]>>;
65}
66
67pub struct WrappedRuntimeCode<'a>(pub Cow<'a, [u8]>);
69
70impl<'a> FetchRuntimeCode for WrappedRuntimeCode<'a> {
71 fn fetch_runtime_code(&self) -> Option<Cow<'_, [u8]>> {
72 Some(self.0.as_ref().into())
73 }
74}
75
76pub struct NoneFetchRuntimeCode;
78
79impl FetchRuntimeCode for NoneFetchRuntimeCode {
80 fn fetch_runtime_code(&self) -> Option<Cow<'_, [u8]>> {
81 None
82 }
83}
84
85#[derive(Clone)]
87pub struct RuntimeCode<'a> {
88 pub code_fetcher: &'a dyn FetchRuntimeCode,
90 pub heap_pages: Option<u64>,
94 pub hash: Vec<u8>,
99}
100
101impl<'a> PartialEq for RuntimeCode<'a> {
102 fn eq(&self, other: &Self) -> bool {
103 self.hash == other.hash
104 }
105}
106
107impl<'a> RuntimeCode<'a> {
108 pub fn empty() -> Self {
112 Self { code_fetcher: &NoneFetchRuntimeCode, hash: Vec::new(), heap_pages: None }
113 }
114}
115
116impl<'a> FetchRuntimeCode for RuntimeCode<'a> {
117 fn fetch_runtime_code(&self) -> Option<Cow<'_, [u8]>> {
118 self.code_fetcher.fetch_runtime_code()
119 }
120}
121
122#[derive(Debug)]
124pub struct CodeNotFound;
125
126impl core::fmt::Display for CodeNotFound {
127 fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
128 write!(f, "the storage entry `:code` doesn't have any code")
129 }
130}
131
132pub trait ReadRuntimeVersion: Send + Sync {
134 fn read_runtime_version(
154 &self,
155 wasm_code: &[u8],
156 ext: &mut dyn Externalities,
157 ) -> Result<Vec<u8>, String>;
158}
159
160impl ReadRuntimeVersion for alloc::sync::Arc<dyn ReadRuntimeVersion> {
161 fn read_runtime_version(
162 &self,
163 wasm_code: &[u8],
164 ext: &mut dyn Externalities,
165 ) -> Result<Vec<u8>, String> {
166 (**self).read_runtime_version(wasm_code, ext)
167 }
168}
169
170sp_externalities::decl_extension! {
171 pub struct ReadRuntimeVersionExt(Box<dyn ReadRuntimeVersion>);
173}
174
175impl ReadRuntimeVersionExt {
176 pub fn new<T: ReadRuntimeVersion + 'static>(inner: T) -> Self {
178 Self(Box::new(inner))
179 }
180}
181
182pub trait SpawnNamed: dyn_clone::DynClone + Send + Sync {
185 fn spawn_blocking(
189 &self,
190 name: &'static str,
191 group: Option<&'static str>,
192 future: futures::future::BoxFuture<'static, ()>,
193 );
194 fn spawn(
198 &self,
199 name: &'static str,
200 group: Option<&'static str>,
201 future: futures::future::BoxFuture<'static, ()>,
202 );
203}
204
205dyn_clone::clone_trait_object!(SpawnNamed);
206
207impl SpawnNamed for Box<dyn SpawnNamed> {
208 fn spawn_blocking(
209 &self,
210 name: &'static str,
211 group: Option<&'static str>,
212 future: futures::future::BoxFuture<'static, ()>,
213 ) {
214 (**self).spawn_blocking(name, group, future)
215 }
216 fn spawn(
217 &self,
218 name: &'static str,
219 group: Option<&'static str>,
220 future: futures::future::BoxFuture<'static, ()>,
221 ) {
222 (**self).spawn(name, group, future)
223 }
224}
225
226pub trait SpawnEssentialNamed: dyn_clone::DynClone + Send + Sync {
231 fn spawn_essential_blocking(
235 &self,
236 name: &'static str,
237 group: Option<&'static str>,
238 future: futures::future::BoxFuture<'static, ()>,
239 );
240 fn spawn_essential(
244 &self,
245 name: &'static str,
246 group: Option<&'static str>,
247 future: futures::future::BoxFuture<'static, ()>,
248 );
249}
250
251dyn_clone::clone_trait_object!(SpawnEssentialNamed);
252
253impl SpawnEssentialNamed for Box<dyn SpawnEssentialNamed> {
254 fn spawn_essential_blocking(
255 &self,
256 name: &'static str,
257 group: Option<&'static str>,
258 future: futures::future::BoxFuture<'static, ()>,
259 ) {
260 (**self).spawn_essential_blocking(name, group, future)
261 }
262
263 fn spawn_essential(
264 &self,
265 name: &'static str,
266 group: Option<&'static str>,
267 future: futures::future::BoxFuture<'static, ()>,
268 ) {
269 (**self).spawn_essential(name, group, future)
270 }
271}