1
// Copyright 2024 Moonbeam foundation
2
// This file is part of Moonbeam.
3

            
4
// Moonbeam is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Moonbeam is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Moonbeam.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
use sc_client_api::execution_extensions::ExecutionExtensions;
18
use sc_executor::{RuntimeVersion, RuntimeVersionOf};
19
use sp_api::ProofRecorder;
20
use sp_core::traits::{CallContext, Externalities};
21
use sp_runtime::traits::{Block as BlockT, HashingFor};
22
use sp_state_machine::{OverlayedChanges, StorageProof};
23
use std::cell::RefCell;
24
use std::marker::PhantomData;
25

            
26
/// Call executor that executes methods locally, querying all required
27
/// data from local backend.
28
#[derive(Clone)]
29
pub struct LazyLoadingCallExecutor<Block, Executor> {
30
	inner: Executor,
31
	_phantom_data: PhantomData<Block>,
32
}
33

            
34
impl<Block: BlockT, Executor> LazyLoadingCallExecutor<Block, Executor>
35
where
36
	Executor: sc_client_api::CallExecutor<Block> + Clone + 'static,
37
{
38
	/// Creates new instance of local call executor.
39
	pub fn new(executor: Executor) -> sp_blockchain::Result<Self> {
40
		Ok(LazyLoadingCallExecutor {
41
			inner: executor,
42
			_phantom_data: Default::default(),
43
		})
44
	}
45
}
46

            
47
impl<Block, Executor> sc_client_api::CallExecutor<Block>
48
	for LazyLoadingCallExecutor<Block, Executor>
49
where
50
	Executor: sc_client_api::CallExecutor<Block>,
51
	Block: BlockT,
52
{
53
	type Error = Executor::Error;
54

            
55
	type Backend = Executor::Backend;
56

            
57
	fn execution_extensions(&self) -> &ExecutionExtensions<Block> {
58
		&self.inner.execution_extensions()
59
	}
60

            
61
	fn call(
62
		&self,
63
		at_hash: Block::Hash,
64
		method: &str,
65
		call_data: &[u8],
66
		context: CallContext,
67
	) -> sp_blockchain::Result<Vec<u8>> {
68
		self.inner.call(at_hash, method, call_data, context)
69
	}
70

            
71
	fn contextual_call(
72
		&self,
73
		at_hash: Block::Hash,
74
		method: &str,
75
		call_data: &[u8],
76
		changes: &RefCell<OverlayedChanges<HashingFor<Block>>>,
77
		// not used in lazy loading
78
		_recorder: &Option<ProofRecorder<Block>>,
79
		call_context: CallContext,
80
		extensions: &RefCell<sp_externalities::Extensions>,
81
	) -> Result<Vec<u8>, sp_blockchain::Error> {
82
		self.inner.contextual_call(
83
			at_hash,
84
			method,
85
			call_data,
86
			changes,
87
			&None,
88
			call_context,
89
			extensions,
90
		)
91
	}
92

            
93
	fn runtime_version(&self, at_hash: Block::Hash) -> sp_blockchain::Result<RuntimeVersion> {
94
		sc_client_api::CallExecutor::runtime_version(&self.inner, at_hash)
95
	}
96

            
97
	fn prove_execution(
98
		&self,
99
		at_hash: Block::Hash,
100
		method: &str,
101
		call_data: &[u8],
102
	) -> sp_blockchain::Result<(Vec<u8>, StorageProof)> {
103
		self.inner.prove_execution(at_hash, method, call_data)
104
	}
105
}
106

            
107
impl<Block, Executor> RuntimeVersionOf for LazyLoadingCallExecutor<Block, Executor>
108
where
109
	Executor: RuntimeVersionOf,
110
	Block: BlockT,
111
{
112
	fn runtime_version(
113
		&self,
114
		ext: &mut dyn Externalities,
115
		runtime_code: &sp_core::traits::RuntimeCode,
116
	) -> Result<RuntimeVersion, sc_executor::error::Error> {
117
		self.inner.runtime_version(ext, runtime_code)
118
	}
119
}