1use super::{code_provider::CodeProvider, ClientConfig};
20use sc_client_api::{
21 backend, call_executor::CallExecutor, execution_extensions::ExecutionExtensions, HeaderBackend,
22};
23use sc_executor::{RuntimeVersion, RuntimeVersionOf};
24use sp_api::ProofRecorder;
25use sp_core::traits::{CallContext, CodeExecutor};
26use sp_externalities::Extensions;
27use sp_runtime::{
28 generic::BlockId,
29 traits::{Block as BlockT, HashingFor},
30};
31use sp_state_machine::{backend::AsTrieBackend, OverlayedChanges, StateMachine, StorageProof};
32use std::{cell::RefCell, sync::Arc};
33
34pub struct LocalCallExecutor<Block: BlockT, B, E> {
37 backend: Arc<B>,
38 executor: E,
39 code_provider: CodeProvider<Block, B, E>,
40 execution_extensions: Arc<ExecutionExtensions<Block>>,
41}
42
43impl<Block: BlockT, B, E> LocalCallExecutor<Block, B, E>
44where
45 E: CodeExecutor + RuntimeVersionOf + Clone + 'static,
46 B: backend::Backend<Block>,
47{
48 pub fn new(
50 backend: Arc<B>,
51 executor: E,
52 client_config: ClientConfig<Block>,
53 execution_extensions: ExecutionExtensions<Block>,
54 ) -> sp_blockchain::Result<Self> {
55 let code_provider = CodeProvider::new(&client_config, executor.clone(), backend.clone())?;
56
57 Ok(LocalCallExecutor {
58 backend,
59 executor,
60 code_provider,
61 execution_extensions: Arc::new(execution_extensions),
62 })
63 }
64}
65
66impl<Block: BlockT, B, E> Clone for LocalCallExecutor<Block, B, E>
67where
68 E: Clone,
69{
70 fn clone(&self) -> Self {
71 LocalCallExecutor {
72 backend: self.backend.clone(),
73 executor: self.executor.clone(),
74 code_provider: self.code_provider.clone(),
75 execution_extensions: self.execution_extensions.clone(),
76 }
77 }
78}
79
80impl<B, E, Block> CallExecutor<Block> for LocalCallExecutor<Block, B, E>
81where
82 B: backend::Backend<Block>,
83 E: CodeExecutor + RuntimeVersionOf + Clone + 'static,
84 Block: BlockT,
85{
86 type Error = E::Error;
87
88 type Backend = B;
89
90 fn execution_extensions(&self) -> &ExecutionExtensions<Block> {
91 &self.execution_extensions
92 }
93
94 fn call(
95 &self,
96 at_hash: Block::Hash,
97 method: &str,
98 call_data: &[u8],
99 context: CallContext,
100 ) -> sp_blockchain::Result<Vec<u8>> {
101 let mut changes = OverlayedChanges::default();
102 let at_number =
103 self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(at_hash))?;
104 let state = self.backend.state_at(at_hash)?;
105
106 let state_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&state);
107 let runtime_code =
108 state_runtime_code.runtime_code().map_err(sp_blockchain::Error::RuntimeCode)?;
109
110 let runtime_code = self.code_provider.maybe_override_code(runtime_code, &state, at_hash)?.0;
111
112 let mut extensions = self.execution_extensions.extensions(at_hash, at_number);
113
114 let mut sm = StateMachine::new(
115 &state,
116 &mut changes,
117 &self.executor,
118 method,
119 call_data,
120 &mut extensions,
121 &runtime_code,
122 context,
123 )
124 .set_parent_hash(at_hash);
125
126 sm.execute().map_err(Into::into)
127 }
128
129 fn contextual_call(
130 &self,
131 at_hash: Block::Hash,
132 method: &str,
133 call_data: &[u8],
134 changes: &RefCell<OverlayedChanges<HashingFor<Block>>>,
135 recorder: &Option<ProofRecorder<Block>>,
136 call_context: CallContext,
137 extensions: &RefCell<Extensions>,
138 ) -> Result<Vec<u8>, sp_blockchain::Error> {
139 let state = self.backend.state_at(at_hash)?;
140
141 let changes = &mut *changes.borrow_mut();
142
143 let state_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&state);
147
148 let runtime_code =
149 state_runtime_code.runtime_code().map_err(sp_blockchain::Error::RuntimeCode)?;
150 let runtime_code = self.code_provider.maybe_override_code(runtime_code, &state, at_hash)?.0;
151 let mut extensions = extensions.borrow_mut();
152
153 match recorder {
154 Some(recorder) => {
155 let trie_state = state.as_trie_backend();
156
157 let backend = sp_state_machine::TrieBackendBuilder::wrap(&trie_state)
158 .with_recorder(recorder.clone())
159 .build();
160
161 let mut state_machine = StateMachine::new(
162 &backend,
163 changes,
164 &self.executor,
165 method,
166 call_data,
167 &mut extensions,
168 &runtime_code,
169 call_context,
170 )
171 .set_parent_hash(at_hash);
172 state_machine.execute()
173 },
174 None => {
175 let mut state_machine = StateMachine::new(
176 &state,
177 changes,
178 &self.executor,
179 method,
180 call_data,
181 &mut extensions,
182 &runtime_code,
183 call_context,
184 )
185 .set_parent_hash(at_hash);
186 state_machine.execute()
187 },
188 }
189 .map_err(Into::into)
190 }
191
192 fn runtime_version(&self, at_hash: Block::Hash) -> sp_blockchain::Result<RuntimeVersion> {
193 let state = self.backend.state_at(at_hash)?;
194 let state_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&state);
195
196 let runtime_code =
197 state_runtime_code.runtime_code().map_err(sp_blockchain::Error::RuntimeCode)?;
198 self.code_provider
199 .maybe_override_code(runtime_code, &state, at_hash)
200 .map(|(_, v)| v)
201 }
202
203 fn prove_execution(
204 &self,
205 at_hash: Block::Hash,
206 method: &str,
207 call_data: &[u8],
208 ) -> sp_blockchain::Result<(Vec<u8>, StorageProof)> {
209 let at_number =
210 self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(at_hash))?;
211 let state = self.backend.state_at(at_hash)?;
212
213 let trie_backend = state.as_trie_backend();
214
215 let state_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(trie_backend);
216 let runtime_code =
217 state_runtime_code.runtime_code().map_err(sp_blockchain::Error::RuntimeCode)?;
218 let runtime_code = self.code_provider.maybe_override_code(runtime_code, &state, at_hash)?.0;
219
220 sp_state_machine::prove_execution_on_trie_backend(
221 trie_backend,
222 &mut Default::default(),
223 &self.executor,
224 method,
225 call_data,
226 &runtime_code,
227 &mut self.execution_extensions.extensions(at_hash, at_number),
228 )
229 .map_err(Into::into)
230 }
231}
232
233impl<B, E, Block> RuntimeVersionOf for LocalCallExecutor<Block, B, E>
234where
235 E: RuntimeVersionOf,
236 Block: BlockT,
237{
238 fn runtime_version(
239 &self,
240 ext: &mut dyn sp_externalities::Externalities,
241 runtime_code: &sp_core::traits::RuntimeCode,
242 ) -> Result<sp_version::RuntimeVersion, sc_executor::error::Error> {
243 RuntimeVersionOf::runtime_version(&self.executor, ext, runtime_code)
244 }
245}
246
247impl<Block, B, E> sp_version::GetRuntimeVersionAt<Block> for LocalCallExecutor<Block, B, E>
248where
249 B: backend::Backend<Block>,
250 E: CodeExecutor + RuntimeVersionOf + Clone + 'static,
251 Block: BlockT,
252{
253 fn runtime_version(&self, at: Block::Hash) -> Result<sp_version::RuntimeVersion, String> {
254 CallExecutor::runtime_version(self, at).map_err(|e| e.to_string())
255 }
256}
257
258impl<Block, B, E> sp_version::GetNativeVersion for LocalCallExecutor<Block, B, E>
259where
260 B: backend::Backend<Block>,
261 E: CodeExecutor + sp_version::GetNativeVersion + Clone + 'static,
262 Block: BlockT,
263{
264 fn native_version(&self) -> &sp_version::NativeVersion {
265 self.executor.native_version()
266 }
267}