sc_service/client/
call_executor.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19use 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
34/// Call executor that executes methods locally, querying all required
35/// data from local backend.
36pub 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	/// Creates new instance of local call executor.
49	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		// It is important to extract the runtime code here before we create the proof
144		// recorder to not record it. We also need to fetch the runtime code from `state` to
145		// make sure we use the caching layers.
146		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}