Skip to main content

anvil_polkadot/substrate_node/service/
executor.rs

1use crate::substrate_node::{
2    host::{PublicKeyToHashOverride, SenderAddressRecoveryOverride},
3    service::{Backend, backend::StorageOverrides},
4};
5use parking_lot::Mutex;
6use polkadot_sdk::{
7    parachains_common::{Hash, opaque::Block},
8    sc_client_api::{Backend as _, CallExecutor, execution_extensions::ExecutionExtensions},
9    sc_executor::{self, RuntimeVersion, RuntimeVersionOf},
10    sc_service,
11    sp_api::{CallContext, ProofRecorder},
12    sp_blockchain::{self, HeaderBackend},
13    sp_core, sp_externalities, sp_io,
14    sp_runtime::{generic::BlockId, traits::HashingFor},
15    sp_state_machine::{OverlayedChanges, StorageProof},
16    sp_storage::ChildInfo,
17    sp_version,
18    sp_wasm_interface::ExtendedHostFunctions,
19};
20use std::{cell::RefCell, sync::Arc};
21
22/// Wasm executor which overrides the signature checking host functions for impersonation.
23pub type WasmExecutor = sc_executor::WasmExecutor<
24    ExtendedHostFunctions<
25        ExtendedHostFunctions<sp_io::SubstrateHostFunctions, SenderAddressRecoveryOverride>,
26        PublicKeyToHashOverride,
27    >,
28>;
29
30type InnerLocalCallExecutor = sc_service::client::LocalCallExecutor<Block, Backend, WasmExecutor>;
31
32#[derive(Clone)]
33/// State-injecting executor implementation.
34pub struct Executor {
35    inner: InnerLocalCallExecutor,
36    storage_overrides: Arc<Mutex<StorageOverrides>>,
37    backend: Arc<Backend>,
38}
39
40impl Executor {
41    pub fn new(
42        inner: InnerLocalCallExecutor,
43        storage_overrides: Arc<Mutex<StorageOverrides>>,
44        backend: Arc<Backend>,
45    ) -> Self {
46        Self { inner, storage_overrides, backend }
47    }
48
49    fn apply_overrides(&self, hash: &Hash, overlay: &mut OverlayedChanges<HashingFor<Block>>) {
50        let overrides = { self.storage_overrides.lock().get(hash) };
51        let Some(overrides) = overrides else { return };
52
53        for (key, val) in overrides.top {
54            overlay.set_storage(key, val);
55        }
56
57        for (child_key, child_map) in overrides.children {
58            let child_info = ChildInfo::new_default_from_vec(child_key);
59
60            for (key, val) in child_map {
61                overlay.set_child_storage(&child_info, key, val);
62            }
63        }
64    }
65}
66
67impl CallExecutor<Block> for Executor {
68    type Error = <InnerLocalCallExecutor as CallExecutor<Block>>::Error;
69
70    type Backend = Backend;
71
72    fn execution_extensions(&self) -> &ExecutionExtensions<Block> {
73        self.inner.execution_extensions()
74    }
75
76    fn call(
77        &self,
78        at_hash: Hash,
79        method: &str,
80        call_data: &[u8],
81        context: CallContext,
82    ) -> sp_blockchain::Result<Vec<u8>> {
83        let at_number =
84            self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(at_hash))?;
85        let extensions = self.execution_extensions().extensions(at_hash, at_number);
86
87        let mut changes = OverlayedChanges::default();
88
89        self.apply_overrides(&at_hash, &mut changes);
90
91        self.contextual_call(
92            at_hash,
93            method,
94            call_data,
95            &RefCell::new(changes),
96            &None,
97            context,
98            &RefCell::new(extensions),
99        )
100    }
101
102    fn contextual_call(
103        &self,
104        at_hash: Hash,
105        method: &str,
106        call_data: &[u8],
107        changes: &RefCell<OverlayedChanges<HashingFor<Block>>>,
108        recorder: &Option<ProofRecorder<Block>>,
109        call_context: CallContext,
110        extensions: &RefCell<sp_externalities::Extensions>,
111    ) -> Result<Vec<u8>, sp_blockchain::Error> {
112        let apply_overrides = (method == "Core_initialize_block"
113            && call_context == CallContext::Onchain)
114            || call_context == CallContext::Offchain;
115
116        if apply_overrides {
117            self.apply_overrides(&at_hash, &mut changes.borrow_mut());
118        }
119
120        self.inner.contextual_call(
121            at_hash,
122            method,
123            call_data,
124            changes,
125            recorder,
126            call_context,
127            extensions,
128        )
129    }
130
131    fn runtime_version(&self, at_hash: Hash) -> sp_blockchain::Result<RuntimeVersion> {
132        CallExecutor::runtime_version(&self.inner, at_hash)
133    }
134
135    fn prove_execution(
136        &self,
137        at_hash: Hash,
138        method: &str,
139        call_data: &[u8],
140    ) -> sp_blockchain::Result<(Vec<u8>, StorageProof)> {
141        self.inner.prove_execution(at_hash, method, call_data)
142    }
143}
144
145impl RuntimeVersionOf for Executor {
146    fn runtime_version(
147        &self,
148        ext: &mut dyn sp_externalities::Externalities,
149        runtime_code: &sp_core::traits::RuntimeCode<'_>,
150    ) -> Result<sp_version::RuntimeVersion, sc_executor::error::Error> {
151        RuntimeVersionOf::runtime_version(&self.inner, ext, runtime_code)
152    }
153}