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}
36
37pub trait CodeExecutor: Sized + Send + Sync + ReadRuntimeVersion + Clone + 'static {
39 type Error: Display + Debug + Send + Sync + 'static;
41
42 fn call(
47 &self,
48 ext: &mut dyn Externalities,
49 runtime_code: &RuntimeCode,
50 method: &str,
51 data: &[u8],
52 context: CallContext,
53 ) -> (Result<Vec<u8>, Self::Error>, bool);
54}
55
56pub trait FetchRuntimeCode {
58 fn fetch_runtime_code(&self) -> Option<Cow<[u8]>>;
62}
63
64pub struct WrappedRuntimeCode<'a>(pub Cow<'a, [u8]>);
66
67impl<'a> FetchRuntimeCode for WrappedRuntimeCode<'a> {
68 fn fetch_runtime_code(&self) -> Option<Cow<[u8]>> {
69 Some(self.0.as_ref().into())
70 }
71}
72
73pub struct NoneFetchRuntimeCode;
75
76impl FetchRuntimeCode for NoneFetchRuntimeCode {
77 fn fetch_runtime_code(&self) -> Option<Cow<[u8]>> {
78 None
79 }
80}
81
82#[derive(Clone)]
84pub struct RuntimeCode<'a> {
85 pub code_fetcher: &'a dyn FetchRuntimeCode,
87 pub heap_pages: Option<u64>,
91 pub hash: Vec<u8>,
96}
97
98impl<'a> PartialEq for RuntimeCode<'a> {
99 fn eq(&self, other: &Self) -> bool {
100 self.hash == other.hash
101 }
102}
103
104impl<'a> RuntimeCode<'a> {
105 pub fn empty() -> Self {
109 Self { code_fetcher: &NoneFetchRuntimeCode, hash: Vec::new(), heap_pages: None }
110 }
111}
112
113impl<'a> FetchRuntimeCode for RuntimeCode<'a> {
114 fn fetch_runtime_code(&self) -> Option<Cow<[u8]>> {
115 self.code_fetcher.fetch_runtime_code()
116 }
117}
118
119#[derive(Debug)]
121pub struct CodeNotFound;
122
123impl core::fmt::Display for CodeNotFound {
124 fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
125 write!(f, "the storage entry `:code` doesn't have any code")
126 }
127}
128
129pub trait ReadRuntimeVersion: Send + Sync {
131 fn read_runtime_version(
151 &self,
152 wasm_code: &[u8],
153 ext: &mut dyn Externalities,
154 ) -> Result<Vec<u8>, String>;
155}
156
157impl ReadRuntimeVersion for alloc::sync::Arc<dyn ReadRuntimeVersion> {
158 fn read_runtime_version(
159 &self,
160 wasm_code: &[u8],
161 ext: &mut dyn Externalities,
162 ) -> Result<Vec<u8>, String> {
163 (**self).read_runtime_version(wasm_code, ext)
164 }
165}
166
167sp_externalities::decl_extension! {
168 pub struct ReadRuntimeVersionExt(Box<dyn ReadRuntimeVersion>);
170}
171
172impl ReadRuntimeVersionExt {
173 pub fn new<T: ReadRuntimeVersion + 'static>(inner: T) -> Self {
175 Self(Box::new(inner))
176 }
177}
178
179pub trait SpawnNamed: dyn_clone::DynClone + Send + Sync {
182 fn spawn_blocking(
186 &self,
187 name: &'static str,
188 group: Option<&'static str>,
189 future: futures::future::BoxFuture<'static, ()>,
190 );
191 fn spawn(
195 &self,
196 name: &'static str,
197 group: Option<&'static str>,
198 future: futures::future::BoxFuture<'static, ()>,
199 );
200}
201
202dyn_clone::clone_trait_object!(SpawnNamed);
203
204impl SpawnNamed for Box<dyn SpawnNamed> {
205 fn spawn_blocking(
206 &self,
207 name: &'static str,
208 group: Option<&'static str>,
209 future: futures::future::BoxFuture<'static, ()>,
210 ) {
211 (**self).spawn_blocking(name, group, future)
212 }
213 fn spawn(
214 &self,
215 name: &'static str,
216 group: Option<&'static str>,
217 future: futures::future::BoxFuture<'static, ()>,
218 ) {
219 (**self).spawn(name, group, future)
220 }
221}
222
223pub trait SpawnEssentialNamed: dyn_clone::DynClone + Send + Sync {
228 fn spawn_essential_blocking(
232 &self,
233 name: &'static str,
234 group: Option<&'static str>,
235 future: futures::future::BoxFuture<'static, ()>,
236 );
237 fn spawn_essential(
241 &self,
242 name: &'static str,
243 group: Option<&'static str>,
244 future: futures::future::BoxFuture<'static, ()>,
245 );
246}
247
248dyn_clone::clone_trait_object!(SpawnEssentialNamed);
249
250impl SpawnEssentialNamed for Box<dyn SpawnEssentialNamed> {
251 fn spawn_essential_blocking(
252 &self,
253 name: &'static str,
254 group: Option<&'static str>,
255 future: futures::future::BoxFuture<'static, ()>,
256 ) {
257 (**self).spawn_essential_blocking(name, group, future)
258 }
259
260 fn spawn_essential(
261 &self,
262 name: &'static str,
263 group: Option<&'static str>,
264 future: futures::future::BoxFuture<'static, ()>,
265 ) {
266 (**self).spawn_essential(name, group, future)
267 }
268}