1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Copyright 2024 Moonbeam foundation
// This file is part of Moonbeam.

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

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

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

use sc_client_api::execution_extensions::ExecutionExtensions;
use sc_executor::{RuntimeVersion, RuntimeVersionOf};
use sp_api::ProofRecorder;
use sp_core::traits::{CallContext, Externalities};
use sp_runtime::traits::{Block as BlockT, HashingFor};
use sp_state_machine::{OverlayedChanges, StorageProof};
use std::cell::RefCell;
use std::marker::PhantomData;

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

impl<Block: BlockT, Executor> LazyLoadingCallExecutor<Block, Executor>
where
	Executor: sc_client_api::CallExecutor<Block> + Clone + 'static,
{
	/// Creates new instance of local call executor.
	pub fn new(executor: Executor) -> sp_blockchain::Result<Self> {
		Ok(LazyLoadingCallExecutor {
			inner: executor,
			_phantom_data: Default::default(),
		})
	}
}

impl<Block, Executor> sc_client_api::CallExecutor<Block>
	for LazyLoadingCallExecutor<Block, Executor>
where
	Executor: sc_client_api::CallExecutor<Block>,
	Block: BlockT,
{
	type Error = Executor::Error;

	type Backend = Executor::Backend;

	fn execution_extensions(&self) -> &ExecutionExtensions<Block> {
		&self.inner.execution_extensions()
	}

	fn call(
		&self,
		at_hash: Block::Hash,
		method: &str,
		call_data: &[u8],
		context: CallContext,
	) -> sp_blockchain::Result<Vec<u8>> {
		self.inner.call(at_hash, method, call_data, context)
	}

	fn contextual_call(
		&self,
		at_hash: Block::Hash,
		method: &str,
		call_data: &[u8],
		changes: &RefCell<OverlayedChanges<HashingFor<Block>>>,
		// not used in lazy loading
		_recorder: &Option<ProofRecorder<Block>>,
		call_context: CallContext,
		extensions: &RefCell<sp_externalities::Extensions>,
	) -> Result<Vec<u8>, sp_blockchain::Error> {
		self.inner.contextual_call(
			at_hash,
			method,
			call_data,
			changes,
			&None,
			call_context,
			extensions,
		)
	}

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

	fn prove_execution(
		&self,
		at_hash: Block::Hash,
		method: &str,
		call_data: &[u8],
	) -> sp_blockchain::Result<(Vec<u8>, StorageProof)> {
		self.inner.prove_execution(at_hash, method, call_data)
	}
}

impl<Block, Executor> RuntimeVersionOf for LazyLoadingCallExecutor<Block, Executor>
where
	Executor: RuntimeVersionOf,
	Block: BlockT,
{
	fn runtime_version(
		&self,
		ext: &mut dyn Externalities,
		runtime_code: &sp_core::traits::RuntimeCode,
	) -> Result<RuntimeVersion, sc_executor::error::Error> {
		self.inner.runtime_version(ext, runtime_code)
	}
}