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